webcodecs-py は WebCodecs API を Python から扱うためのバインディングであり、リアルタイム処理向けに最適化しています。
- 最終更新: 2026-01-26
- 基準仕様: W3C WebCodecs
- 日付: 2025-11-19
- commit: 66a81b2
webcodecs-py は WebCodecs API にできるだけ準拠しつつ、以下の方針で実装しています:
- Python エコシステムとの親和性: Python の命名規則やイディオムに従う
- リアルタイム用途の最適化: WebRTC、Media over QUIC でのリアルタイム処理を想定
- ndarray の活用: バッファの入出力に numpy.ndarray を前提とし、Python エコシステムとの連携を容易にする
- 型安全性: 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 の 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 |
encoder.addEventListener('dequeue', () => {
// イベントハンドラ
});
encoder.ondequeue = () => {
// イベントハンドラ
};# コンストラクタでコールバックを指定
encoder = VideoEncoder(
on_output=lambda chunk: ...,
on_error=lambda error: ...
)
# dequeue イベントは後から設定可能
encoder.on_dequeue(lambda: ...)理由: Python には JavaScript の EventTarget に相当する標準的なイベントシステムがないため、コールバック方式を採用しています。
await encoder.flush(); // Promise を返す
const support = await VideoEncoder.isConfigSupported(config);# 現在は同期的に実行
encoder.flush()
# is_config_supported は同期的
support = VideoDecoder.is_config_supported(config)理由: Python では同期的な処理を採用しています。
注: WebCodecs 仕様に準拠した並列処理は実装済みです。encode() / decode() メソッドは即座に返り、実際の処理はバックグラウンドのワーカースレッドで実行されます。
const encoder = new VideoEncoder({
output: (chunk, metadata) => { ... },
error: (error) => { ... }
});# コールバックを直接コンストラクタに渡す
encoder = VideoEncoder(
on_output=lambda chunk: ...,
on_error=lambda error: ...
)
# または位置引数で
encoder = VideoEncoder(output_callback, error_callback)理由: Python のシンプルさを重視し、コールバックは直接コンストラクタで指定する方式を採用しています。
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_configSvcOutputMetadata- EncodedVideoChunkMetadata の svc (scalabilityMode 指定時のみ)
Result 系 (メソッドの戻り値):
ImageDecodeResult- ImageDecoder.decode() の戻り値
- JavaScript の Promise を返すメソッドは、Python では通常の同期メソッドとして実装
- 非同期処理は内部的に処理
- VideoFrame と AudioData の内部バッファへのビューを返す独自拡張
planes()メソッドはコピーなしで内部データにアクセス可能
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() メソッド(独自拡張)を使用してください。
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)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)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)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)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)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)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)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)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)| プロパティ | 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 | - | 未実装 |
| プロパティ | 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) |
| プロパティ | 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 |
| プロパティ | 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 | - | 未実装 |
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| プロパティ | 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 |
| プロパティ | 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(実際に使用される) |
| メソッド/プロパティ | 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 | 独自拡張: 特定チャンネルのデータを返す |
| メソッド/プロパティ | 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 に書き込み |
| メソッド/プロパティ | 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 はコンストラクタで指定) |
| メソッド/プロパティ | 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 はコンストラクタで指定) |
| メソッド/プロパティ | 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)
| メソッド/プロパティ | 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 に書き込み |
| メソッド/プロパティ | 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 はコンストラクタで指定) |
| メソッド/プロパティ | 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 がないため)
内部バッファに直接アクセスする独自拡張メソッド
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 も変更されるエンコーダーが直接利用できるプロパティ(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 は以下の 3 つのモードで動作します:
-
外部メモリ参照モード (コンストラクタで ndarray を渡した場合)
- 元の ndarray への参照を保持
- planes() メソッドは内部バッファに直接アクセスできる
- copy_to() メソッドはデータのコピーを返す
-
内部メモリ所有モード (width, height, format で作成した場合)
- 内部でメモリを確保し所有
- planes() メソッドは内部メモリへのビューを返す
- copy_to() メソッドはデータのコピーを返す
-
native_buffer モード (コンストラクタで PyCapsule を渡した場合、macOS のみ)
- CVPixelBufferRef への参照のみを保持(データは保持しない)
- planes() / plane() / copy_to() は使用不可(RuntimeError)
- Video Toolbox エンコーダーが直接利用可能
| プロパティ | Python | WebCodecs API | 備考 |
|---|---|---|---|
offset |
o | o | |
stride |
o | o |
| プロパティ | Python | WebCodecs API | 備考 |
|---|---|---|---|
x |
o | o | |
y |
o | o | |
width |
o | o | |
height |
o | o |
| プロパティ | Python | WebCodecs API | 備考 |
|---|---|---|---|
primaries |
o | o | |
transfer |
o | o | |
matrix |
o | o | |
full_range |
o | o |
UNCONFIGURED- 未設定状態CONFIGURED- 設定済み状態CLOSED- クローズ済み状態
実装済みのフォーマット:
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:0I420A,I420AP10,I420AP12- アルファ付き YUV 4:2:0I422P10,I422P12- 10/12bit YUV 4:2:2I422A,I422AP10,I422AP12- アルファ付き YUV 4:2:2I444P10,I444P12- 10/12bit YUV 4:4:4I444A,I444AP10,I444AP12- アルファ付き YUV 4:4:4RGBX,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 ではこれらのライブラリとの相互運用性を重視し、独自拡張として RGB と BGR をサポートしています。
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)実装済みのフォーマット:
U8,S16,S32,F32- インターリーブフォーマットU8_PLANAR,S16_PLANAR,S32_PLANAR,F32_PLANAR- プレーナーフォーマット
KEY- キーフレームDELTA- 差分フレーム
ハードウェアアクセラレーションエンジンを指定する 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の指定が必要
エンコーダーのレイテンシーモードを指定する ENUM:
QUALITY- 品質優先モード(デフォルト)REALTIME- リアルタイム優先モード
使用例:
from webcodecs import VideoEncoder, VideoEncoderConfig, LatencyMode
config: VideoEncoderConfig = {
"codec": "av1",
"width": 1920,
"height": 1080,
"latency_mode": LatencyMode.REALTIME
}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
}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
}アルファチャンネルの処理方法を指定する ENUM:
KEEP- アルファチャンネルを保持DISCARD- アルファチャンネルを破棄(デフォルト)
使用例:
from webcodecs import VideoEncoder, VideoEncoderConfig, AlphaOption
config: VideoEncoderConfig = {
"codec": "av1",
"width": 1920,
"height": 1080,
"alpha": AlphaOption.DISCARD
}ハードウェアアクセラレーションの優先度を指定する ENUM:
NO_PREFERENCE- 指定なし(デフォルト)PREFER_HARDWARE- ハードウェア優先PREFER_SOFTWARE- ソフトウェア優先
注: このオプションは現在フィールド定義のみで、実際には HardwareAccelerationEngine 独自拡張を使用してください。
色空間の原色を指定する ENUM:
BT709- ITU-R BT.709BT470BG- ITU-R BT.470BGSMPTE170M- SMPTE 170MBT2020- ITU-R BT.2020SMPTE432- SMPTE ST 432-1 (DCI-P3)
伝達特性を指定する ENUM:
BT709- ITU-R BT.709SMPTE170M- SMPTE 170MIEC61966_2_1- IEC 61966-2-1 (sRGB)LINEAR- リニアPQ- SMPTE ST 2084 (PQ)HLG- ARIB STD-B67 (HLG)
行列係数を指定する ENUM:
RGB- RGB (行列変換なし)BT709- ITU-R BT.709BT470BG- ITU-R BT.470BGSMPTE170M- SMPTE 170MBT2020_NCL- ITU-R BT.2020 non-constant luminance
独自拡張関数 - 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 標準、h265やhevcではない)vp8- VP8 (WebCodecs 標準)vp09- VP9 (WebCodecs 標準、vp9ではない)
実装詳細:
- macOS では VideoToolbox の実際の利用可能性を
VTCompressionSessionCreate()で確認 - macOS では libvpx による VP8/VP9 が利用可能
- 各プラットフォームで実際にサポートされているコーデックのみを返す
- 未実装のエンジン (NVIDIA、INTEL、AMD) は結果に含まれない
独自拡張関数 - 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) |
AVCNalUnitType と HEVCNalUnitType は 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}")| プロパティ | 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 | - | 未実装 |
| プロパティ | Python | WebCodecs API | テスト | 備考 |
|---|---|---|---|---|
frame_index |
o | o | o | デフォルト 0 |
complete_frames_only |
o | o | - | デフォルト true |
| プロパティ | Python | WebCodecs API | テスト | 備考 |
|---|---|---|---|---|
image |
o | o | o | VideoFrame |
complete |
o | o | o | デコード完了フラグ |
| メソッド/プロパティ | 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 フレームワークを使用しています。他のプラットフォームでは利用できません。
| メソッド/プロパティ | 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 の同期版 |
| メソッド/プロパティ | Python | WebCodecs API | テスト | 備考 |
|---|---|---|---|---|
animated |
o | o | o | |
frame_count |
o | o | o | |
repetition_count |
o | o | o | |
selected |
o | o | o | 読み書き可能 |
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 |
未実装 |
| コーデック | エンコード | デコード | ライブラリ/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 モードが適用されます。
| コーデック | エンコード | デコード | ライブラリ/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) # 処理待ちタスク数plane(),planes()メソッドは内部バッファへのビューを返す(コピーなし)
- Python のガベージコレクションと C++ オブジェクトのライフサイクル管理を適切に統合
close()メソッドによる明示的なリソース解放をサポート- ワーカースレッドでの shared_ptr 使用によるメモリ安全性の確保
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()Free Threading 対応コードは GIL ビルド(通常の Python)でも動作します。nb::ft_mutex は GIL ビルドではノーオペレーションとなるため、パフォーマンスへの影響はありません。
- 初期化時:データのコピーが発生(安全性重視)
- planes() メソッド:内部データのビューを返す(コピーなし)
- copy_to() メソッド:destination バッファに書き込み(WebCodecs API 準拠)
- エンコーダー/デコーダー:自動的に内部コピーを作成(セグフォ防止)
| 用途 | 推奨メソッド | 理由 |
|---|---|---|
| データの読み取り | 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 準拠)
この実装により、セグメンテーションフォルトを防ぎつつ、読み取り操作では高速なアクセスを提供しています。
- メモリ管理
- planes() でビューを取得した場合、VideoFrame/AudioData の生存期間に注意
- ハードウェアエンコーダーを使用する場合は copy_to() を推奨
- スレッドセーフティ
- エンコーダー/デコーダーは Free Threading 環境(Python 3.13t / 3.14t)でスレッドセーフ
- コールバックの変更・呼び出しは内部で排他制御される
- 詳細は「Free Threading 対応」セクションを参照
- プラットフォーム依存
- VideoToolbox (H.264/H.265) は macOS のみ
- AudioToolbox (AAC) は macOS のみ
- libvpx (VP8/VP9) は macOS / Ubuntu
- 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"}を指定
- ライブストリーミング(WebRTC、RTP):
- VideoDecoder は Annex B 形式のみ対応
- 色空間サポート
- VideoColorSpace インターフェースの完全実装
- 色空間変換の改善
- メタデータサポート
- エンコード/デコード時のメタデータ処理
- フレームメタデータの管理
- ハードウェアアクセラレーション
- Windows/Linux でのハードウェアアクセラレーション対応
- OpenH264 対応
- libopenh264 を使用した H.264 エンコーディング/デコーディング
- 外部読み込みファイル対応