WebCodecs API実践:ブラウザ側低遅延音声動画エンコード・デコード
技术架构(更新: 2026年6月14日)
ブラウザ音声動画処理の進化
| 手法 | 遅延 | フレームレベル制御 | コーデックアクセス | 適用場面 |
|---|---|---|---|---|
<video> + MSE |
2-5s | ❌ | コンテナ形式 | 再生、ストリーミング |
| FFmpeg.wasm | 1-3s | ✅ | 完全 | トランスコード(ただし30MB+) |
| WebCodecs | <100ms | ✅ | ネイティブ | リアルタイム処理、低遅延トランスコード |
WebCodecsはブラウザ内蔵コーデックへの直接アクセスを提供。WASMラッパー不要で遅延を10-50分の1に削減。
コアオブジェクト概要
VideoFrame ←→ VideoEncoder ←→ EncodedVideoChunk
↓ ネットワーク / ストレージ
AudioData ←→ AudioEncoder ←→ EncodedAudioChunk
↓
VideoFrame ←→ VideoDecoder ←→ EncodedVideoChunk
AudioData ←→ AudioDecoder ←→ EncodedAudioChunk
VideoFrame:ゼロコピーフレーム操作
const frame = new VideoFrame(canvas, { timestamp: performance.now() * 1000 });
const bitmap = await createImageBitmap(videoElement);
const frame2 = new VideoFrame(bitmap, { timestamp: 0 });
console.log(frame.width, frame.height, frame.duration, frame.timestamp);
frame.close();
重要:VideoFrameはGPUテクスチャ参照を保持します。
close()を呼んで解放しないとGPUメモリリークが発生します。
VideoEncoder:動画エンコード
const encoder = new VideoEncoder({
output: (chunk, metadata) => {
const data = new Uint8Array(chunk.byteLength);
chunk.copyTo(data);
handleEncodedChunk(chunk.type, data, chunk.timestamp, metadata);
},
error: (e) => console.error('エンコードエラー:', e),
});
encoder.configure({
codec: 'avc1.64001E',
width: 1920,
height: 1080,
bitrate: 5_000_000,
framerate: 30,
});
encoder.encode(frame, { keyFrame: true });
frame.close();
サポートコーデック
| コーデック | codec文字列 | 特徴 |
|---|---|---|
| H.264 | avc1.64001E |
最も広い互換性 |
| H.265 | hev1.1.6.L93.B0 |
圧縮率40%向上、互換性制限 |
| VP8 | vp8 |
WebM形式 |
| VP9 | vp9 |
YouTubeデフォルト |
| AV1 | av01.0.01M.08 |
次世代、最高圧縮率 |
VideoDecoder:動画デコード
const decoder = new VideoDecoder({
output: (frame) => {
ctx.drawImage(frame, 0, 0);
frame.close();
},
error: (e) => console.error('デコードエラー:', e),
});
decoder.configure({
codec: 'avc1.64001E',
codedWidth: 1920,
codedHeight: 1080,
});
const chunk = new EncodedVideoChunk({
type: isKeyFrame ? 'key' : 'delta',
timestamp: timestamp,
data: encodedData,
});
decoder.decode(chunk);
AudioEncoder / AudioDecoder
const audioEncoder = new AudioEncoder({
output: (chunk) => {
const data = new Uint8Array(chunk.byteLength);
chunk.copyTo(data);
handleAudioChunk(data, chunk.timestamp);
},
error: (e) => console.error(e),
});
audioEncoder.configure({
codec: 'aac',
sampleRate: 48000,
numberOfChannels: 2,
bitrate: 128000,
});
const audioData = new AudioData({
format: 'f32-planar',
sampleRate: 48000,
numberOfFrames: 1024,
numberOfChannels: 2,
timestamp: 0,
data: float32Array,
});
audioEncoder.encode(audioData);
audioData.close();
実践:動画形式トランスコードパイプライン
ToolsKuの動画変換のコアトランスコードフロー:
async function transcodeVideo(inputChunks: EncodedVideoChunk[], config: TranscodeConfig) {
const decodedFrames: VideoFrame[] = [];
const decoder = new VideoDecoder({
output: (frame) => decodedFrames.push(frame),
error: (e) => { throw e; },
});
decoder.configure(inputConfig);
for (const chunk of inputChunks) {
decoder.decode(chunk);
}
await decoder.flush();
const encoder = new VideoEncoder({
output: (chunk) => muxer.addChunk(chunk),
error: (e) => { throw e; },
});
encoder.configure(config.outputCodec);
for (const frame of decodedFrames) {
encoder.encode(frame);
frame.close();
}
await encoder.flush();
return muxer.finalize();
}
MSEとの比較:低遅延シナリオ
| 指標 | MSE (MediaSource) | WebCodecs |
|---|---|---|
| 初フレーム遅延 | 2-5s(バッファリング戦略) | <100ms |
| フレームレベル制御 | ❌ appendBufferのみ | ✅ フレーム単位エンコード/デコード |
| リアルタイム処理 | ❌ 追加ミュクシング必要 | ✅ ネイティブサポート |
| メモリ使用量 | 高(バッファキュー) | 低(フレーム単位処理) |
| 適用 | 動画再生 | リアルタイム通信、トランスコード、解析 |
パフォーマンス実測:動画圧縮シナリオ
1080p 30fps 60秒動画のH.264→H.265トランスコード:
| 手法 | トランスコード時間 | 出力サイズ | 遅延 |
|---|---|---|---|
| FFmpeg.wasm | 180s | 12MB | 3s(WASM初期化) |
| WebCodecs | 45s | 12MB | <100ms |
WebCodecsはブラウザネイティブコーデックを活用—4倍高速、30MB+のWASMダウンロード不要。
よくある質問
WebCodecsはどのコンテナ形式をサポートするか?
WebCodecsは生のエンコードチャンクのみを処理し、コンテナミュクシングは行いません。mp4-muxerやwebm-muxer等のライブラリでMP4/WebMにパッケージ化する必要があります。
動画ファイルからエンコードデータを取得する方法?
MP4 demuxer(mp4box.js等)でMP4ファイルを分離し、EncodedVideoChunkを抽出してDecoderに入力します。
VideoFrameはWorker間で転送可能か?
可能です。VideoFrameはTransferableを実装しており、postMessage(frame, [frame])でゼロコピー転送してWorkerで処理できます。
まとめ
WebCodecs APIはブラウザに音声動画コーデックへの直接アクセスを提供し、ゼロコピーフレーム処理と<100ms遅延のエンコード/デコードを実現します。VideoEncoder/Decoderが動画、AudioEncoder/Decoderが音声、VideoFrame/AudioDataがフレームレベル操作を担います。demuxer/muxerライブラリと組み合わせることで、ブラウザ側で完全な低遅延動画トランスコードパイプラインを構築できます。
ブラウザローカルツールを無料で試す →
#WebCodecs#视频编解码#AudioData#VideoFrame#低延迟