WebCodecs動画処理実践:ブラウザネイティブ動画エンコード/デコードの5つのコアパターン
前端工程
WebCodecs動画処理:ブラウザネイティブの動画コーデック能力
FFmpeg.wasmは大容量で読み込みが遅い、Canvasフレーム処理はパフォーマンスが低い、WebRTCはブラックボックスでカスタマイズ不可——ブラウザ動画処理は長年制約されてきました。WebCodecs APIは低レベルの動画コーデック機能を提供し、H.264/H.265/VP9/AV1をサポート、ゼロコピーで生フレームデータにアクセスでき、ネイティブアプリに迫るパフォーマンスを実現。2026年、WebCodecsはChromeとEdgeで完全サポートされ、ブラウザ動画編集とリアルタイムエンコーディングが現実になりました。
本記事では5つのコアパターンを通じて、VideoDecoder→VideoEncoder→フレーム処理→リアルタイムトランスコード→動画録画のフルチェーン実践を解説します。
コア概念
| 概念 | 説明 |
|---|---|
| WebCodecs | ブラウザネイティブ動画/音声コーデックAPI |
| VideoDecoder | 動画デコーダー、エンコードデータを生フレームに変換 |
| VideoEncoder | 動画エンコーダー、生フレームをエンコードデータに変換 |
| VideoFrame | ピクセルデータとメタデータを含む動画フレームオブジェクト |
| EncodedVideoChunk | エンコードされた動画データチャンク |
| hardwareAcceleration | ハードウェアアクセラレーション設定 |
問題分析:WebCodecsの5つの課題
- 低レベルAPI抽象化:フレームライフサイクルとメモリの手動管理が必要
- コーデックサポートの差異:ブラウザ/プラットフォームごとにサポートcodecが異なる
- キーフレーム管理:デコードに正しいキーフレームシーケンスが必要
- パフォーマンスチューニング:ハードウェアアクセラレーション設定とフレームレート制御
- デバッグの困難さ:コーデックエラーメッセージが不親切
ステップバイステップ:5つのWebCodecsパターン
パターン1:VideoDecoder動画デコード
const decoder = new VideoDecoder({
output: (frame: VideoFrame) => { processFrame(frame); frame.close(); },
error: (e: Error) => console.error(e),
});
decoder.configure({
codec: "avc1.64001f",
codedWidth: 1920, codedHeight: 1080,
hardwareAcceleration: "prefer-hardware",
});
パターン2:VideoEncoder動画エンコード
const encoder = new VideoEncoder({
output: (chunk) => encodedChunks.push(chunk),
error: (e) => console.error(e),
});
encoder.configure({
codec: "avc1.64001f",
width: 1920, height: 1080,
bitrate: 5_000_000, framerate: 30, keyInterval: 30,
});
パターン3:リアルタイムフレーム処理とフィルター
onDecodedFrame(frame: VideoFrame) {
this.ctx.drawImage(frame, 0, 0);
frame.close();
const processedFrame = new VideoFrame(this.canvas, { timestamp: frame.timestamp });
this.encoder.encode(processedFrame);
processedFrame.close();
}
パターン4:動画フォーマットトランスコード
async function transcodeVideo(inputChunks, inputCodec, outputCodec, width, height) {
const decoder = new VideoDecoder({
output: (frame) => { encoder.encode(frame); frame.close(); },
error: (e) => console.error(e),
});
const encoder = new VideoEncoder({
output: (chunk) => outputChunks.push(chunk),
error: (e) => console.error(e),
});
decoder.configure({ codec: inputCodec, codedWidth: width, codedHeight: height });
encoder.configure({ codec: outputCodec, width, height, bitrate: 4_000_000, framerate: 30 });
}
パターン5:MediaStreamリアルタイム録画
async function recordScreen() {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: { width: 1920, height: 1080, frameRate: 30 },
});
const processor = new MediaStreamTrackProcessor({ track: stream.getVideoTracks()[0] });
const reader = processor.readable.getReader();
while (true) {
const { done, value: frame } = await reader.read();
if (done) break;
encoder.encode(frame); frame.close();
}
}
落とし穴ガイド
落とし穴1:VideoFrame未クローズによるメモリリーク
// ✅ 正しい:使用後すぐにクローズ
output: (frame) => { processFrame(frame); frame.close(); }
落とし穴2:コーデック非対応
const support = await VideoDecoder.isConfigSupported({ codec: "avc1.64001f" });
if (!support.supported) throw new Error("Codec not supported");
落とし穴3:最初のフレームがキーフレームではない
const chunk = new EncodedVideoChunk({ type: "key", timestamp: 0, data });
落とし穴4:エンコーダーbitrateが低すぎる
encoder.configure({ bitrate: 5_000_000 }); // 1080pは5Mbps
落とし穴5:メインスレッドで大量フレーム処理
const worker = new Worker("video-processor.js");
worker.postMessage({ frame }, [frame]);
エラートラブルシューティング
| # | エラー | 原因 | 解決方法 |
|---|---|---|---|
| 1 | NotSupportedError |
コーデック非対応 | isConfigSupportedで確認 |
| 2 | InvalidStateError |
エンコーダー/デコーダー状態エラー | configure後にencode/decodeを実行 |
| 3 | OutOfMemoryError |
フレーム未クローズでメモリリーク | frame.close()を毎回呼び出し |
| 4 | EncodingError |
エンコードパラメータ不正 | bitrate、解像度、framerateを確認 |
| 5 | Hardware acceleration unavailable |
HWアクセラレーション不可 | softwareモードにフォールバック |
| 6 | Key frame required |
キーフレーム不足 | 最初のフレームと定期キーフレームを確保 |
| 7 | Timestamp discontinuity |
タイムスタンプ不連続 | タイムスタンプの単調増加を確保 |
| 8 | Codec string invalid |
codec文字列フォーマットエラー | 標準codec文字列を使用 |
高度な最適化
- Web Worker並列エンコード/デコード:コーデック操作をWorkerに移動しメインスレッドをブロック回避
- ハードウェアアクセラレーション優先:prefer-hardware設定でGPUコーデックを活用
- キーフレーム間隔チューニング:シナリオに応じてkeyIntervalを調整
- アダプティブビットレートABR:ネットワーク状況に応じてbitrateを動的調整
- WebGPUアクセラレーションフィルター:Compute Shaderで動画フレーム効果を処理
比較分析
| 次元 | WebCodecs | FFmpeg.wasm | Canvasフレーム処理 | WebRTC |
|---|---|---|---|---|
| コーデックパフォーマンス | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| フォーマットサポート | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
| カスタマイズ性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| 読み込みサイズ | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| ブラウザサポート | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
まとめ:WebCodecsはブラウザにネイティブレベルの動画コーデック能力をもたらし、FFmpeg.wasmやCanvasソリューションを大幅に凌駕するパフォーマンスを発揮します。WebCodecsはブラウザ側動画処理が必要なアプリケーションに適しており、特に動画エディター、リアルタイムトランスコード、画面録画に最適です。2026年のChrome/Edge完全サポートにより、次世代Web動画アプリケーションの基盤となります。
オンラインツール推薦
- JSONフォーマッター:/ja/json/format
- Hash計算:/ja/encode/hash
- cURL to Code:/ja/dev/curl-to-code
ブラウザローカルツールを無料で試す →
#WebCodecs#视频处理#浏览器视频#编解码#2026#前端工程