Skip to content

Latest commit

 

History

History
2031 lines (1533 loc) · 69.4 KB

File metadata and controls

2031 lines (1533 loc) · 69.4 KB

webcodecs-py 対応状況

webcodecs-py は WebCodecs API を Python から扱うためのバインディングであり、リアルタイム処理向けに最適化しています。

  • 最終更新: 2026-01-26
  • 基準仕様: W3C WebCodecs
    • 日付: 2025-11-19
    • commit: 66a81b2

基本方針

webcodecs-py は WebCodecs API にできるだけ準拠しつつ、以下の方針で実装しています:

  1. Python エコシステムとの親和性: Python の命名規則やイディオムに従う
  2. リアルタイム用途の最適化: WebRTC、Media over QUIC でのリアルタイム処理を想定
  3. ndarray の活用: バッファの入出力に numpy.ndarray を前提とし、Python エコシステムとの連携を容易にする
  4. 型安全性: TypedDict による型ヒントで IDE サポートと型チェックを提供

実装ステータス概要

セクション 主な対象 Python 補足
辞書型インターフェース AudioDataInit / VideoFrameBufferInit / 各 Config 必須項目は実装済み hardware_acceleration は未対応
Video クラス VideoFrame / EncodedVideoChunk / VideoEncoder / VideoDecoder 全メソッド実装済み
Audio クラス AudioData / EncodedAudioChunk / AudioEncoder / AudioDecoder 全メソッド実装済み
補助型と列挙型 PlaneLayout / DOMRect / VideoColorSpace / CodecState など 必要項目を実装済み 列挙値の未実装分はテーブルで明記
独自拡張 HardwareAccelerationEngine / VideoFrame 拡張 / AudioData 拡張 / get_video_codec_capabilities() / H.264/H.265 ヘッダーパーサー planes() とハードウェアアクセラレーション、ヘッダーパーサー 仕様逸脱理由を各節で説明

WebCodecs API との主な差異

1. 命名規則

WebCodecs API の JavaScript camelCase から Python の snake_case に変換:

WebCodecs API (JavaScript) webcodecs-py (Python)
numberOfChannels number_of_channels
numberOfFrames number_of_frames
sampleRate sample_rate
encodeQueueSize encode_queue_size
decodeQueueSize decode_queue_size
byteLength byte_length
codedWidth coded_width
codedHeight coded_height
allocationSize allocation_size
isConfigSupported is_config_supported

2. イベントハンドリング

WebCodecs API (JavaScript)

encoder.addEventListener('dequeue', () => {
  // イベントハンドラ
});
encoder.ondequeue = () => {
  // イベントハンドラ
};

webcodecs-py (Python)

# コンストラクタでコールバックを指定
encoder = VideoEncoder(
    on_output=lambda chunk: ...,
    on_error=lambda error: ...
)
# dequeue イベントは後から設定可能
encoder.on_dequeue(lambda: ...)

理由: Python には JavaScript の EventTarget に相当する標準的なイベントシステムがないため、コールバック方式を採用しています。

3. 非同期処理

WebCodecs API (JavaScript)

await encoder.flush();  // Promise を返す
const support = await VideoEncoder.isConfigSupported(config);

webcodecs-py (Python)

# 現在は同期的に実行
encoder.flush()
# is_config_supported は同期的
support = VideoDecoder.is_config_supported(config)

理由: Python では同期的な処理を採用しています。

: WebCodecs 仕様に準拠した並列処理は実装済みです。encode() / decode() メソッドは即座に返り、実際の処理はバックグラウンドのワーカースレッドで実行されます。

4. コンストラクタ引数

WebCodecs API (JavaScript)

const encoder = new VideoEncoder({
  output: (chunk, metadata) => { ... },
  error: (error) => { ... }
});

webcodecs-py (Python)

# コールバックを直接コンストラクタに渡す
encoder = VideoEncoder(
    on_output=lambda chunk: ...,
    on_error=lambda error: ...
)
# または位置引数で
encoder = VideoEncoder(output_callback, error_callback)

理由: Python のシンプルさを重視し、コールバックは直接コンストラクタで指定する方式を採用しています。

5. TypedDict による設定辞書

WebCodecs API の辞書型インターフェースを TypedDict で実装:

from webcodecs import LatencyMode, VideoEncoder, VideoEncoderConfig

# TypedDict による型チェック
config: VideoEncoderConfig = {
    "codec": "av1",
    "width": 1920,
    "height": 1080,
    "bitrate": 1000000,
    "latency_mode": LatencyMode.REALTIME,
}

encoder = VideoEncoder(on_output, on_error)
encoder.configure(config)  # dict として渡す

利点:

  • IDE による補完と型チェック
  • 実行時は通常の dict として動作(パフォーマンスへの影響なし)
  • WebCodecs API の辞書型との互換性を維持

実装済み TypedDict:

Init 系:

  • AudioDataInit - AudioData コンストラクタ用
  • EncodedAudioChunkInit - EncodedAudioChunk コンストラクタ用
  • EncodedVideoChunkInit - EncodedVideoChunk コンストラクタ用
  • ImageDecoderInit - ImageDecoder コンストラクタ用
  • VideoFrameBufferInit - VideoFrame コンストラクタ用

Config 系:

  • AudioEncoderConfig - AudioEncoder.configure() 用
  • AudioDecoderConfig - AudioDecoder.configure() 用
  • VideoEncoderConfig - VideoEncoder.configure() 用
  • VideoDecoderConfig - VideoDecoder.configure() 用

コーデック固有設定系:

  • OpusEncoderConfig - AudioEncoderConfig.opus 用
  • FlacEncoderConfig - AudioEncoderConfig.flac 用
  • AvcEncoderConfig - VideoEncoderConfig.avc 用
  • HevcEncoderConfig - VideoEncoderConfig.hevc 用

Options 系:

  • AudioDataCopyToOptions - AudioData.copy_to() のオプション
  • ImageDecodeOptions - ImageDecoder.decode() のオプション
  • VideoEncoderEncodeOptions - VideoEncoder.encode() のオプション
  • VideoEncoderEncodeOptionsForAv1 - AV1 固有のエンコードオプション
  • VideoEncoderEncodeOptionsForAvc - AVC 固有のエンコードオプション
  • VideoEncoderEncodeOptionsForHevc - HEVC 固有のエンコードオプション
  • VideoEncoderEncodeOptionsForVp8 - VP8 固有のエンコードオプション
  • VideoEncoderEncodeOptionsForVp9 - VP9 固有のエンコードオプション
  • VideoFrameCopyToOptions - VideoFrame.copy_to() のオプション

Support 系 (is_config_supported() の戻り値):

  • AudioEncoderSupport - AudioEncoder.is_config_supported() 用
  • AudioDecoderSupport - AudioDecoder.is_config_supported() 用
  • VideoEncoderSupport - VideoEncoder.is_config_supported() 用
  • VideoDecoderSupport - VideoDecoder.is_config_supported() 用

Metadata 系 (出力コールバックで提供):

  • EncodedVideoChunkMetadata - VideoEncoder の output callback の第 2 引数
  • EncodedVideoChunkMetadataDecoderConfig - EncodedVideoChunkMetadata の decoder_config
  • SvcOutputMetadata - EncodedVideoChunkMetadata の svc (scalabilityMode 指定時のみ)

Result 系 (メソッドの戻り値):

  • ImageDecodeResult - ImageDecoder.decode() の戻り値

6. Promise の代替

  • JavaScript の Promise を返すメソッドは、Python では通常の同期メソッドとして実装
  • 非同期処理は内部的に処理

7. planes() メソッド

  • VideoFrame と AudioData の内部バッファへのビューを返す独自拡張
  • planes() メソッドはコピーなしで内部データにアクセス可能

8. copy_to() の実装

WebCodecs API の copyTo() 仕様に準拠した実装:

  • VideoFrame.copy_to(): destination バッファに書き込み、PlaneLayout のリストを返す
  • AudioData.copy_to(): destination バッファに書き込み、戻り値なし
  • EncodedVideoChunk.copy_to(): destination バッファに書き込み、戻り値なし
  • EncodedAudioChunk.copy_to(): destination バッファに書き込み、戻り値なし
import numpy as np
from webcodecs import AudioData, AudioSampleFormat

# 音声データを作成 (ステレオ、1024 フレーム、float32)
sample_rate = 48000
number_of_channels = 2
number_of_frames = 1024
data = np.zeros(number_of_frames * number_of_channels, dtype=np.float32)

init = {
    "format": AudioSampleFormat.F32,
    "sample_rate": sample_rate,
    "number_of_frames": number_of_frames,
    "number_of_channels": number_of_channels,
    "timestamp": 0,
    "data": data,
}
audio = AudioData(init)

# 指定したプレーンをコピー
options = {"plane_index": 0}
destination = np.zeros(audio.allocation_size(options), dtype=np.uint8)
audio.copy_to(destination, options)
import numpy as np
from webcodecs import VideoFrame, VideoPixelFormat

# 映像データを作成 (I420 フォーマット、640x480)
width = 640
height = 480
# I420: Y プレーン + U プレーン (1/4) + V プレーン (1/4)
data = np.zeros(width * height * 3 // 2, dtype=np.uint8)

init = {
    "format": VideoPixelFormat.I420,
    "coded_width": width,
    "coded_height": height,
    "timestamp": 0,
}
frame = VideoFrame(data, init)

# 全プレーンをコピー
destination = np.zeros(frame.allocation_size(), dtype=np.uint8)
layouts = frame.copy_to(destination)

# フォーマット変換してコピー(I420 → RGBA)
rgba_size = frame.allocation_size({"format": VideoPixelFormat.RGBA})
rgba_buffer = np.zeros(rgba_size, dtype=np.uint8)
frame.copy_to(rgba_buffer, {"format": VideoPixelFormat.RGBA})
import numpy as np
from webcodecs import EncodedVideoChunk, EncodedVideoChunkType

# エンコード済みデータ (実際にはエンコーダーから取得)
data = b"\x00" * 1000

chunk = EncodedVideoChunk({
    "type": EncodedVideoChunkType.KEY,
    "timestamp": 0,
    "data": data,
})

# エンコード済みデータをコピー
destination = np.zeros(chunk.byte_length, dtype=np.uint8)
chunk.copy_to(destination)

直接アクセス: 内部バッファに直接アクセスする場合は planes() メソッド(独自拡張)を使用してください。

基本的な利用例

AudioDecoder の例

from webcodecs import AudioDecoder, AudioDecoderConfig


def on_output(audio_data):
    print(f"デコード完了: {audio_data.number_of_frames} frames")


def on_error(error):
    print(f"エラー: {error}")


decoder = AudioDecoder(on_output, on_error)

config: AudioDecoderConfig = {
    "codec": "opus",
    "sample_rate": 48000,
    "number_of_channels": 2,
}
decoder.configure(config)

AudioEncoder の例 (Opus)

from webcodecs import AudioEncoder, AudioEncoderConfig


def on_output(chunk):
    print(f"エンコード完了: {chunk.byte_length} bytes")


def on_error(error):
    print(f"エラー: {error}")


encoder = AudioEncoder(on_output, on_error)

config: AudioEncoderConfig = {
    "codec": "opus",
    "sample_rate": 48000,
    "number_of_channels": 2,
    "bitrate": 64000,
}
encoder.configure(config)

AudioEncoder の例 (AAC - macOS のみ)

from webcodecs import AudioEncoder, AudioEncoderConfig


def on_output(chunk):
    print(f"エンコード完了: {chunk.byte_length} bytes")


def on_error(error):
    print(f"エラー: {error}")


encoder = AudioEncoder(on_output, on_error)

# コーデック名は "mp4a.40.2" または "aac" が使用可能
config: AudioEncoderConfig = {
    "codec": "mp4a.40.2",
    "sample_rate": 48000,
    "number_of_channels": 2,
    "bitrate": 128000,
}
encoder.configure(config)

VideoDecoder の例

from webcodecs import VideoDecoder, VideoDecoderConfig


def on_output(frame):
    print(f"デコード完了: {frame.coded_width}x{frame.coded_height}")


def on_error(error):
    print(f"エラー: {error}")


decoder = VideoDecoder(on_output, on_error)

config: VideoDecoderConfig = {
    "codec": "av01.0.08M.08",
    "coded_width": 1920,
    "coded_height": 1080,
}
decoder.configure(config)

VideoDecoder の例 (ハードウェアアクセラレーション)

from webcodecs import VideoDecoder, VideoDecoderConfig, HardwareAccelerationEngine


def on_output(frame):
    print(f"デコード完了: {frame.coded_width}x{frame.coded_height}")


def on_error(error):
    print(f"エラー: {error}")


decoder = VideoDecoder(on_output, on_error)

# Apple Video Toolbox を使用した H.264 デコード (macOS)
config: VideoDecoderConfig = {
    "codec": "avc1.42001f",
    "hardware_acceleration_engine": HardwareAccelerationEngine.APPLE_VIDEO_TOOLBOX,
}
decoder.configure(config)
# NVIDIA Video Codec SDK を使用した H.264 デコード (Ubuntu)
config: VideoDecoderConfig = {
    "codec": "avc1.42001f",
    "hardware_acceleration_engine": HardwareAccelerationEngine.NVIDIA_VIDEO_CODEC,
}
decoder.configure(config)
# Apple Video Toolbox を使用した VP9 デコード (macOS)
# デフォルトでは libvpx によるソフトウェアデコードが使用される
# VideoToolbox による高速なハードウェアデコードを使用する場合は明示的に指定が必要
config: VideoDecoderConfig = {
    "codec": "vp09.00.10.08",
    "hardware_acceleration_engine": HardwareAccelerationEngine.APPLE_VIDEO_TOOLBOX,
}
decoder.configure(config)
# Apple Video Toolbox を使用した AV1 デコード (macOS)
# デフォルトでは dav1d によるソフトウェアデコードが使用される
# VideoToolbox による高速なハードウェアデコードを使用する場合は明示的に指定が必要
config: VideoDecoderConfig = {
    "codec": "av01.0.08M.08",
    "hardware_acceleration_engine": HardwareAccelerationEngine.APPLE_VIDEO_TOOLBOX,
}
decoder.configure(config)

VideoEncoder の例

from webcodecs import VideoEncoder, VideoEncoderConfig


def on_output(chunk):
    print(f"エンコード完了: {chunk.byte_length} bytes")


def on_error(error):
    print(f"エラー: {error}")


encoder = VideoEncoder(on_output, on_error)

config: VideoEncoderConfig = {
    "codec": "av1",
    "width": 1920,
    "height": 1080,
    "bitrate": 1000000,
}
encoder.configure(config)

VideoEncoder の例 (VP8/VP9 - macOS / Ubuntu)

from webcodecs import LatencyMode, VideoEncoder, VideoEncoderConfig


def on_output(chunk):
    print(f"エンコード完了: {chunk.byte_length} bytes")


def on_error(error):
    print(f"エラー: {error}")


encoder = VideoEncoder(on_output, on_error)

# VP8 の場合
config_vp8: VideoEncoderConfig = {
    "codec": "vp8",
    "width": 1280,
    "height": 720,
    "bitrate": 1000000,
    "latency_mode": LatencyMode.REALTIME,
}

# VP9 の場合 (Profile 0, 8-bit)
config_vp9: VideoEncoderConfig = {
    "codec": "vp09.00.10.08",
    "width": 1280,
    "height": 720,
    "bitrate": 1000000,
    "latency_mode": LatencyMode.REALTIME,
}

# VP9 Profile 2 (10-bit) の場合
config_vp9_10bit: VideoEncoderConfig = {
    "codec": "vp09.02.10.10",
    "width": 1280,
    "height": 720,
    "bitrate": 1000000,
}

encoder.configure(config_vp9)

VideoEncoder の例 (VP9 SVC - macOS / Ubuntu)

from webcodecs import LatencyMode, VideoEncoder, VideoEncoderConfig


def on_output(chunk, metadata=None):
    if metadata and "svc" in metadata:
        tid = metadata["svc"]["temporal_layer_id"]
        print(f"エンコード完了: {chunk.byte_length} bytes, temporal_layer_id={tid}")
    else:
        print(f"エンコード完了: {chunk.byte_length} bytes")


def on_error(error):
    print(f"エラー: {error}")


encoder = VideoEncoder(on_output, on_error)

# VP9 L1T2 (2 temporal layers)
# temporal layer パターン: 0, 1, 0, 1, ...
config_l1t2: VideoEncoderConfig = {
    "codec": "vp09.00.10.08",
    "width": 1280,
    "height": 720,
    "bitrate": 1000000,
    "latency_mode": LatencyMode.REALTIME,
    "scalability_mode": "L1T2",
}

# VP9 L1T3 (3 temporal layers)
# temporal layer パターン: 0, 2, 1, 2, 0, 2, 1, 2, ...
config_l1t3: VideoEncoderConfig = {
    "codec": "vp09.00.10.08",
    "width": 1280,
    "height": 720,
    "bitrate": 1000000,
    "latency_mode": LatencyMode.REALTIME,
    "scalability_mode": "L1T3",
}

encoder.configure(config_l1t2)

VideoEncoder の例 (AV1 SVC)

from webcodecs import LatencyMode, VideoEncoder, VideoEncoderConfig


def on_output(chunk, metadata=None):
    if metadata and "svc" in metadata:
        tid = metadata["svc"]["temporal_layer_id"]
        print(f"エンコード完了: {chunk.byte_length} bytes, temporal_layer_id={tid}")
    else:
        print(f"エンコード完了: {chunk.byte_length} bytes")


def on_error(error):
    print(f"エラー: {error}")


encoder = VideoEncoder(on_output, on_error)

# AV1 L1T2 (2 temporal layers)
# temporal layer パターン: 0, 1, 0, 1, ...
# 注: SVC 使用時は自動的に REALTIME モードが適用される
config_l1t2: VideoEncoderConfig = {
    "codec": "av01.0.08M.08",
    "width": 1280,
    "height": 720,
    "bitrate": 1000000,
    "scalability_mode": "L1T2",
}

# AV1 L1T3 (3 temporal layers)
# temporal layer パターン: 0, 2, 1, 2, 0, 2, 1, 2, ...
config_l1t3: VideoEncoderConfig = {
    "codec": "av01.0.08M.08",
    "width": 1280,
    "height": 720,
    "bitrate": 1000000,
    "scalability_mode": "L1T3",
}

encoder.configure(config_l1t2)

実装済みインターフェース

辞書型インターフェース (Config)

AudioDataInit

プロパティ Python WebCodecs API テスト 備考
format o o o AudioSampleFormat を受け入れ、必須
sample_rate o o o 必須
number_of_frames o o o 必須
number_of_channels o o o 必須
timestamp o o o 必須
data o o o 必須
transfer x o - 未実装

AudioDecoderConfig

プロパティ Python WebCodecs API テスト 備考
codec o o o 必須
sample_rate o o o 必須
number_of_channels o o o 必須
description o o o bytes 型 (WebCodecs API では AllowSharedBufferSource)

AudioEncoderConfig

プロパティ Python WebCodecs API テスト 備考
codec o o o 必須
sample_rate o o o 必須
number_of_channels o o o 必須
bitrate o o o
bitrate_mode o o o BitrateMode enum

VideoFrameBufferInit

プロパティ Python WebCodecs API テスト 備考
format o o o VideoPixelFormat を受け入れ
coded_width o o o 必須
coded_height o o o 必須
timestamp o o o 必須
duration o o o
layout o o o PlaneLayout の配列
visible_rect o o o DOMRect または dict
display_width o o o
display_height o o o
color_space o o o VideoColorSpace または dict
rotation o * o 0, 90, 180, 270 のみ対応(WebCodecs は任意の double 値)
flip o o o
metadata o o o VideoFrameMetadata または dict
transfer x o - 未実装

VideoFrameMetadata

WebCodecs VideoFrame Metadata Registry に準拠したメタデータフィールドの型定義です。

プロパティ Python WebCodecs API テスト 備考
capture_time o o o DOMHighResTimeStamp (マイクロ秒)
receive_time o o o DOMHighResTimeStamp (マイクロ秒)
rtp_timestamp o o o RTP タイムスタンプ(整数)
segments o o - 顔セグメンテーション(型: Any)
background_blur o o - 背景ぼかし効果ステータス(型: Any)
background_segmentation_mask o o - 背景セグメンテーションマスク(型: Any)

注意:

  • すべてのフィールドはオプション (total=False)
  • TypedDict は型ヒント用であり、実行時の検証は行われない
  • 型が不明確なフィールド (segments, background_blur, background_segmentation_mask) は Any として定義
  • MediaCapture Extensions 仕様で定義されているフィールド
  • 参照: WebCodecs VideoFrame Metadata Registry

使用例:

from webcodecs import VideoFrame, VideoFrameBufferInit, VideoFrameMetadata, VideoPixelFormat
import numpy as np

# TypedDict を使用(IDE の補完・型チェックが効く)
metadata: VideoFrameMetadata = {
    "capture_time": 1234567890.0,
    "receive_time": 1234567891.0,
    "rtp_timestamp": 12345,
}

data = np.zeros(640 * 480 * 3 // 2, dtype=np.uint8)

init: VideoFrameBufferInit = {
    "format": VideoPixelFormat.I420,
    "coded_width": 640,
    "coded_height": 480,
    "timestamp": 0,
    "metadata": metadata,
}

frame = VideoFrame(data, init)

# metadata の取得
result = frame.metadata()
print(result["capture_time"])  # 1234567890.0

VideoDecoderConfig

プロパティ Python WebCodecs API テスト 備考
codec o o o 必須
description o o o bytes 型 (WebCodecs API では AllowSharedBufferSource)
coded_width o o o
coded_height o o o
display_aspect_width x o - 未実装
display_aspect_height x o - 未実装
color_space x o - 未実装
hardware_acceleration x o - 未実装
optimize_for_latency x o - 未実装
rotation x o - 未実装
flip x o - 未実装
hardware_acceleration_engine o x o 独自拡張: HardwareAccelerationEngine ENUM

VideoEncoderConfig

プロパティ Python WebCodecs API テスト 備考
codec o o o 必須
width o o o 必須
height o o o 必須
display_width x o - 未実装
display_height x o - 未実装
bitrate o o o
framerate o o o
hardware_acceleration x o - 未実装
alpha o o o AlphaOption enum
scalability_mode o o o VP9 L1T2/L1T3 のみ対応
bitrate_mode o o o VideoEncoderBitrateMode enum
latency_mode o o o LatencyMode enum
content_hint x o - 未実装
avc o o o AvcEncoderConfig (format: "annexb" | "avc")
hevc o o o HevcEncoderConfig (format: "annexb" | "hevc")
hardware_acceleration_engine o x o 独自拡張: HardwareAccelerationEngine ENUM(実際に使用される)

Audio インターフェース

AudioData

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(init) o o o AudioDataInit を使用
format o o o AudioSampleFormat
sample_rate o o o
number_of_frames o o o
number_of_channels o o o
duration o o o
timestamp o o o
allocation_size(options) o o o AudioDataCopyToOptions に基づいてサイズを計算
copy_to(destination, options) o o o AudioDataCopyToOptions に基づいて destination に書き込み(format 指定で変換も可能)
clone() o o o
close() o o o
is_closed o x o 独自拡張: プロパティ
get_channel_data() o x o 独自拡張: 特定チャンネルのデータを返す

EncodedAudioChunk

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(init) o o o EncodedAudioChunkInit (dict) を受け取る
type o o o "key" または "delta"
timestamp o o o
duration o o o
byte_length o o o
copy_to() o o o destination に書き込み

AudioDecoder

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(output, error) o * o Python 実装: コールバックを直接渡す (WebCodecs は init 辞書)
state o o o CodecState
decode_queue_size o o o
on_dequeue o o o EventHandler
configure(config) o o o
decode(chunk) o o o
flush() o o o
reset() o o o
close() o o o
is_config_supported() o o o 静的メソッド
on_output(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)
on_error(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)

AudioEncoder

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(output, error) o * o Python 実装: コールバックを直接渡す (WebCodecs は init 辞書)
state o o o CodecState
encode_queue_size o o o
on_dequeue o o o EventHandler
configure(config) o o o
encode(data) o o o
flush() o o o
reset() o o o
close() o o o
is_config_supported() o o o 静的メソッド
on_output(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)
on_error(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)

Video インターフェース

VideoFrame

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(image, init) - o - 実装しない (CanvasImageSource はブラウザ固有機能)
constructor(data, init) o o o VideoFrameBufferInit を使用
format o o o VideoPixelFormat を返す
coded_width o o o
coded_height o o o
coded_rect x o - 未実装
visible_rect o o o DOMRect を返す
rotation o * o 0, 90, 180, 270 のみ対応(WebCodecs は任意の double 値)
flip o o o 水平反転
display_width o o o
display_height o o o
duration o o o
timestamp o o o
color_space o o o VideoColorSpace を返す
metadata() o o o VideoFrameMetadata 型の dict を返す
allocation_size(options) o o o copy_to() に必要なバッファサイズを返す
copy_to(destination, options) o * o destination に書き込み、PlaneLayout のリストを返す(format 指定で変換も可能、color_space オプションは未実装)
clone() o o o すべてのプロパティ(metadata 含む)をコピー
close() o o o
is_closed o x o 独自拡張: プロパティ
planes() o x o 独自拡張: 全プレーン (Y, U, V) をタプルで返す(I420/I422/I444 のみ)
plane() o x o 独自拡張: 指定したプレーンを返す(全フォーマット対応)
native_buffer o x o 独自拡張: ネイティブバッファ(PyCapsule)を保持するプロパティ(macOS のみ)

clone() の動作:

  • すべてのプロパティ(timestamp, duration, format, color_space, metadata 等)がコピーされる
  • データは新しいメモリ領域にコピーされる(deep copy)

EncodedVideoChunk

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(init) o o o EncodedVideoChunkInit (dict) を受け取る
type o o o "key" または "delta"
timestamp o o o
duration o o o
byte_length o o o
copy_to() o o o destination に書き込み

VideoDecoder

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(output, error) o * o Python 実装: コールバックを直接渡す (WebCodecs は init 辞書)
state o o o CodecState
decode_queue_size o o o
on_dequeue o o o EventHandler
configure(config) o o o
decode(chunk) o o o
flush() o o o
reset() o o o
close() o o o
is_config_supported() o o o 静的メソッド
on_output(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)
on_error(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)

VideoEncoder

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(output, error) o * o Python 実装: コールバックを直接渡す (WebCodecs は init 辞書)
state o o o CodecState
encode_queue_size o o o
on_dequeue o o o EventHandler
configure(config) o o o
encode(frame, options) o o o VideoEncoderEncodeOptions (key_frame, av1.quantizer, avc.quantizer, hevc.quantizer, vp8.quantizer, vp9.quantizer)
flush() o o o
reset() o o o
close() o o o
is_config_supported() o o o 静的メソッド
on_output(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)
on_error(callback) o x o 独自拡張: コールバック設定 (WebCodecs はコンストラクタで指定)

: avc.quantizer / hevc.quantizer は VideoToolbox (Apple) ではフレームごとの指定がサポートされていないため無視される。

output callback の metadata: WebCodecs API 仕様に準拠し、キーフレーム時に metadata (dict) が第 2 引数として渡される。後方互換性のため、1 引数のコールバックも引き続きサポートされる。

def on_output(chunk, metadata=None):
    # metadata はキーフレーム時のみ提供される
    if metadata is not None:
        decoder_config = metadata.get("decoder_config")
        if decoder_config is not None:
            # codec: str
            # coded_width: int (オプション)
            # coded_height: int (オプション)
            # description: bytes (H.264 では avcC、H.265 では hvcC)
            description = decoder_config.get("description")

自動スケーリング: WebCodecs API 仕様に準拠し、encode() で渡される VideoFrame の解像度と configure() で指定した解像度が異なる場合、自動的にスケーリングが行われます。

from webcodecs import VideoEncoder, VideoEncoderConfig, VideoFrame, VideoPixelFormat
import numpy as np

def on_output(chunk, metadata=None):
    pass

def on_error(error):
    pass

encoder = VideoEncoder(on_output, on_error)

# configure で 640x360 を指定
config: VideoEncoderConfig = {
    "codec": "av01.0.04M.08",
    "width": 640,
    "height": 360,
    "bitrate": 1_000_000,
}
encoder.configure(config)

# 1280x720 のフレームを渡すと、自動的に 640x360 にスケーリングされる
data = np.zeros(1280 * 720 * 3 // 2, dtype=np.uint8)
frame = VideoFrame(data, {
    "format": VideoPixelFormat.I420,
    "coded_width": 1280,
    "coded_height": 720,
    "timestamp": 0,
})
encoder.encode(frame)  # 640x360 にスケーリングしてエンコード
frame.close()
encoder.close()

スケーリング実装の詳細:

エンコーダー スケーリング方式 対応フォーマット
Apple Video Toolbox (H.264/HEVC) VTPixelTransferSession (HWA) I420, NV12, BGRA
ソフトウェアエンコーダー (AV1/VP8/VP9) libyuv (各フォーマット対応) I420, I422, I444, NV12, RGBA, BGRA, RGB, BGR
NVIDIA Video Codec SDK (NVENC) libyuv (各フォーマット対応) I420, I422, I444, NV12, RGBA, BGRA, RGB, BGR
Intel VPL libyuv (各フォーマット対応) I420, I422, I444, NV12, RGBA, BGRA, RGB, BGR

注意事項:

  • スケーリングはダウンスケール、アップスケールの両方に対応
  • アスペクト比は configure() で指定した解像度に合わせられる(引き伸ばし)
  • 同じ解像度のフレームはスケーリング処理をスキップ
  • 入力フォーマットに応じた libyuv スケーラーが使用される (I420Scale, I422Scale, I444Scale, NV12Scale, ARGBScale)
  • RGB/BGR フォーマットは I420/NV12 に変換後スケーリング (libyuv に RGBScale がないため)

独自インターフェース

VideoFrame 拡張

planes() メソッド

内部バッファに直接アクセスする独自拡張メソッド

def planes() -> tuple[ndarray, ndarray, ndarray]
  • 目的: 内部バッファに直接アクセスし、入出力に利用できる ndarray を返す
  • 対応フォーマット: I420, I422, I444
  • 戻り値: (Y プレーン, U プレーン, V プレーン) のタプル
  • 注意事項:
    • 返されるビューは元の VideoFrame のメモリを参照している
    • VideoFrame が close() されるとビューは無効になる
    • ビューへの書き込みは元のデータを変更する

使用例:

import numpy as np
from webcodecs import VideoFrame, VideoFrameBufferInit, VideoPixelFormat

# データを作成
data = np.zeros(width * height * 3 // 2, dtype=np.uint8)

init: VideoFrameBufferInit = {
    "format": VideoPixelFormat.I420,
    "coded_width": width,
    "coded_height": height,
    "timestamp": 0,
}

frame = VideoFrame(data, init)

# 内部バッファに直接アクセス
y_plane, u_plane, v_plane = frame.planes()

# ビューへの書き込みは元のデータを変更
y_plane[:] = 235  # 元の data も変更される

native_buffer プロパティ

エンコーダーが直接利用できるプロパティ(macOS 専用)

native_buffer: object | None  # 読み書き可能
  • 目的: CVPixelBufferRef を保持し、Video Toolbox エンコーダーが直接利用できる
  • 対応プラットフォーム: macOS のみ
  • 形式: PyCapsule(名前: "CVPixelBufferRef"

コンストラクタでの使用:

VideoFrame は data (numpy.ndarray) の代わりに PyCapsule を直接受け取ることができます:

import ctypes
from webcodecs import VideoFrame, VideoPixelFormat

# CVPixelBufferRef を PyCapsule でラップ(実際のコードでは外部から取得)
# capsule = create_cv_pixel_buffer_capsule(cv_pixel_buffer_ref)

frame = VideoFrame(
    capsule,  # data の代わりに PyCapsule を渡す
    {
        "format": VideoPixelFormat.NV12,
        "coded_width": 640,
        "coded_height": 480,
        "timestamp": 0,
    },
)

# エンコーダーが直接利用する
encoder.encode(frame)

制限事項:

native_buffer のみで作成した VideoFrame では、以下のメソッドは使用できません(RuntimeError が発生):

  • plane() - プレーンデータにアクセスできない
  • planes() - プレーンデータにアクセスできない
  • copy_to() - データをコピーできない
  • clone() - データをコピーできない

これらのメソッドが必要な場合は、data (numpy.ndarray) を使用して VideoFrame を作成してください。

ユースケース:

  • カメラキャプチャから直接取得した CVPixelBufferRef をエンコード
  • GPU レンダリング結果の CVPixelBufferRef をエンコード
  • メモリコピーを最小化したリアルタイム処理

VideoFrame のメモリ管理

VideoFrame は以下の 3 つのモードで動作します:

  1. 外部メモリ参照モード (コンストラクタで ndarray を渡した場合)

    • 元の ndarray への参照を保持
    • planes() メソッドは内部バッファに直接アクセスできる
    • copy_to() メソッドはデータのコピーを返す
  2. 内部メモリ所有モード (width, height, format で作成した場合)

    • 内部でメモリを確保し所有
    • planes() メソッドは内部メモリへのビューを返す
    • copy_to() メソッドはデータのコピーを返す
  3. native_buffer モード (コンストラクタで PyCapsule を渡した場合、macOS のみ)

    • CVPixelBufferRef への参照のみを保持(データは保持しない)
    • planes() / plane() / copy_to() は使用不可(RuntimeError)
    • Video Toolbox エンコーダーが直接利用可能

その他の型定義

補助型

PlaneLayout

プロパティ Python WebCodecs API 備考
offset o o
stride o o

DOMRect

プロパティ Python WebCodecs API 備考
x o o
y o o
width o o
height o o

VideoColorSpace

プロパティ Python WebCodecs API 備考
primaries o o
transfer o o
matrix o o
full_range o o

列挙型

CodecState

  • UNCONFIGURED - 未設定状態
  • CONFIGURED - 設定済み状態
  • CLOSED - クローズ済み状態

VideoPixelFormat

実装済みのフォーマット:

  • I420, I422, I444 - YUV プレーナーフォーマット
  • NV12 - YUV セミプレーナーフォーマット
  • RGBA, BGRA - 4:4:4 RGBA フォーマット
  • RGB, BGR - 4:4:4 RGB フォーマット(独自拡張、下記参照)

未実装のフォーマット (WebCodecs API で定義):

  • I420P10, I420P12 - 10/12bit YUV 4:2:0
  • I420A, I420AP10, I420AP12 - アルファ付き YUV 4:2:0
  • I422P10, I422P12 - 10/12bit YUV 4:2:2
  • I422A, I422AP10, I422AP12 - アルファ付き YUV 4:2:2
  • I444P10, I444P12 - 10/12bit YUV 4:4:4
  • I444A, I444AP10, I444AP12 - アルファ付き YUV 4:4:4
  • RGBX, BGRX - 不透明 RGB フォーマット

RGB/BGR が独自拡張である理由:

WebCodecs API では RGB 系フォーマットとして RGBA, RGBX, BGRA, BGRX の 4 種類のみを定義しており、すべて 4 バイト/ピクセル(32 ビット境界)です。これは GPU やハードウェアアクセラレーションとの互換性、およびメモリアライメントの効率を考慮した設計です。

一方、Python エコシステム(NumPy、PIL/Pillow、OpenCV、matplotlib 等)では 3 バイト/ピクセルの RGB/BGR フォーマットが広く使用されています。webcodecs-py ではこれらのライブラリとの相互運用性を重視し、独自拡張として RGBBGR をサポートしています。

import numpy as np
from webcodecs import VideoFrame, VideoPixelFormat

# PIL/Pillow との連携例
from PIL import Image
img = Image.open("image.png").convert("RGB")
rgb_data = np.array(img)  # shape: (height, width, 3)

AudioSampleFormat

実装済みのフォーマット:

  • U8, S16, S32, F32 - インターリーブフォーマット
  • U8_PLANAR, S16_PLANAR, S32_PLANAR, F32_PLANAR - プレーナーフォーマット

EncodedVideoChunkType / EncodedAudioChunkType

  • KEY - キーフレーム
  • DELTA - 差分フレーム

HardwareAccelerationEngine(独自拡張)

ハードウェアアクセラレーションエンジンを指定する ENUM:

  • NONE - ソフトウェアエンコード/デコード(デフォルト)
  • APPLE_VIDEO_TOOLBOX
    • macOS の VideoToolbox
    • Encoder: H.264 / H.265
    • Decoder: H.264 / H.265 / VP9 / AV1
  • NVIDIA_VIDEO_CODEC
    • NVIDIA Video Codec SDK
    • Encoder: AV1 / H.264 / H.265
    • Decoder: VP8 / VP9 / AV1 / H.264 / H.265
  • INTEL_VPL - Intel VPL(未実装)
  • AMD_AMF - AMD AMF(未実装)

使用例 (Apple Video Toolbox):

from webcodecs import VideoEncoder, VideoEncoderConfig, HardwareAccelerationEngine

config: VideoEncoderConfig = {
    "codec": "avc1.42001f",
    "width": 1920,
    "height": 1080,
    "hardware_acceleration_engine": HardwareAccelerationEngine.APPLE_VIDEO_TOOLBOX
}

使用例 (NVIDIA Video Codec SDK):

from webcodecs import VideoEncoder, VideoEncoderConfig, HardwareAccelerationEngine

# H.264 エンコード
config: VideoEncoderConfig = {
    "codec": "avc1.42001f",
    "width": 1920,
    "height": 1080,
    "bitrate": 5_000_000,
    "hardware_acceleration_engine": HardwareAccelerationEngine.NVIDIA_VIDEO_CODEC
}

# HEVC エンコード
config_hevc: VideoEncoderConfig = {
    "codec": "hvc1.1.6.L93.B0",
    "width": 1920,
    "height": 1080,
    "bitrate": 5_000_000,
    "hardware_acceleration_engine": HardwareAccelerationEngine.NVIDIA_VIDEO_CODEC
}

# AV1 エンコード (NVIDIA RTX 40 シリーズ以降)
config_av1: VideoEncoderConfig = {
    "codec": "av01.0.08M.08",
    "width": 1920,
    "height": 1080,
    "bitrate": 5_000_000,
    "hardware_acceleration_engine": HardwareAccelerationEngine.NVIDIA_VIDEO_CODEC
}

NVIDIA Video Codec SDK の要件:

  • NVIDIA GPU
  • NVIDIA ドライバーがインストールされていること
  • Ubuntu のみ対応
  • ビルド時に USE_NVIDIA_CUDA_TOOLKIT=1 uv build --wheel の指定が必要

LatencyMode

エンコーダーのレイテンシーモードを指定する ENUM:

  • QUALITY - 品質優先モード(デフォルト)
  • REALTIME - リアルタイム優先モード

使用例:

from webcodecs import VideoEncoder, VideoEncoderConfig, LatencyMode

config: VideoEncoderConfig = {
    "codec": "av1",
    "width": 1920,
    "height": 1080,
    "latency_mode": LatencyMode.REALTIME
}

VideoEncoderBitrateMode

VideoEncoder のビットレートモードを指定する ENUM:

  • CONSTANT - 固定ビットレート
  • VARIABLE - 可変ビットレート(デフォルト)
  • QUANTIZER - 量子化パラメータ指定

使用例:

from webcodecs import VideoEncoder, VideoEncoderConfig, VideoEncoderBitrateMode

config: VideoEncoderConfig = {
    "codec": "av1",
    "width": 1920,
    "height": 1080,
    "bitrate_mode": VideoEncoderBitrateMode.CONSTANT,
    "bitrate": 1000000
}

BitrateMode

AudioEncoder のビットレートモードを指定する ENUM:

  • CONSTANT - 固定ビットレート
  • VARIABLE - 可変ビットレート(デフォルト)

使用例:

from webcodecs import AudioEncoder, AudioEncoderConfig, BitrateMode

config: AudioEncoderConfig = {
    "codec": "opus",
    "sample_rate": 48000,
    "number_of_channels": 2,
    "bitrate_mode": BitrateMode.CONSTANT,
    "bitrate": 64000
}

AlphaOption

アルファチャンネルの処理方法を指定する ENUM:

  • KEEP - アルファチャンネルを保持
  • DISCARD - アルファチャンネルを破棄(デフォルト)

使用例:

from webcodecs import VideoEncoder, VideoEncoderConfig, AlphaOption

config: VideoEncoderConfig = {
    "codec": "av1",
    "width": 1920,
    "height": 1080,
    "alpha": AlphaOption.DISCARD
}

HardwareAcceleration

ハードウェアアクセラレーションの優先度を指定する ENUM:

  • NO_PREFERENCE - 指定なし(デフォルト)
  • PREFER_HARDWARE - ハードウェア優先
  • PREFER_SOFTWARE - ソフトウェア優先

: このオプションは現在フィールド定義のみで、実際には HardwareAccelerationEngine 独自拡張を使用してください。

VideoColorPrimaries

色空間の原色を指定する ENUM:

  • BT709 - ITU-R BT.709
  • BT470BG - ITU-R BT.470BG
  • SMPTE170M - SMPTE 170M
  • BT2020 - ITU-R BT.2020
  • SMPTE432 - SMPTE ST 432-1 (DCI-P3)

VideoTransferCharacteristics

伝達特性を指定する ENUM:

  • BT709 - ITU-R BT.709
  • SMPTE170M - SMPTE 170M
  • IEC61966_2_1 - IEC 61966-2-1 (sRGB)
  • LINEAR - リニア
  • PQ - SMPTE ST 2084 (PQ)
  • HLG - ARIB STD-B67 (HLG)

VideoMatrixCoefficients

行列係数を指定する ENUM:

  • RGB - RGB (行列変換なし)
  • BT709 - ITU-R BT.709
  • BT470BG - ITU-R BT.470BG
  • SMPTE170M - SMPTE 170M
  • BT2020_NCL - ITU-R BT.2020 non-constant luminance

独自関数

get_video_codec_capabilities()

独自拡張関数 - WebCodecs API にはない

実行環境で利用可能なビデオコーデックとハードウェアアクセラレーションエンジンの詳細情報を返します。

def get_video_codec_capabilities() -> dict[HardwareAccelerationEngine, dict]

戻り値:

HardwareAccelerationEngine をキーとした辞書。各エンジンの情報には以下が含まれます:

  • available (bool) - エンジンが利用可能かどうか
  • platform (str) - 対応プラットフォーム ("darwin", "linux", "windows", "all")
  • codecs (dict) - コーデック名をキーとした辞書
    • 各コーデックには以下が含まれる:
      • encoder (bool) - エンコーダーが利用可能かどうか
      • decoder (bool) - デコーダーが利用可能かどうか

使用例 (macOS):

from webcodecs import get_video_codec_capabilities, HardwareAccelerationEngine

capabilities = get_video_codec_capabilities()

# 結果の例
# {
#     HardwareAccelerationEngine.NONE: {
#         "available": True,
#         "platform": "all",
#         "codecs": {
#             "av01": {"encoder": True, "decoder": True},
#             "vp8": {"encoder": True, "decoder": True},
#             "vp09": {"encoder": True, "decoder": True}
#         }
#     },
#     HardwareAccelerationEngine.APPLE_VIDEO_TOOLBOX: {
#         "available": True,
#         "platform": "darwin",
#         "codecs": {
#             "avc1": {"encoder": True, "decoder": True},
#             "hvc1": {"encoder": True, "decoder": True},
#             "vp09": {"encoder": False, "decoder": True},
#             "av01": {"encoder": False, "decoder": True}
#         }
#     }
# }

# 特定のコーデックが利用可能か確認
vt_info = capabilities.get(HardwareAccelerationEngine.APPLE_VIDEO_TOOLBOX)
if vt_info and vt_info["available"]:
    if "avc1" in vt_info["codecs"] and vt_info["codecs"]["avc1"]["encoder"]:
        print("H.264 ハードウェアエンコーダーが利用可能")

使用例 (Ubuntu):

capabilities = get_video_codec_capabilities()

# 結果の例
# {
#     HardwareAccelerationEngine.NONE: {
#         "available": True,
#         "platform": "all",
#         "codecs": {
#             "av01": {"encoder": True, "decoder": True}
#         }
#     }
# }

コーデック名について:

WebCodecs の codec format 仕様に準拠した名前を使用しています:

  • av01 - AV1 (WebCodecs 標準)
  • avc1 - H.264 (WebCodecs 標準、h264 ではない)
  • hvc1 - H.265/HEVC (WebCodecs 標準、h265hevc ではない)
  • vp8 - VP8 (WebCodecs 標準)
  • vp09 - VP9 (WebCodecs 標準、vp9 ではない)

実装詳細:

  • macOS では VideoToolbox の実際の利用可能性を VTCompressionSessionCreate() で確認
  • macOS では libvpx による VP8/VP9 が利用可能
  • 各プラットフォームで実際にサポートされているコーデックのみを返す
  • 未実装のエンジン (NVIDIA、INTEL、AMD) は結果に含まれない

H.264/H.265 ヘッダーパーサー

独自拡張関数 - WebCodecs API にはない

H.264 (AVC) および H.265 (HEVC) のビットストリームヘッダーをパースし、SPS/PPS/VPS および NAL ユニット情報を抽出します。

パース関数

Annex B フォーマット用:

def parse_avc_annexb(data: bytes) -> AVCAnnexBInfo: ...
def parse_hevc_annexb(data: bytes) -> HEVCAnnexBInfo: ...

スタートコード(0x00 0x00 0x01 または 0x00 0x00 0x00 0x01)で区切られた NAL ユニットをパースします。

Description (avcC/hvcC) フォーマット用:

def parse_avc_description(data: bytes) -> AVCDescriptionInfo: ...
def parse_hevc_description(data: bytes) -> HEVCDescriptionInfo: ...

エンコーダーから出力される description(avcC/hvcC box)をパースします。

使用例:

from webcodecs import parse_avc_annexb, parse_avc_description

# Annex B フォーマットの H.264 ストリーム
avc_stream = b"\x00\x00\x00\x01\x67..."  # SPS + PPS + ...
info = parse_avc_annexb(avc_stream)

if info.sps is not None:
    print(f"Profile: {info.sps.profile_idc}")
    print(f"Level: {info.sps.level_idc}")
    print(f"Resolution: {info.sps.width}x{info.sps.height}")

# NAL ユニット情報
for nal in info.nal_units:
    print(f"NAL Type: {nal.nal_unit_type}, Key frame: {nal.is_key_frame}")

# エンコーダーから取得した description をパース
def on_output(chunk, metadata=None):
    if metadata and "decoder_config" in metadata:
        description = metadata["decoder_config"].get("description")
        if description:
            desc_info = parse_avc_description(description)
            print(f"Length size: {desc_info.length_size}")

個別パース関数

def parse_avc_sps(data: bytes) -> AVCSpsInfo: ...
def parse_avc_pps(data: bytes) -> AVCPpsInfo: ...
def parse_hevc_vps(data: bytes) -> HEVCVpsInfo: ...
def parse_hevc_sps(data: bytes) -> HEVCSpsInfo: ...
def parse_hevc_pps(data: bytes) -> HEVCPpsInfo: ...

個別の NAL ユニットをパースします。入力データには NAL ヘッダーを含めてください。

戻り値の型

AVCSpsInfo:

フィールド 説明
profile_idc int プロファイル ID (66=Baseline, 77=Main, 100=High など)
level_idc int レベル ID (30=3.0, 31=3.1, 40=4.0 など)
constraint_set_flags int 制約フラグ
width int 解像度(幅)
height int 解像度(高さ)
bit_depth_luma int 輝度ビット深度 (通常 8)
bit_depth_chroma int 色差ビット深度 (通常 8)
chroma_format_idc int クロマフォーマット (1=4:2:0, 2=4:2:2, 3=4:4:4)
sps_id int SPS ID
framerate float | None フレームレート(VUI から取得、存在する場合)

AVCPpsInfo:

フィールド 説明
pps_id int PPS ID
sps_id int 参照する SPS ID
entropy_coding_mode_flag bool CABAC 使用フラグ

AVCNalUnitHeader:

フィールド 説明
nal_unit_type int NAL ユニットタイプ (1=非IDRスライス, 5=IDRスライス, 7=SPS, 8=PPS など)
nal_ref_idc int 参照指標 (0-3)
is_idr bool IDR フレームか
is_key_frame bool キーフレームか

AVCAnnexBInfo:

フィールド 説明
sps AVCSpsInfo | None SPS 情報(存在する場合)
pps AVCPpsInfo | None PPS 情報(存在する場合)
nal_units list[AVCNalUnitHeader] NAL ユニットヘッダーのリスト

AVCDescriptionInfo:

フィールド 説明
sps AVCSpsInfo | None SPS 情報(存在する場合)
pps AVCPpsInfo | None PPS 情報(存在する場合)
nal_units list[AVCNalUnitHeader] NAL ユニットヘッダーのリスト
length_size int NAL ユニット長のバイト数 (通常 4)

HEVCVpsInfo:

フィールド 説明
vps_id int VPS ID
max_layers_minus1 int 最大レイヤー数 - 1
max_sub_layers_minus1 int 最大サブレイヤー数 - 1

HEVCSpsInfo:

フィールド 説明
sps_id int SPS ID
vps_id int 参照する VPS ID
width int 解像度(幅)
height int 解像度(高さ)
bit_depth_luma int 輝度ビット深度
bit_depth_chroma int 色差ビット深度
chroma_format_idc int クロマフォーマット
general_profile_idc int 一般プロファイル ID
general_level_idc int 一般レベル ID
general_tier_flag int 一般ティアフラグ
framerate float | None フレームレート(VUI から取得、存在する場合)

HEVCPpsInfo:

フィールド 説明
pps_id int PPS ID
sps_id int 参照する SPS ID

HEVCNalUnitHeader:

フィールド 説明
nal_unit_type int NAL ユニットタイプ (32=VPS, 33=SPS, 34=PPS, 19-21=IDR など)
nuh_layer_id int レイヤー ID
nuh_temporal_id_plus1 int テンポラル ID + 1
is_irap bool IRAP (Intra Random Access Point) フレームか
is_key_frame bool キーフレームか

HEVCAnnexBInfo:

フィールド 説明
vps HEVCVpsInfo | None VPS 情報(存在する場合)
sps HEVCSpsInfo | None SPS 情報(存在する場合)
pps HEVCPpsInfo | None PPS 情報(存在する場合)
nal_units list[HEVCNalUnitHeader] NAL ユニットヘッダーのリスト

HEVCDescriptionInfo:

フィールド 説明
vps HEVCVpsInfo | None VPS 情報(存在する場合)
sps HEVCSpsInfo | None SPS 情報(存在する場合)
pps HEVCPpsInfo | None PPS 情報(存在する場合)
nal_units list[HEVCNalUnitHeader] NAL ユニットヘッダーのリスト
length_size int NAL ユニット長のバイト数 (通常 4)

NAL ユニットタイプ enum

AVCNalUnitTypeHEVCNalUnitType は IntEnum 相当として定義されており、整数値との比較が可能です。

from webcodecs import AVCNalUnitType, HEVCNalUnitType

# AVC NAL ユニットタイプ
print(AVCNalUnitType.SPS)       # 7
print(AVCNalUnitType.PPS)       # 8
print(AVCNalUnitType.IDR_SLICE) # 5

# HEVC NAL ユニットタイプ
print(HEVCNalUnitType.VPS)      # 32
print(HEVCNalUnitType.SPS)      # 33
print(HEVCNalUnitType.PPS)      # 34

エラー処理

不正なデータの場合は ValueError を送出します:

from webcodecs import parse_avc_annexb

try:
    info = parse_avc_annexb(b"")  # 空データ
except ValueError as e:
    print(f"Error: {e}")

Image インターフェース

辞書型インターフェース (Image)

ImageDecoderInit

プロパティ Python WebCodecs API テスト 備考
type o o o MIME タイプ、必須
data o o o bytes 型、必須
color_space_conversion o o - "default" または "none"
desired_width o o - リサイズ幅
desired_height o o - リサイズ高さ
prefer_animation o o - アニメーション優先
transfer x o - 未実装

ImageDecodeOptions

プロパティ Python WebCodecs API テスト 備考
frame_index o o o デフォルト 0
complete_frames_only o o - デフォルト true

ImageDecodeResult

プロパティ Python WebCodecs API テスト 備考
image o o o VideoFrame
complete o o o デコード完了フラグ

ImageDecoder

メソッド/プロパティ Python WebCodecs API テスト 備考
constructor(init) o o o ImageDecoderInit を使用
type o o o MIME タイプ
complete o o o データ読み込み完了
completed - o - Promise(Python では is_complete プロパティ)
tracks o o o ImageTrackList
decode(options) o o o 同期的に実行、ImageDecodeResult を返す
reset() o o o
close() o o o
is_type_supported() o o o 静的メソッド
is_closed o x o 独自拡張: プロパティ
is_complete o x o 独自拡張: complete の別名

サポートフォーマット (macOS のみ):

フォーマット MIME タイプ 対応状況
JPEG image/jpeg o
PNG image/png o
GIF image/gif o(アニメーション対応)
WebP image/webp o
BMP image/bmp o
TIFF image/tiff o
HEIC/HEIF image/heic, image/heif o

: ImageDecoder は macOS の Image I/O フレームワークを使用しています。他のプラットフォームでは利用できません。

ImageTrackList

メソッド/プロパティ Python WebCodecs API テスト 備考
[index] o o o __getitem__
ready - o - Promise(Python では is_ready プロパティ)
length o o o
selected_index o o o
selected_track o o o
is_ready o x o 独自拡張: ready の同期版

ImageTrack

メソッド/プロパティ Python WebCodecs API テスト 備考
animated o o o
frame_count o o o
repetition_count o o o
selected o o o 読み書き可能

ImageDecoder の使用例

from webcodecs import ImageDecoder, ImageDecoderInit

# JPEG ファイルを読み込み
with open("image.jpg", "rb") as f:
    jpeg_data = f.read()

# ImageDecoder を作成
decoder = ImageDecoder({
    "type": "image/jpeg",
    "data": jpeg_data,
})

# 画像情報を確認
print(f"Type: {decoder.type}")
print(f"Complete: {decoder.complete}")
print(f"Tracks: {decoder.tracks.length}")

track = decoder.tracks[0]
print(f"Animated: {track.animated}")
print(f"Frame count: {track.frame_count}")

# デコード
result = decoder.decode()
frame = result["image"]

print(f"Size: {frame.coded_width}x{frame.coded_height}")
print(f"Format: {frame.format}")  # RGBA

# クリーンアップ
frame.close()
decoder.close()

未実装の機能

実装しない機能

以下の機能は webcodecs-py では実装しません:

  • CanvasImageSource: VideoFrame の CanvasImageSource コンストラクタはブラウザ固有機能のため実装対象外

未実装の辞書型

辞書型 備考
VideoColorSpaceInit VideoColorSpace クラスで代替
EncodedAudioChunkMetadata メタデータサポート未実装

: EncodedVideoChunkMetadata は VideoEncoder の output callback で dict として提供される (キーフレーム時のみ decoder_config を含む)。scalability_mode が指定されている場合、全フレームで svc フィールド (temporal_layer_id を含む) が提供される。

未実装の列挙型

列挙型 備考
PredefinedColorSpace 未実装

サポートされているコーデック

Video コーデック

コーデック エンコード デコード ライブラリ/API プラットフォーム
VP8 o o libvpx macOS / Ubuntu
VP9 o o libvpx macOS / Ubuntu
VP9 - o VideoToolbox* macOS
AV1 o o libaom / dav1d All
AV1 - o VideoToolbox* macOS
AV1 o o NVENC / NVDEC Ubuntu x86_64
H.264 o o VideoToolbox* macOS
H.264 o o NVENC / NVDEC Ubuntu x86_64
H.265 o o VideoToolbox* macOS
H.265 o o NVENC / NVDEC Ubuntu x86_64

*ハードウェアアクセラレーション使用(VP9/AV1 の VideoToolbox デコードは HardwareAccelerationEngine.APPLE_VIDEO_TOOLBOX を明示的に指定した場合のみ有効)

VP9 プロファイル対応状況:

Profile ビット深度 クロマサブサンプリング 対応状況
0 8-bit 4:2:0 o
1 8-bit 4:2:2, 4:4:4 o
2 10/12-bit 4:2:0 o
3 10/12-bit 4:2:2, 4:4:4 o

VP9 scalabilityMode 対応状況:

モード 説明 対応状況
L1T2 1 spatial layer, 2 temporal layers o
L1T3 1 spatial layer, 3 temporal layers o
L2T* 2+ spatial layers x

AV1 scalabilityMode 対応状況:

モード 説明 対応状況
L1T2 1 spatial layer, 2 temporal layers o
L1T3 1 spatial layer, 3 temporal layers o
L2T* 2+ spatial layers x

: AV1 で scalabilityMode を使用する場合、libaom の制約により自動的に REALTIME モードが適用されます。

Audio コーデック

コーデック エンコード デコード ライブラリ/API プラットフォーム
Opus o o libopus All
FLAC o o libFLAC All
AAC o o AudioToolbox macOS

パフォーマンス最適化

並列処理実装

WebCodecs 仕様に準拠した並列処理を全てのコーデックで実装:

  • 非ブロッキング API: encode() / decode() メソッドは即座に返る(< 1ms)
  • ワーカースレッド: バックグラウンドでのエンコード/デコード処理
  • 順序保証: 出力フレーム/チャンクの順序を保持
  • キュー管理: 複数のタスクを同時にスケジュール可能
  • スレッドセーフ: 複数スレッドからの同時呼び出しに対応
# 並列処理の例 - 前の処理を待たずに次の処理を開始
encoder.encode(frame1)  # 即座に返る
encoder.encode(frame2)  # frame1 の完了を待たない
encoder.encode(frame3)  # frame2 の完了を待たない

# キューサイズの確認
print(encoder.encode_queue_size)  # 処理待ちタスク数

planes() によるビューアクセス

  • plane(), planes() メソッドは内部バッファへのビューを返す(コピーなし)

メモリ管理

  • Python のガベージコレクションと C++ オブジェクトのライフサイクル管理を適切に統合
  • close() メソッドによる明示的なリソース解放をサポート
  • ワーカースレッドでの shared_ptr 使用によるメモリ安全性の確保

Free Threading 対応

Python 3.13t / 3.14t の Free Threading ビルド(GIL 無効化)に対応しています。

対応状況

クラス 対応状況 備考
VideoEncoder o コールバックの並列変更・呼び出しに対応
VideoDecoder o コールバックの並列変更・呼び出しに対応
AudioEncoder o コールバックの並列変更・呼び出しに対応
AudioDecoder o コールバックの並列変更・呼び出しに対応
VideoFrame - コールバック機構なし(対応不要)、native_buffer 含む
AudioData - コールバック機構なし(対応不要)
EncodedVideoChunk - イミュータブル(対応不要)
EncodedAudioChunk - イミュータブル(対応不要)

サポートプラットフォーム

プラットフォーム Python 3.13t Python 3.14t
macOS o o
Ubuntu o o
Windows o x(nanobind ビルドの問題)

実装詳細

Free Threading 環境でのスレッドセーフ性を確保するため、以下の同期メカニズムを使用しています:

  • nb::ft_mutex: Python オブジェクト(コールバック)の保護
  • std::mutex: C++ 内部状態(キュー、バッファ)の保護
  • std::atomic<>: スレッドセーフなフラグ管理

コールバックの変更と呼び出しは排他制御されており、複数スレッドから同時にアクセスしても安全です:

import threading
from webcodecs import VideoEncoder, VideoEncoderConfig

def on_output(chunk, metadata=None):
    pass

def on_error(err):
    pass

encoder = VideoEncoder(on_output, on_error)
encoder.configure({
    "codec": "av01.0.04M.08",
    "width": 320,
    "height": 240,
})

# 複数スレッドから同時にコールバックを変更しても安全
def modify_callback(thread_id):
    for i in range(100):
        def new_output(chunk, metadata=None, tid=thread_id, idx=i):
            pass
        encoder.on_output(new_output)

threads = [threading.Thread(target=modify_callback, args=(i,)) for i in range(4)]
for t in threads:
    t.start()
for t in threads:
    t.join()

encoder.close()

GIL ビルドとの互換性

Free Threading 対応コードは GIL ビルド(通常の Python)でも動作します。nb::ft_mutex は GIL ビルドではノーオペレーションとなるため、パフォーマンスへの影響はありません。

メモリ管理とパフォーマンス

メモリ管理の実装方式

  1. 初期化時:データのコピーが発生(安全性重視)
  2. planes() メソッド:内部データのビューを返す(コピーなし)
  3. copy_to() メソッド:destination バッファに書き込み(WebCodecs API 準拠)
  4. エンコーダー/デコーダー:自動的に内部コピーを作成(セグフォ防止)

使い分けガイドライン

用途 推奨メソッド 理由
データの読み取り planes() 内部データへの高速アクセス
データの保存・処理 copy_to() 独立したコピーが必要な場合
エンコード/デコード 通常通り encode() / decode() 自動的に安全なコピーを作成
VideoFrame のフォーマット変換 copy_to(dest, {"format": ...}) WebCodecs API 準拠の変換
AudioData のフォーマット変換 copy_to(dest, {"format": ...}) WebCodecs API 準拠の変換

パフォーマンスの考慮事項

  • 初期化コスト:VideoFrame 作成時に 1 回のコピーが発生
  • エンコード時:内部で安全なコピーを自動作成(追加コピー)
  • planes() 使用時:コピーなし(高速)
  • copy_to() 使用時:destination バッファに書き込み(WebCodecs API 準拠)

この実装により、セグメンテーションフォルトを防ぎつつ、読み取り操作では高速なアクセスを提供しています。

注意事項

  1. メモリ管理
    • planes() でビューを取得した場合、VideoFrame/AudioData の生存期間に注意
    • ハードウェアエンコーダーを使用する場合は copy_to() を推奨
  2. スレッドセーフティ
    • エンコーダー/デコーダーは Free Threading 環境(Python 3.13t / 3.14t)でスレッドセーフ
    • コールバックの変更・呼び出しは内部で排他制御される
    • 詳細は「Free Threading 対応」セクションを参照
  3. プラットフォーム依存
    • VideoToolbox (H.264/H.265) は macOS のみ
    • AudioToolbox (AAC) は macOS のみ
    • libvpx (VP8/VP9) は macOS / Ubuntu
  4. H.264/H.265 ビットストリームフォーマット
    • VideoDecoder は Annex B 形式のみ対応
      • スタートコード(0x00 0x00 0x01 または 0x00 0x00 0x00 0x01)で区切られた NAL ユニット
      • キーフレームには SPS/PPS(H.264)または VPS/SPS/PPS(H.265)が含まれる必要あり
    • VideoEncoder はデフォルトで length-prefixed 形式(avc/hevc)を出力
      • WebCodecs API 仕様に準拠
      • Annex B 形式で出力する場合は avc: {"format": "annexb"} または hevc: {"format": "annexb"} を指定
    • 用途別推奨設定:
      • ライブストリーミング(WebRTC、RTP): "avc": {"format": "annexb"} を指定
      • MP4 ファイル保存: デフォルト(avc/hevc 形式)を使用し、そのまま muxer に渡す
      • エンコード→デコードのパイプライン: "avc": {"format": "annexb"} を指定

今後の実装予定

  1. 色空間サポート
    • VideoColorSpace インターフェースの完全実装
    • 色空間変換の改善
  2. メタデータサポート
    • エンコード/デコード時のメタデータ処理
    • フレームメタデータの管理
  3. ハードウェアアクセラレーション
    • Windows/Linux でのハードウェアアクセラレーション対応
  4. OpenH264 対応
    • libopenh264 を使用した H.264 エンコーディング/デコーディング
    • 外部読み込みファイル対応

参考資料