WebCodecs API
動画のエンコード・デコードをブラウザ内蔵コーデックへ直接アクセスして高速化できる。フレーム単位の制御でMediaStreamでは不可能だった低遅延処理と柔軟なトランスコードが実現する。
- 1.WebCodecsはOS/ブラウザ内蔵のハードウェアコーデックへ生の圧縮バイト列・生フレーム単位でアクセスできるAPIで、`<video>`やMediaRecorderのような高水準の抽象を経由しない。
- 2.エンコーダ・デコーダは非同期キューを持ち、`configure`でコーデックを設定し`encode`/`decode`を呼ぶ。デコーダの出力は仕様上『提示順』が保証されるが、エンコーダの出力順は仕様上保証されず実装依存になりうる。
- 3.VideoFrame/EncodedVideoChunkはGPU/共有メモリ上のリソースを参照するため、使い終わったら明示的に`close()`しないとメモリを圧迫する。
何を解決するAPIか
ブラウザは長年、動画の符号化・復号を<video>要素やMediaRecorder、MediaStreamといった高水準の箱の中に隠してきました。これらは「再生する」「録画する」という用途には便利ですが、フレーム単位で画素を触ったり、任意のタイミングでエンコード設定を変えたり、コーデック処理だけを取り出して独自パイプラインに組み込むことはできません。WebCodecs APIは、この隠蔽を剥がし、ブラウザやOSに実装済みのハードウェア/ソフトウェアコーデックへフレーム単位・チャンク単位で直接アクセスする低レベルAPIです。
対象はH.264/H.265、VP8/VP9、AV1、Opus、AACなど、実行環境が対応するコーデック群です。WebCodecs自体はコーデックを実装せず、あくまで既存実装への薄いラッパーである点が設計の要になります。
MediaStreamとの違い
MediaStreamは「カメラや<video>から連続的に流れてくる映像・音声トラック」という連続ストリームの抽象です。トラックの中身がどうエンコードされているかは意識せず、ブラウザが内部で自動的に処理します。対してWebCodecsは、その内部処理を担っていたエンコーダ・デコーダ自体を個別のオブジェクトとして取り出し、1フレームずつ入出力させます。
| 観点 | MediaStream / MediaRecorder | WebCodecs |
|---|---|---|
| 抽象度 | トラック単位(連続ストリーム) | フレーム/チャンク単位 |
| 制御粒度 | ビットレート等の大まかな設定のみ | フレームごとに鍵フレーム指定・QP調整等が可能 |
| データ取得 | 録画結果のBlobなど事後取得が中心 | エンコード直後のバイト列に即アクセス |
| 典型用途 | カメラ映像の表示・簡易録画 | リアルタイム加工、トランスコード、独自コンテナ出力 |
たとえば「WebRTCで受信した映像にリアルタイムでフィルタをかけてから再送信する」「録画ファイルを別コーデックへ変換する」といった処理は、MediaStreamの抽象では困難でした。WebRTCのRTCPeerConnectionと組み合わせるInsertable Streamsはまさにこの隙間を埋める用途で設計されています。
WebCodecsが扱うのは圧縮された生データ(elementary stream)までで、MP4やWebMのようなコンテナへの多重化・分離(mux/demux)は対象外です。ファイル入出力を行うには、mp4boxやmatroska実装などのJSライブラリと組み合わせる必要があります。
フレームとチャンクという2つの単位
WebCodecsの中心には2種類のオブジェクトがあります。**VideoFrameは非圧縮の生画素データ(またはGPU上のリソースへの参照)を表し、EncodedVideoChunk**は圧縮済みバイト列と鍵フレーム種別・タイムスタンプを表します。エンコーダはVideoFrameを受け取りEncodedVideoChunkを出力し、デコーダはその逆を行います。
カメラ/canvas → VideoFrame → [VideoEncoder] → EncodedVideoChunk → 送信/保存
受信/読込 → EncodedVideoChunk → [VideoDecoder] → VideoFrame → 描画/加工
エンコーダ・デコーダはどちらも非同期のパイプラインとして動きます。configure()でコーデック・解像度・ビットレート等を指定し、encode()/decode()を呼ぶと即座には結果を返さず、内部キューに投入されるだけです。処理が終わった出力は、configure()時に渡したoutputコールバックへ非同期に届きます。
const encoder = new VideoEncoder({
output: (chunk, metadata) => sendChunk(chunk, metadata),
error: (e) => console.error(e),
});
encoder.configure({
codec: "vp09.00.10.08",
width: 1280,
height: 720,
bitrate: 2_000_000,
framerate: 30,
});
encoder.encode(videoFrame, { keyFrame: needsKeyFrame });
videoFrame.close(); // 参照を明示的に解放
仕様が明確に順序を保証しているのはデコーダ側で、VideoDecoderの出力は常に「提示順(presentation order)」で届きます。これはH.264/H.265のBフレームのようにフレーム間予測(表示順より後のフレームを参照する圧縮)を使うコーデックでは、コーデック内部のデコード順と最終的な表示順が一致しないため、ブラウザ実装が並べ替えを行った上で提示順に揃えて出力する必要があるからです。一方エンコーダ側は仕様上そこまでの順序保証がなく、encode()に渡した順序とoutputコールバックの発火順が実装依存でずれる余地がある点に注意が必要です。またencode自体は呼び出しごとにブロックしない設計のため、キューの深さ(encodeQueueSize)を監視し、詰まりすぎたら新規フレームの投入を間引くバックプレッシャー制御が実務では必須になります。これはStreams APIのバックプレッシャーと同じ考え方です。
リソース管理とclose()の重要性
VideoFrameやEncodedVideoChunk、AudioDataは、内部でGPUメモリや共有メモリ上のバッファを保持していることがあります。これらはガベージコレクションに任せると解放が遅れ、特に高フレームレートの映像処理では数フレーム分の遅延だけでメモリを使い切るリスクがあります。
VideoFrameはGC対象ではありますが、GCのタイミングは保証されません。encode()や描画に渡した後、そのフレームが不要になった時点で必ずclose()を呼び、参照しているバッファを即座に解放してください。特にWorker間でtransferせずコピーを繰り返すと、明示的closeなしでは容易にメモリ圧迫を招きます。
処理をWeb Workerに移し、VideoFrameをpostMessageの第2引数(transfer list)で転送すれば、コピーコストなしにメインスレッドをブロックせず処理できます。WebCodecsの多くの操作はメインスレッド外でも動作するため、リアルタイム映像処理のパイプラインをWorker内に閉じ込める設計と相性が良いです。
ハードウェアアクセラレーションとhardwareAcceleration
VideoEncoderConfig/VideoDecoderConfigにはhardwareAcceleration("no-preference" / "prefer-hardware" / "prefer-software")が指定できます。ハードウェアコーデックは省電力・高速な一方、対応解像度やビットレート制御の柔軟性がソフトウェア実装より劣ることがあり、正確なビットレート制御が必要なトランスコード用途では意図的にソフトウェアを選ぶ判断もあり得ます。実際にどのコーデック・解像度の組み合わせが使えるかは、VideoEncoder.isConfigSupported()で事前に問い合わせるのが安全です。
WebCodecsは「コーデックを実装するAPI」ではなく「既存のコーデック実装へのアクセスを提供するAPI」である点、デコーダの出力コールバックは提示順序を保つ一方でエンコーダの出力順序は仕様上保証されない点、フレーム系オブジェクトはclose()で明示的にリソース解放が必要な点の3つが頻出です。MediaStreamとの違いを「抽象度(トラック単位 vs フレーム単位)」で説明できるようにしておきましょう。
リアルタイム処理とトランスコードでの活用
代表的な用途は2つに大別できます。ひとつはリアルタイム映像処理で、受信したEncodedVideoChunkをデコードしてVideoFrameを得たあと、canvasやWebGL/WebGPUで背景ぼかしやフィルタなどのGPU処理を挟み、再エンコードして送り出すパイプラインです。もうひとつはトランスコードで、あるコーデックのファイルをデコードし、別コーデック・別ビットレートで再エンコードする、サーバーを介さないブラウザ内変換が可能になります。
いずれも「フレームを止めて加工し、また流す」という制御が要点で、これはMediaStreamの連続ストリーム抽象では実現できなかった領域です。WebCodecsはこの中間層を公開することで、ブラウザを本格的な映像処理基盤として使えるようにしています。
Web/フロントエンド Article
WebCodecs APIを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
WebCodecs
比較で見る軸
難易度: advanced / カテゴリ: Web/フロントエンド / タグ数: 6
導入後に効く点
エンコーダ・デコーダは非同期キューを持ち、`configure`でコーデックを設定し`encode`/`decode`を呼ぶ。デコーダの出力は仕様上『提示順』が保証されるが、エンコーダの出力順は仕様上保証されず実装依存になりうる。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- Web/フロントエンド
- タグ数
- 6
判断チェックリスト
- 自社の用途が「WebCodecs / 動画処理」に近いか確認する。
- 強みである「WebCodecsはOS/ブラウザ内蔵のハードウェアコーデックへ生の圧縮バイト列・生フレーム単位でアクセスできるAPIで、`<video>`やMediaRecorderのような高水準の抽象を経由しない。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。