inside webm
TRANSCRIPT
Inside of WebM
2015.06.06インフォコム株式会社
がねこまさし@massie_g
1
WebM とは• Wikipedia より http://ja.wikipedia.org/wiki/WebM– 米 Google が開発している– オープンでロイヤリティフリーな– 動画コンテナフォーマット
• コーデック– 映像: VP8 / VP9– 音声: Vorbis
• コンテナ– Matroska のサブセット
Matroska• Wikipedia より http://ja.wikipedia.org/wiki/Matroska
– ロシアの入れ子人形マトリョーシカにちなむ– オープンソース( GNU LGPL )で開発中– EBML ( Extensible Binary Meta Language )採用– http://www.matroska.org/technical/specs/index.html– こちらの記事からたどり着きました。ありがとうございます!
• Media Source Extensions を使ってみた (WebM 編 ) @othersight• http://qiita.com/tomoyukilabs/items/57ba8a982ab372611669
• EBML ( Extensible Binary Meta Language )– XML を基に作られた、拡張性に優れたデータ格納方式
• 要素のみ、属性なし、入れ子あり• ※ むしろ YAML と言った方が近いかも
– 対応していない機能 ( タグ ) は無視する– テキストではなくバイナリで表現
EMBL のイメージ<EBML>
<EBMLVersion>1</EBMLVersion><DocType>webm</DocType>
</EBML><Segment> …
<Info> … </Info><Tracks> … </Tracks><Cluster> … </Cluster><Cluster> … </Cluster>…
</Segment>
これがバイナリで格納されている
WebM のおおまかな構造
ヘッダー 部分
映像 / 音声 部分
おまけ 部分
Header
Meta Seek Info
Segment InfoTracks
(Chapters)
ClusterClusterCluster
Cluster
(Cue Data)(Attachment)
(Tagging)
Matroska 的
EBML
Segment
WebRTC 的
Header の主要要素EBML:[1A][45][DF][A3]... EBML 形式であることを示す
EBMLVersion:[42][86]… EBML のバージョン 1EBMLMaxIDLength:[42][F2]…ID( タグ ) の最大長 4EBMLMaxSizeLength:[42][F3]…
要素値のサイズを指定する数値の最大バイト数 8
DocType:[42][82]… ファイル形式” webm”DocTypeVersion:[42][87]… ファイル形式のバー
ジョン
Header
Header の主要要素EBML:[1A][45][DF][A3]... EBML 形式であることを示す
EBMLVersion:[42][86]… EBML のバージョン 1EBMLMaxIDLength:[42][F2]…ID( タグ ) の最大長 4EBMLMaxSizeLength:[42][F3]…
要素値のサイズを指定する数値の最大バイト数 8
DocType:[42][82]… ファイル形式” webm”DocTypeVersion:[42][87]… ファイル形式のバー
ジョン
Header
ファイル名が変更されて拡張子がなくても・先頭の 4 バイトが 0x1A, 0x45, 0xDF, 0xA3 であれば、高確率でWebM・さらに DocType の値を見れば、 WebM であることがほぼ確定
Segment Info の主要要素Info:[15][49][A9][66]
TimecodeScale:[2A][D7][B1]… トラックの時刻を示す単位を、ナノ秒で指
定 →1,000,000 ナノ秒 = 1 ミリ秒Duration:[44][89]… 映像 / 音声の長さ
TimecodeScale を単位として示す※ 不明(継続中)の場合は 0
Segment Info
Segment Info の主要要素Info:[15][49][A9][66]
TimecodeScale:[2A][D7][B1]… トラックの時刻を示す単位を、ナノ秒で指
定 →1,000,000 ナノ秒 = 1 ミリ秒Duration:[44][89]… 映像 / 音声の長さ
TimecodeScale を単位として示す※ 不明(継続中)の場合は 0
Segment Info
TimecodeScale で、この後登場する時刻、時間の単位を指定・仕様上ナノ秒単位でも指定できるので、光の動きも捉えられそうDuration では再生時間を指定・ MediaRecorder で録画したものでは、 0( ゼロ ) が指定
Tracks の主要要素Tracks:[16][54][AE][6B]… Video/Audio トラックのセット
TrackEntry:[AE]… トラックTrackNumber : [D7]CodecName:[25][86][88]TrackType:[83] … Video/AudioVideo:[E0]
PixelWidth:[B0]PixelHeight:[BA]FrameRate:[23][83][E3]
Audio:[E1]SamplingFrequency:[B5]Channels:[9F]
Tracks
Track についてTracks
・仕様上は、 Track は 127 個まで入れることが可能 ※今のところ、 Video が 1 つ、 Audio が 1 つ、というケースしか見たことがない・ TrackType は、 Video/Audio 以外にも字幕、ロゴなどが用意されている模様
Cluster の主要要素Cluster[1F][43][B6][75]… 実際の Video と Audio の断片を格納
Timecode:[E7] … その断片の開始時刻 (TimecodeScale の値単位 )
SimpleBlock : [A3] …Video か Audio の断片。複数※SimpleBlock の中身は、 EBML 形式ではない
Cluster
Cluster の主要要素Cluster[1F][43][B6][75]… 実際の Video と Audio の断片を格納
Timecode:[E7] … その断片の開始時刻 (TimecodeScale の値単位 )
SimpleBlock : [A3] …Video か Audio の断片。複数※SimpleBlock の中身は、 EBML 形式ではない
Cluster
・実際の映像 (Video) と音声 (Audio) のデータは Cluster に含まれる・一つの WebM ファイルには複数の Cluster が含まれる
WebM/Matroska/EBMLバイナリのレイアウト
EBML
EBMLVersion
“webm”
Segment
1
Tracks
CodecName
“VP8”
DOCType
タグ /Element のバイナリ表現
• 3 つのパートでタグ /Element は構成される
ID DataSize Data
1 ~ 4 バイト 1 ~ 8 バイト 0 ~ 0x00FFFFFFFFFFFFFE バイト ペタバイト級まで
可変長 可変長
可変長
実際のデータだけでなく、 ID も DataSize も可変長厄介なヤツ。マジ勘弁…
ID 部のバイナリ表現1 バイト目 (2 進 )
1xxx-xxxx
01xx-xxxx xxxx-xxxx
001x-xxxx xxxx-xxxx xxxx-xxxx
0001-xxxx xxxx-xxxx xxxx-xxxx xxxx-xxxx
0x80 ~ 0xFF
0x40 ~ 0x7F
1 バイト目 (16 進 )
0x20 ~ 0x3F
0x10 ~ 0x1F
※ 先頭ビットも、 ID の値に含める
DataSize 部のバイナリ表現
xxxx-xxxxxxxx-xxxx xxxx-xxxxxxxx-xxxx xxxx-xxxx xxxx-xxxxxxxx-xxxx0000-0001
xxxx-xxxxxxxx-xxxx xxxx-xxxxxxxx-xxxx xxxx-xxxx xxxx-xxxx0000-001x
xxxx-xxxxxxxx-xxxx xxxx-xxxxxxxx-xxxx xxxx-xxxx0000-01xx
xxxx-xxxxxxxx-xxxx xxxx-xxxxxxxx-xxxx0000-1xxx
xxxx-xxxxxxxx-xxxx xxxx-xxxx0001-xxxx
xxxx-xxxxxxxx-xxxx001x-xxxx
xxxx-xxxx01xx-xxxx
1xxx-xxxx
1 バイト目 (2 進 )
7bits
14bits
21bits
28bits
35bits
42bits
49bits
56bits
値は Big Endian の Unsigned Integer※ 先頭ビットは、 DataSize の値に含めない※ すべてのビットが 1 の値は予約済(多分)
Data 部分• DataSize で指定されたバイト数• タグ (ID) の種類によって、さまざま型– 整数: unsigned int, signed int (Big Endian)– 文字列 : ASCII string, UTF-8 string– 実数: float (Big Endian)– 日付 : date (Big Endian)– バイナリ : binary– 他の複数のタグ: master
• タグの入れ子の構造• 型を識別するルールは無い …みたい– タグの値と型を対応付ける辞書を持つしかなさそう– http://www.matroska.org/technical/specs/index.html
20
http://www.matroska.org/technical/specs/index.html より
ID 型
解析例 (1) EBMLVersion
• 16 進表記: 42 86 81 01• ID の最初のバイトの 2 進表記: 0100 0010– → ID は 2 バイトの [42][86]– 一覧表から、 EBMLVersion と判明
• DataSize の最初のバイトの 2 進表記: 1000 0001– → DataSize は 1 バイト– サイズは 0000 0001 = 1 バイト
• Data は 1 バイト。先ほどの一覧表から、型は Unsigend Int– → 値は 1
• 結果: EBMLVersion = 1
解析例 (2) DocType
• 16 進表記: 42 86 84 77 65 62 6D• ID の最初のバイトの 2 進表記: 0100 0010– → ID は 2 バイトの [42][84]– 一覧表から、 DocType と判明
• DataSize の最初のバイトの 2 進表記: 1000 1000– → DataSize は 1 バイト。サイズは 0000 1000 = 4 バイ
ト• Data は 4 バイト。先ほどの一覧表から、型は ASCII string– 77 65 62 6D → 値は "webm"
• 結果: DocType = "webm"
WebM のパース• 先頭から 1 バイトづつパースしていけば、タグの内容を
解析可能• とくに興味が無いタグや、理解できないタグが出現した
場合– データー長はルールに従って算出可能 → スキップすることが可
能
• ※ もちろんライブラリもあります– libebml http://dl.matroska.org/downloads/libebml/– libmatroska http://dl.matroska.org/downloads/libmatroska/– yamka https://sourceforge.net/projects/yamka/※ 使ってはいません。詳細不明
• Node.js のサンプルコードを書いてみました– https://gist.github.com/mganeko/9ceee931ac5dde298e81– メモリ上に一括して読み込む、しょぼい実装ですが…