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
280
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
750
Node.js x Chrome headless for WebRTC MCU
mganeko
1
3.3k
Extend User Experience of WebRTC with Cool Sensor Devices
mganeko
1
710
Playing with OSS WebRTC SFU meidasoup (update for v1.2)
mganeko
0
900
Build WebRTC iOS Gateway on Browser
mganeko
0
1.2k
Other Decks in Technology
See All in Technology
AzureのIaC管理からログ調査まで、随所に役立つSkillsとCustom-Instructions / Boosting IaC and Log Analysis with Skills
aeonpeople
0
280
Do Ruby::Box dream of Modular Monolith?
joker1007
1
360
サイボウズ 開発本部採用ピッチ / Cybozu Engineer Recruit
cybozuinsideout
PRO
10
79k
ハーネスエンジニアリングをやりすぎた話 ~そのハーネスは解体された~
gotalab555
5
1.9k
AI時代における技術的負債への取り組み
codenote
1
1.8k
国内外の生成AIセキュリティの最新動向 & AIガードレール製品「chakoshi」のご紹介 / Latest Trends in Generative AI Security (Domestic & International) & Introduction to AI Guardrail Product "chakoshi"
nttcom
4
1.5k
Chasing Real-Time Observability for CRuby
whitegreen
0
280
ネットワーク運用を楽にするAWS DevOps Agent活用法!! / 20260421 Masaki Okuda
shift_evolve
PRO
2
230
AndroidアプリとCopilot Studioの統合
nakasho
0
170
はじめての MagicPod生成AI機能 機能紹介から活用方法まで
magicpod
0
120
これからの「データマネジメント」の話をしよう
sansantech
PRO
0
150
AIはハッカーを減らすのか、増やすのか?──現役ホワイトハッカーから見るAI時代のリアル【MEGU-Meet】
cscengineer
PRO
0
210
Featured
See All Featured
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
300
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.8k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.2k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
130
The Curse of the Amulet
leimatthew05
1
12k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
53k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
199
73k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
260
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
210
Leo the Paperboy
mayatellez
7
1.7k
Building an army of robots
kneath
306
46k
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で行く が吉