MoQ WGで議論されているLow Overhead Media Container (LOC)の紹介
はじめに
IETFに提出されているLow Overhead Media Containerというドラフトについて紹介します。
MoQ WGとWebCodecsのことを何となく知っている人向けです。
Low Overhead Media Container (LOC)とは
Low Overhead Media Container (LOC)
はMedia over QUIC Transport (MOQT)
上のメディアコンテナフォーマットです。
MOQTはメディア配信における要求の異なる広いユースケースをサポートしようとするプロトコルで、下層としてQUICかWebTransportを用います。
LOCと同じ立ち位置のドラフトとしてはWARP Streaming Formatが存在します。
MOQTやWARPについては@flano_yukiさんのMOQTについてのブログ記事が詳しいです。
MoQ WGの中間会議資料のWARP streaming format p.2より
名前の通り、LOCは映像や音声向けの低オーバーヘッドのメディアコンテナフォーマットを目指しています。
最重要のモチベーションは、WebCodecsと相互作用するときに余分なカプセル化とアプリケーションのオーバヘッドを最小化するために、WebCodecsで使われるメディアフォーマットと協調することです。
LOCでは音声と映像のペイロードに、それぞれWebCodecsでエンコードした結果であるEncodedAudioChunk
とEncodedVideoChunk
の中身の"internal data"
がそのまま使えます。
RTP
やWARPで想定されているCMAF
のような他のコンテナフォーマットはデメリットが2つあると書かれています。一つはより大きなカプセル化オーバーヘッドで、もう一つはフォーマット変換によってより大きなアプリケーションのオーバヘッドを要求するだろう点です。
WARPに対してLOCはこのオーバーヘッドの点で特に音声向けで差別化されていると思います。
LOCはWebCodecsのフォーマットを用いていますが、それらの"internal data"は単純なビットストリームのフォーマットなのでWebブラウザ外のアプリケーションでも使用可能だと書かれています。[1]
LOCのフォーマット
MOQTのObjectはMOQ Object Header
とMOQ Object Payload
から構成されます。以下のように、MOQ Object Payload
はLOCではLOC Header
とLOC Payload
が含まれます。
+--------------+----------+-----------+
| MOQ Object | LOC | LOC |
| Header | Header | Payload |
+--------------+----------------------+
<---------------------->
MOQ Object Payload
LOC Payload
前述の通りLOC PayloadにはWebCodecsでエンコードした結果であるEncodedAudioChunk
とEncodedVideoChunk
の中身の"internal data"
がそのまま使われます。
E2EE(End to End Encryption)がサポートされている場合、エンコードされたペイロードはMLSなどの共通鍵のメカニズムからなる鍵で暗号化され、Payload自身(映像の各フレームなど)もSFrameや似た手法で保護されます。
LOC Header
映像と音声で共通のヘッダは2つあります。
1つはSequence Number
でフレーム毎に1ずつ増加します。
もう一つはCapture Timestamp
でフレームの実測時間[2]が符号なしの64bitでミリ秒単位で入ります。
加えて音声ではRFC6464で定義されるAudio Level
が存在します。
もし新たなヘッダを追加したい場合は以下の情報が必要になります。
- Shortname
- metadataの短い名前
- 登録上必要だが実際のデータには載らない
- Description
- metadataの詳しい説明
- 登録上必要だが実際のデータには載らない
- ID
- レジストリで割り当てられる識別子
- 可変長整数
- Length
- metadata valueのバイト長
- 可変長整数
- Value
- metadataの値
Catalog
CatalogはLOC固有の仕組みではなく、WARPでも定義されている仕組みです。[3]
Catalogは特別なMOQT Object
[4]でpublishされているtrack一覧の情報を提供します。また、"catalog"というtrack nameを持ちます。
提供されるTrackの情報としてはTrack IDの他に、コーデックの詳細やゲームではgamestateのエンコーディングの詳細などがあります。
Catalogのコンテンツは仲介サーバであるRelayからは不明であり、E2EEされているかもしれません。
publisherはCatalogを用いて自身の配信している内容を広告し、subscriberはCatalogを用いてどれを受信するか選びます。
これによりsubscriberはCatalog以外のtrack nameを事前に知る必要がなく、publisherもtrack nameを固定する必要がなくなります。
CatalogはJSONで表現され、以下のフィールドがtrack毎に必須になります。
このうち、Track Namespace
と Track Name
を連結したものがFull Track Name
となり、これによってtrackを識別することになります。
+=================+=======+===========+
| Name | Label | JSON Type |
+=================+=======+===========+
| Track Namespace | ns | String |
+-----------------+-------+-----------+
| Track Name | tn | String |
+-----------------+-------+-----------+
| QualityProfile | qp | |
+-----------------+-------+-----------+
QualityProfile
はkey-valueをカンマで連結する文字列で、映像か音声かによって以下のようにフィールドが異なります。
例を見ると、全てのフィールドが必須という訳ではなさそうなことが分かります。
+===============+=======+============+===========+
| Name | Label | Media Type | JSON Type |
+===============+=======+============+===========+
| Codec | cs | AV | String |
+---------------+-------+------------+-----------+
| Framerate | fr | V | Number |
+---------------+-------+------------+-----------+
| Bitrate | br | AV | Number |
+---------------+-------+------------+-----------+
| Width | wd | V | Number |
+---------------+-------+------------+-----------+
| Height | ht | V | Number |
+---------------+-------+------------+-----------+
| SampleRate | sr | A | Number |
+---------------+-------+------------+-----------+
| ChanelCount | cc | A | Number |
+---------------+-------+------------+-----------+
| DisplayWidth | dw | V | Number |
+---------------+-------+------------+-----------+
| DisplayHeight | dh | V | Number |
+---------------+-------+------------+-----------+
以下はドラフトにあるCatalogの一例です。
{
"ls": ["audio", "video"],
[
{
"ns": "conference.example.com/conference123/alice",
"n": "video",
"qp": "cs=av01.0.08M.10.0.110.09,wd=1920,ht=1080,fr=30"
},
{
"ns": "conference.example.com/conference123/alice",
"n": "audio",
"qp": "cs=opus,sr=48000,cc=2"
}
],
}
よくわからなかった点
5. Container Serialization
の節はどういう内容なのかいまいち分かりませんでした。
ここでいうHeaderとPayloadがMOQTのものなのか、LOCのものなのかどちらなのか不明です。
MOQTのPayloadの暗号化は任意のはずなので必ず暗号化されるような書き方にならなそうな気がします。
一方、LOC HeaderとLOC Payloadと考えると、直前のペイロードの暗号化で共通鍵メカニズムからなる鍵による方式としか書いていないのに、ここではAEADと明記されていて、違うものを指しているのではないかという気がします。
+--------+------------+-------+------------+
| Payload | Bytes | Payload | Bytes |
| Len | (0) | Len (1) | (1) | ...
+--------+------------+-------+------------+
他にはLOC Headerのエンコード形式が気になりました。
Key-Length-Value形式なのか、JSONなのか、その他なのかいろいろありそうですが、2.2.4の内容を見るとKey-Length-Value形式なのかなと思います。
また、Objectの話のみでGroupの話が出てこなかったのが気になりました。
デコード可能な時点で区切ることを考えると、キーフレーム毎に別Groupになるのでしょうか?
その場合、アプリケーションやpublisher毎にGroupの長さが大分異なりそうです。
感想
WebCodecsのフォーマットがそのまま利用可能なため、ブラウザ間で行いたい場合にクライアント側の実装が比較的簡単になりそうに見えます。一方でできることがWebCodecsに依存するはずなので、ブラウザでできないことをやりたい場合には向かないかもしれません。
映像はWARP、音声はLOCのようなことも議論されているようなので、MOQT全体がどうなるかも気になるところです。次の中間会議は9月下旬から10月上旬に開催されるようです。
-
実際の仕様がどこにあるかは見つけられませんでした。 ↩︎
-
フレームの生成にかかる時間は与えられても嬉しくないと思うので、フレームが表す時間(unix timestampなど)ということでしょうか? ↩︎
-
フォーマット毎に定義するのではなくCatalogのドラフトを作成してそちらに仕様を移すことが検討されています。 ↩︎
-
MOQTでのバイト列の最小単位。他にGroupやTrackがある。 https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-00#name-objects ↩︎
Discussion