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
1.6k
0
Share
WebCodecsの実装状況 / Status of WebCodecs
WebRTC Meetup Tokyo #24 のLT資料です。
WebCodecsの2023年6月の実装状況についてのまとめです
mganeko
June 23, 2023
More Decks by mganeko
See All by mganeko
OpenAI RealTime API WebRTCモード - シグナリングとDataChannelの使い道 -
mganeko
0
290
Canvasで簡易背景ぼかしをやってみた
mganeko
0
1k
M1 Macと将棋AIとUSI
mganeko
2
1.4k
Small Tips to use Bun with WebSocket Server and WebAssembly Modules
mganeko
0
5.3k
Build Node.js–WASM/WASI tiny compiler with Node.js
mganeko
0
760
Node.js x Chrome headless for WebRTC MCU
mganeko
1
3.3k
Extend User Experience of WebRTC with Cool Sensor Devices
mganeko
1
720
Playing with OSS WebRTC SFU meidasoup (update for v1.2)
mganeko
0
910
Build WebRTC iOS Gateway on Browser
mganeko
0
1.2k
Other Decks in Technology
See All in Technology
M&Aで増え続けるプロダクトに少数QAはどう立ち向かうか─GENDAが挑む、全員で取り組む品質標準化戦略 / GENDA Tech Talk #4
genda
0
250
ECSのTerraformモジュールにコントリビュートした話
harukasakihara
0
260
パーソルキャリア IT/テクノロジー職向け 会社紹介資料|Company Introduction Deck
techtekt
PRO
0
240
R&D 祭 2024 アニメエフェクト作成の効率化
olmdrd
PRO
0
110
TSKaigi 2026 - 型プラグインシステムの実装に使われるテクニック
teamlab
PRO
0
110
How to learn AWS Well-Architected with AWS BuilderCards: Security Edition
coosuke
PRO
0
190
O'Reilly Infrastructure & Ops Superstream: Platform Engineering for Developers, Architects & the Rest of Us
syntasso
0
320
20260515 ログイン機能だけではないアカウント管理を全体で考える~サービス設計者向け~
oidfj
1
870
エンタープライズの厳格な制約を開発者に意識させない:クラウドネイティブ開発基盤設計/cloudnative-kaigi-golden-path
mhrtech
0
470
ワールドカフェ再び、そしてゴール・ルール・ロール・ツール / World Café Revisited, and the Goals-Rules-Roles-Tools
ks91
PRO
0
180
その英語学習、AWSで代替できませんか?
suzutatsu
1
160
DI コンテナ自動生成ツールを実装してみた / intro-autodi
uhzz
0
710
Featured
See All Featured
Darren the Foodie - Storyboard
khoart
PRO
3
3.3k
The Cult of Friendly URLs
andyhume
79
6.9k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
180
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
190
The Invisible Side of Design
smashingmag
302
52k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
130
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
180
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.1k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.9k
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で行く が吉