2018-05-07

HLSやMPEG-DASHやCMAFについて

先日、Streaming Conference #2でFragmented MP4についてのスライドを発表しました。

https://speakerdeck.com/yaminoma/fragmented-mp4falseohanasi

その際、スライドに書き切れなかった内容をここで補足しておきます。

HTTP Live Streaming(HLS)

  • HLSは最低でも3セグメントをプレイリスト(m3u8)に書く必要があります
  • Appleは1つのプレイリストに6セグメント、2秒ごとに更新を推奨しています
  • 1セグメントには必ずキーフレーム(IDRフレーム)を入れる必要があります
  • 理由として、MP4では先頭にdurationやoffsetといったメタデータを入れる必要があります。なので、セグメント全体を構成するフレームがすべてそろうまでクライアントに送信することが出来ないのです。
  • また、蛇足にはなりますが、Bフレームを入れた場合、エンコードとデコードの双方で負荷がかかるため、基本的に遅延を重視するのであれば、入れないことをオススメします。
  • 遅延を少なくするにはキーフレーム感覚を短くする必要があり、結果的に画質低下を生むことになります

何故キーフレームが多くなると画質が下がるのか?

  • キーフレームが来ると前のフレームとの依存関係が絶たれて、新たなピクチャのシークエンスが形成されるので、前のフレームと比べると大きな差が生まれてしまう
  • それがノイズとなって見えてしまうのです

HLSの再生順序を変えるには

  • 先ほど書いたとおり、HLSでは最低3セグメントをプレイリストに入れる必要があります
  • しかし、これでは3セグメント分の遅延が発生してしまいます
  • これを一番最新のセグメントから再生させるためには以下のメタタグを入れる必要があります。

#EXT-X-START:TIME-OFFSET=-3.00,PRECISE=NO (durationが3秒の場合)

  • これにより、一番最後から3秒前、つまり一番最新のセグメントから再生することが出来ます
  • しかし、クライアントによってはEXT-X-STARTが認識しなかったりするので使う場合は注意が必要です(認識されない場合は無視されます)

MPEG-DASH(DASH)

  • DASHも1セグメントに必ずキーフレームを入れる必要があります
  • DASHの場合はMPDと呼ばれるプレイリストを使いますが、セグメントの数の制限はないので、最低1個でも再生されます

DASHの方が再生が軽いのか?

  • MPEG2-TSの場合は、映像と音声を多重化しているため、再生する場合は取り出す必要があります
  • ブラウザで再生する場合はMedia Source Extensionを使う必要があります。
  • Media Source Extensionには以下の条件があります。
    • 初期化に必要なヘッダ情報である初期化セグメント
    • 短い時間で区切られたメディアデータ本体が含まれるメディアセグメント
  • なので、MPEG2-TSを再生するには上記のフォーマットに変換する必要があります。
  • HLS.jsなどではJavaScript側でFragmented MP4に組み立て直して再生しているため、その部分がオーバーヘッドになり、処理が重くなるのです。
  • また、Safariの場合はQuickTimeコンポーネントが直接MPEG2-TSを再生するため、JavaScript側で処理する必要はなく、再生が非常に軽いです。
  • つまり、MPEG2-TSはブラウザで直接再生出来ないのでいったん再生できるフォーマットに変換する必要があり、その部分をJavaScriptで処理しているので重い
  • Fragmented MP4だとそのまま再生できるという感じです

CMAF

  • CMAFはFragmented MP4であることが仕様に定義されています
  • プレイリストはHLSまたはDASHのいずれかを使用します
  • CMAFは1つのセグメントを更に分割したチャンクを使います
  • 1チャンクにはキーフレームを入れる必要はありません
  • そのため、変換途中のものをそのままHTTP Chunked Encodingで送ることができます
  • 結果として低遅延で再生が可能になるのです