Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WebCodecsの実装状況 / Status of WebCodecs
Search
mganeko
June 23, 2023
Technology
0
1.5k
WebCodecsの実装状況 / Status of WebCodecs
WebRTC Meetup Tokyo #24 のLT資料です。
WebCodecsの2023年6月の実装状況についてのまとめです
mganeko
June 23, 2023
Tweet
Share
More Decks by mganeko
See All by mganeko
OpenAI RealTime API WebRTCモード - シグナリングとDataChannelの使い道 -
mganeko
0
240
Canvasで簡易背景ぼかしをやってみた
mganeko
0
960
M1 Macと将棋AIとUSI
mganeko
1
1.4k
Small Tips to use Bun with WebSocket Server and WebAssembly Modules
mganeko
0
5.2k
Build Node.js–WASM/WASI tiny compiler with Node.js
mganeko
0
730
Node.js x Chrome headless for WebRTC MCU
mganeko
1
3.3k
Extend User Experience of WebRTC with Cool Sensor Devices
mganeko
0
680
Playing with OSS WebRTC SFU meidasoup (update for v1.2)
mganeko
0
870
Build WebRTC iOS Gateway on Browser
mganeko
0
1.2k
Other Decks in Technology
See All in Technology
RALGO AIを組織に組み込む方法 -アルゴリズム中心組織設計- #RSGT2026 / RALGO: How to Integrate AI into an Organization – Algorithm-Centric Organizational Design
kyonmm
PRO
2
260
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
10k
ルネサンス開発者を育てる 1on1支援AIエージェント
yusukeshimizu
0
130
Redshift認可、アップデートでどう変わった?
handy
1
120
名刺メーカーDevグループ 紹介資料
sansan33
PRO
0
1k
マーケットプレイス版Oracle WebCenter Content For OCI
oracle4engineer
PRO
5
1.5k
「駆動」って言葉、なんかカッコイイ_Mitz
comucal
PRO
0
130
2025年の医用画像AI/AI×medical_imaging_in_2025_generated_by_AI
tdys13
0
280
re:Invent2025 セッションレポ ~Spec-driven development with Kiro~
nrinetcom
PRO
2
160
Agentic AIが変革するAWSの開発・運用・セキュリティ ~Frontier Agentsを試してみた~ / Agentic AI transforms AWS development, operations, and security I tried Frontier Agents
yuj1osm
0
180
I tried making a solo advent calendar!
zzzzico
0
120
Claude Codeを使った情報整理術
knishioka
16
11k
Featured
See All Featured
Balancing Empowerment & Direction
lara
5
830
Bash Introduction
62gerente
615
210k
RailsConf 2023
tenderlove
30
1.3k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
2
74
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.4k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
180
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.7k
How STYLIGHT went responsive
nonsquared
100
6k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
0
84
Information Architects: The Missing Link in Design Systems
soysaucechin
0
730
[SF Ruby Conf 2025] Rails X
palkan
0
660
Transcript
WebCodecs 実装状況 (2023年6月現在) WebRTC Meetup Tokyo #24 2023.06.23 @massie_g /
が こまさし
WebCodecs APIと • VideoやAudioをエンコード、デコードするAPI • 仕様 ◦ WebCodecs W3C Working
Draft, 11 May 2023 ◦ https://www.w3.org/TR/webcodecs/ • 関連する仕様 ◦ MediaStreamTrack Insertable Media Processing using Streams ▪ Editor’s Draft, 20 October 2022 • https://w3c.github.io/mediacapture-transform/ ▪ Unofficial Proposal Draft, 26 November 2021 • https://alvestrand.github.io/mediacapture-transform/chrome-96.html
https://caniuse.com/webcodecs • Chrome 114 / Edge 114 … Video, Audio
サポート • Safari TP171 … Video みサポート, オプション指定 • Firefox … 未対応
Video
VideoFrame VideoEncoder EncodedVideoChunk EncodedVideoChunk EncodedVideoChunk VideoDecoder VideoFrame VideoEncoder / VideoDecoder
VideoFrame VideoEncoder EncodedVideoChunk EncodedVideoChunk EncodedVideoChunk VideoDecoder VideoFrame VideoFrameを作る/使う <img> <canvas>
<video> ImageBitmap OffscreenCanvas VideoFrame <canvas> コンストラクタ new VideoFrame() drawImage()
VideoFrameを作る const frame = new VideoFrame(element, { timestamp: timestamp_in_micro_second, //
タイムスタンプをμ秒で指定 duration: duration_in_micro_second, // フレーム 長さをμ秒で指定 }); // do something with frame // release frame.close(); 属性 • readonly attribute VideoPixelFormat? format; • readonly attribute unsigned long codedWidth; • readonly attribute unsigned long codedHeight; • readonly attribute DOMRectReadOnly? codedRect; • readonly attribute DOMRectReadOnly? visibleRect; • readonly attribute unsigned long displayWidth; • readonly attribute unsigned long displayHeight; • readonly attribute unsigned long long? duration; // μs • readonly attribute long long timestamp; // μs • readonly attribute VideoColorSpace colorSpace;
VideoFrame フォーマット • 元にした要素により、フォーマットが異なる • ブラウザによっても、フォーマットが異なる 元 要素 Chrome 114
/ Canary 116 (Win10, M1 Mac) afari P 171 (M1 Mac) img(jpeg) BG X GBA canvas GBA GBA video(mp4) NV12 I420 video(camera) I420 I420 • BGRX ◦ Blue, Green, Red, ◦ X:透明度 … 255で透明 • RGBA ◦ Red, Green, Blue ◦ A:αチャンネル … 255で不透明 • YUV420 (NV12, I420) ◦ 画像/映像 情報量を抑える形式 ▪ https://qiita.com/Yossy_Hal/items/8e0b9676698 ba552c210 ◦ Y(輝度), U(青色式差), V(赤色式差) ▪ Y そ まま ▪ U, V 縦横半分に間引く ◦ U, V 並べ方 違いでNV12とI420がある
VideoFrameを使う: Canvasに描画 const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, width, height);
ctx.drawImage(videoframe, 0, 0);
Encode → Decode実験 (1) Encoder const encoder = new VideoEncoder({
output: (chunk) => { // エンコード成功時 処理 }, error: (err) => { /* エラー時 処理 */ } }); await encoder.configure({ codec: CODEC, // コーデック 指定 width: WIDTH, // 幅 指定 height: HEIGHT, // 高さ 指定 framerate: 10 // フレームレート 指定 }); // フレーム取得 const frame = new VideoFrame(element, { timestamp: timestamp_in_micro_second, duration: duration_in_micro_second }); // エンコード (成功すると、output に指定した関数が呼 れ る) encoder.encode(frame, { keyFrame : true}); // true: キーフレーム、false: 差分フレーム frame.close(); // フレームを解放
Encode → Decode実験 (2) Decoder const decoder = new VideoDecoder({
output: (frame) => { // デコード成功時 処理 frame.close(); //フレームを解放 }, error: (err) => { /* エラー時 処理 */ } }); await decoder.configure({ codec: CODEC }); // デコード (成功すると、output に指定した関数が呼 れる) decoder.decode(chunk); // chunk エンコード済み データ
Encode → Decode実験(img, mp4, カメラ映像、全てkeyframe) コーデック Chrome 114 / Canary
116 (Win10, M1 Mac) Safari TP 171 (M1 Mac) デコード結果 デコード後 フォーマット デコード結果 デコード後 フォーマット VP8 〇 2フレーム目 デコードで表示 (outputが呼 れる) I420 〇(img, video:カメラ映像) 1フレーム目 デコードで表示 ✕(video:mp4) 緑色や崩れた描画 I420 VP9 profile0 〇 1フレーム目 デコードで表示 NV12 〇(img, video:カメラ映像) 1フレーム目 デコードで表示 ✕(video:mp4) 緑色や崩れた描画 I420 VP9 profile2 〇 1フレーム目 デコードで表示 null ✕ エラー: Not supported ✕ AV1 〇 4フレーム目 デコードで表示 I420 ✕ NotSupportedError: VPx encoding initialization failed with error -1 ✕ H.264 〇 2フレーム目 デコードで表示 NV12 〇 1フレーム目 デコードで表示 I420
参考: Encoder/Decoder 初期化オプション コーデック encoder.configure() オプション例 decoder.configure() オプション例 VP8 codec
: "vp8" codec : "vp8" VP9 profile0 codec: "vp09.00.10.08" codec: "vp09.00.10.08" VP9 profile2 codec: "vp09.02.10.10" codec: "vp09.02.10.10" AV1 codec: "av01.0.01M.08" codec: "av01.0.01M.08" H.264 codec: "avc1.42001E", avc: { format: "annexb" } codec: "avc1.42001E"
Audio
AudioEncoder EncodedAudioChunk EncodedAudioChunk AudioDecoder AudioEncoder / AudioDecoder AudioData AudioData AudioData
AudioData AudioData AudioData AudioData AudioData AudioData AudioData Chromeで 20ms 長さで分割 EncodedAudioChunk EncodedAudioChunk EncodedAudioChunk EncodedAudioChunk EncodedAudioChunk EncodedAudioChunk Chromeで 48k sample/sec, 20ms 長さ Chromeで 3k~768k sample/sec 長さ 自由
AudioData const audioData = new AudioData({ format: format, // "u8",
"s16", "s32", "f32", (※"f32" み確認) // "u8-planar", "s16-planar", "s32-planar", "f32-planar" sampleRate: sampleRate, // Chromeで 3,000 ~ 768,000 numberOfFrames: frames, // 何個分 サンプルを持っているか numberOfChannels: channels, // 1:モノラル or 2:ステレオ (※1: み確認) timestamp: timestamp, // μ秒で指定 data: data }); ※WebAudio AudioBufferと 異なる。そ ままで 再生できない
AudioEncoder encoder = new AudioEncoder({ output: (chunk) => { //
エンコード成功時 処理 }, error: (err) => { /* エラー時 処理 */ } }); await encoder.configure({ codec: CODEC, numberOfChannels: 1 sampleRate: SAMPLE_RATE, }); 仕様上 CODEC • Audio Codecs https://w3c.github.io/webcodecs/codec_registry.htm l#audio-codec-registry • "flac" ... Flac • "mp3" ... MP3 • "mp4a.*" ... AAC • "opus" ... OPUS • "vorbis" ... Vorbis • "ulaw" ... u-law PCM • "alaw" ... A-law PCM • "pcm-*" ... Linear PCM → 現状Chrome OPUS みサポート
AudioDecoder decoder = new AudioDecoder({ output: async (audioData) => {
// デコード成功時 処理 audioData.close(); }, error: (err) => { /* エラー時 処理 */ } }) await decoder.configure({ codec: CODEC, numberOfChannels: 1, sampleRate: SAMPLE_RATE, }); // エンコード encoder.encode(audioData); // デコード decoder.decode(chunk);
MediaStreamTrack Insertable Media Processing using Streams Processor / Generator
Processor / Generator MediaStream MediaStreamTrack (video) MediaStreamTrack (audio) MediaStreamTrack Processor
MediaStreamTrack Processor VideoFrame AudioData AudioData AudioData MediaStreamTrack Generator MediaStreamTrack Generator MediaStreamTrack (video) MediaStreamTrack (audio) MediaStream Encoder ↓ Decoder VideoFrame AudioData AudioData AudioData
MediaStream/MediaStreamTrackと 組合せ MediaStreamTrack Insertable Media Processing using Streams Unofficial Proposal
Draft, 26 November 2021 Editor’s Draft, 20 October 2022 Chrome 114 (Unofficial Proposal) Safari TP171 未対応 MediaStreamTrack → VideoFrame MediaStreamTrackPr ocessor MediaStreamTrack Processor MediaStreamTrack Processor 未対応 VideoFrame → MediaStreamTrack MediaStreamTrackG enerator VideoTrackGenera tor MediaStreamTrack Generator 未対応 MediaStreamTrack → AudioData MediaStreamTrackPr ocessor MediaStreamTrack Processor MediaStreamTrack Processor 未対応 AudioData → MediaStreamTrack MediaStreamTrackG enerator なし MediaStreamTrack Generator 未対応
まとめ • WebCodecs ◦ Chrome かなり実装もこなれてきた ▪ Chrome限定なら、使える場面もありそう ◦ Safari
まだまだ、Audio無し ▪ Safariで使うなら、H.264が無難 • MediaStreamTrack Insertable Media Processing using Streams ◦ 仕様がまた整理されていない、使うに まだ早い ▪ Chromeで 実験 、もう始められる 個人 見解 • WebCodecsが普及する まだまだ先(5年以上) • し らく WebRTCで行く が吉