ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
低遅延HLSの紹介
2009年の導入以来、HTTP Live Streaming(HLS)は、世界中で数えきれないほどのライブおよびオンデマンドのオーディオおよびビデオストリームの配信を可能にしてきました。新しい低遅延モードの導入により、既存のクライアントへの後方互換性を保ちながら、大規模なパブリックネットワークで2秒未満の遅延を達成できるようになりました。この新しいテクノロジーを活用するために、コンテンツ配信システムを開発および構成する方法についてご確認ください。
リソース
- Enabling Low-Latency HTTP Live Streaming (HLS)
- HTTP Live Streaming (HLS) authoring specification for Apple devices
- HTTP Live Streaming Tools
- プレゼンテーションスライド(PDF)
関連ビデオ
WWDC20
WWDC19
-
ダウンロード
(音楽)
どうも (拍手) こんにちは ようこそ ロジャー・パントスです 今年のHLSセッションのテーマは 低遅延についてです まず初めに― この低遅延の 遅延とは何のことでしょうか?
今回の話でいえば カメラでとらえた映像の1フレームや バックエンドを叩いた際の返しが iPadやApple TVのユーザに 届くまでの時間です その時間を短く維持することが 重要なコンテンツがあります なじみがあるものだと 例えばスポーツ中継です 他にもニュースの生中継や ゲームのライブ配信なども 当てはまります オスカー授賞式もそうですね 同じ映像を 同じ時間 大勢が見るものは 全て当てはまります 大抵 社会的にも重要です では 最高のユーザ体験を 提供するには 遅延は何秒以下にすべきなのか?
現在の目指すべき基準は 約2~8秒です これはケーブルテレビや 衛星放送が実現している時間です そこで 我々も低遅延HLSで 目標を立てました インターネット経由のライブ配信で 遅延を1~2秒に抑えるという 目標です そして HLSの魅力的な機能を 犠牲にすることなく 目標を達成しました ユーザの通信速度に合わせて 画質を変更できます コンテンツの保護と広告の挿入 プログラムの境界や― メタデータの提供を可能にします
そして 数十万以上のユーザに 配信を広げられます コスト効率に優れたCDNを使用してです そして ストリーミングは 下位互換性があるので 古いクライアントも 通常の遅延で視聴できます それを可能にする方法は? まず… 低遅延HLSを理解するには― 通常のHLSを振り返る必要があります
まず 当初からHLSは シンプルで強力な― プロトコルになるよう設計されました すばらしいことです 実際に あなたのコンテンツが 先ほどのジャンルに該当しないなら― 通常のHLSを使い続けるべきです しかしシンプルさには犠牲が伴います その例として Apple TVで スポーツ中継を見ると ゴールの瞬間を見る前に 隣人が先に歓喜の声を上げます
この原因は? 理解するために 通常のHLSの仕組みについて見ましょう ユーザがバックエンドから フレームを取得する流れです まず フレームをエンコードし セグメントに入れます 長さの推奨は6秒です しかし リアルタイムで エンコードするため CDNに置くために まず6秒かかります その後 今度はクライアントが 見つける必要があります HLSはポーリングを使用します つまりクライアントは随時 新たなプレイリストがないか確認します タイミングが良ければ Serverが最新のプレイリストを 置いた直後に確認できます しかし タイミングが 合わない時もあります クライアントが見つけるのに さらに6秒かかることもあるでしょう
そして 最新のプレイリストを 取得したあとも 今度はセグメント自体を 取得しなくてはいけません さらに ラウンドトリップタイムを 忘れてはいけません 特にモバイル通信では 数百ミリ秒かかり 見過ごせない時間です さて ようやくセグメントが クライアントに届き 動画を再生出来るようになります この例では 既に12秒もかかっています しかも 広く普及したCDNで コンテンツを届けるとなると ライブより さらに遅れます それはHLSとCDNの関係にあります その理由について見ていきましょう HLSでストリームするとして 右側をオリジンに設定しています プレイリストには セグメントが3つあります 最初のクライアントが 動画を確認に来ます もしCDNエッジServerに プレイリストのキャッシュがなければ オリジンからプレイリストを取得します CDNは最新のプレイリストを クライアント1に届けます 問題は その1~2秒後です オリジンで新たなセグメントができ プレイリストも更新 セグメント4が追加されました どうなるでしょう? クライアント2が 最新のプレイリストを要求します エッジServerから返されるのは キャッシュなので セグメントは1~3で 4は見つけられないのです これはCDNがキャッシュを 返したためです なぜCDNは このような動作を? 最新版を返せば良いのでは? それは オリジンが 更新されていることを CDNは知るすべがないからです もしクライアントが 最新版を要求するたびに CDNがオリジンにアクセスしたら? オリジンがパンクします CDNには一定期間キャッシュを残す Time to Liveが備わっています 有効期限が長ければ長いほど 配信されるプレイリストが 古くなります そしてディレイが長くなるのです
しかし… これらの問題は解決できます
さて 解決方法を考えるに当たり 考慮すべきことが何点かあります まず 同じメディアを配信するには HTTPが最良の方法です 同時に数十万人に 配信することができるからです HTTPは使うべきです 裏を返せば HTTPデリバリモデルは 変えられません 分割されたリソースをクライアントに 配布するということです そして その分割の生成には 6秒かかるので 既に目標を超えています ライブから1秒の遅れを目指すなら HTTPで配布するものを 大幅に縮小する必要があるのです
次に取り組むべき問題は 現在や近い将来において― 世界中の視聴者に配信するには CDNが不可欠ということです しかし CDNは根本的には HTTPプロキシキャッシュなので キャッシュ以上の役割を 求めてはいけません そして 最後に ライブとの遅延が短くなると バッファもあまり出来ません なので 例えばビットレートを 切り替える場合― 再生が止まるまで 10秒も猶予はありません 時間は1秒もないのです そのため 切り替えの効率を 上げる必要があります 時間がないためです そこで…
私たちはHLSデリバリモデルを 隅から隅まで目を通しました そして 大きな改善点を 5つ見つけました ライブから1~2秒以内の遅延を 達成するための改善です まず 1つ目の改善点は 6秒以内にメディアを Serverに上げることです “パブリッシング遅延の縮小” と呼んでいる技術です
メインのセグメントが 生成される前に Serverにセグメントの分割を 許可します 小さな塊なら早く配信できます 2つ目の改善点は クライアントがセグメントを 発見する方法を最適化します そのために クライアントが プレイリストを更新する方法を変えます Serverが配信可能になる前に クライアントに更新の要求を許可します Serverはプレイリストが更新されるまで 要求を残しておき 更新されるとすぐに クライアントへ配信します ラウンドトリップタイムを削減できます また個々のプレイリストの更新は 異なるURLとなります これが2つ目の利点です 更新されたプレイリストの 効率的なキャッシュ化です 更新毎にURLが異なるので キャッシュも異なって見えます クライアント1が 更新を要求するとします CDNは その更新を知らないので オリジンに聞きます オリジンは まだ生成出来ていないと答えます 更新後 CDNに渡し CDNはクライアントに渡します 次は クライアント2が更新を要求 CDNはURLから更新を特定し クライアントに渡します 更新を要求する他のクライアントも CDNからキャッシュを取得します しかし 今度は クライアントが別の更新を要求すると 異なるURLをCDNに送ります URLが異なるのでCDNは キャッシュがないと判断し オリジンに更新がないか確認します 更新が出来ると オリジンはCDNに渡し クライアントにも送られます
この新しい…
プレイリスト更新の要求ですが 本質的にはキャッシュバスティングです CDNのキャッシュ機能が向上します 3つ目の改善点は 余分なラウンドトリップの排除です セグメントを見つけたあとに 取得することです そのためにPushを使います クライアントがServerに 新しいプレイリストがないか確認します そして 更新されたプレイリストに 新しいセグメントがあれば プレイリストと一緒にセグメントも プッシュするよう要求します それで1往復分の節約になります
4つ目はプレイリストを 何度も転送する― 処理時間に取り組みました その解決策は差分更新です 初めてクライアントが プレイリストを要求すると CDNはプレイリストを丸々返します しかし そのあと知りたいのは 変更がかかったプレイリストの 最後の部分だけです そこで 2回目以降は CDNに差分更新だけが必要だと 要求します その分 返ってくるデータは小さく 最新のプレイリストの 変更部分だけになります 差分更新は1パケットに 収まることでしょう 続く更新も非常に効率的になります
次は5つ目の改善点です 更新されたプレイリストは 最新なので― ビットレートのティアの切り替えを 高速にする情報を付加できます 例えば CDNに2つのビットレートがあり クライアントは1Mbpsで再生中 更新を要求すると1Mbpsで プレイリストの最新版を受け取ります プレイリストには 2Mbpsに切り替えられる情報もあるので クライアントはプレイリストを 直接2Mbpsで要求できます ビットレートの切り替えが 効率的になります これらが5つの改善点です
パブリッシング遅延の縮小 セグメント発見の最適化 ラウンドトリップの排除 転送のオーバーヘッドの縮小 そして 切り替えの高速化 では 詳細を説明します
これらを利用するに当たり…
クライアントはServerに新しい機能を 利用したいことを伝える手段が要ります
そこで HLS Origin APIと 呼ばれるものを使います
Serverを操作する新しいタグを使って サービスに知らせるものです クライアントがタグを見つけると Serverに 少数のディレクティブを送ります GETリクエストにクエリパラメータを 追加するのです こんな感じです さて…
HLSにクエリパラメータを指定するのは 初の試みです プレイリストのURLでは HLSから始まるクエリパラメータは すべてプロトコルとして扱われます クライアントに対して クエリパラメータがURL内に 確定的な順序で表示されるようにします そうすればCDNが同じリクエストを キャッシュするのを防げます さて 5つの改善点の詳細を 見ていきましょう
1つ目はパブリッシング遅延の縮小です パーシャルセグメントを HLSに導入します 略して“パーツ”です パーツは基本的に セグメントの集合体で 親セグメントにメディアの サブセットを含みます CMAFではこれに名前が既についており fMP4に対して CMAFチャンクと呼んでいます チャンクをHLSでパーツとして 使うことができます またトランスポートストリームや 定義されたセグメントフォーマットを パーツとして使用できます
パーツは短く GOPよりも短くなるので 0.5秒のパーツと2秒GOPを 残すことができます
パーツは生成されるたびに プレイリストに追加されます つまり もし0.5秒のセグメントがあれば CDNにコンテンツを発行できます パブリッシング遅延を ここまで縮小できるのです
パーツは通常のセグメントと 並行してプレイリストに追加されます しかし 長くは残りません
パーツの利用が主に適しているのが ライブ配信だからです クライアントが即座にメディアを 見つけられます パーツの粒度が高い アドレス可能性により クライアントがライブに近い ストリームに参加することが可能です しかし パーツがライブ配信より離れ 親セグメントが確立されれば パーツより親セグメントが 読み込まれるべきです パーツはプレイリストから除かれ― プレイリストは小さいままです セグメントが生成される時 パーツも平行して生成されます その後 最初のパーツが ライブ配信より離れると 新しいパーツに置き替えられるのです 実際のHLSの プレイリストを見てみましょう
注目すべき点が2つあります まず 気づいてほしい点は 通常のプレイリストには セグメントの長さの目標値があります パーツも長さにも目標値があります このプレイリストでは パーツの最大の長さは0.5秒です 次は 通常の6秒の segment43があります それをプレイリストに置いた 0.5秒後― segment44の最初のパーツを 追加できます 実行するためには 新しいタグを使います 新しいタグをパートタグと呼び URIパラメータを持ちます このパーツのURIはsegment44.1です 長さは0.5秒で独立したセグメントです 0.5秒後 次のsegment44.2を プレイリストに追加できます 6秒のプレイリストなのでパーツは12個 最後のsegment44.12まで来ると 親セグメントも生成できます そのため segment44.12と 親セグメントを同時に発行できます そして0.5秒後 繰り返しで segment45.1が生成されます その後 中間のパーツは プレイリストの先端から離れたため 取り除くことができます 今は segment43と44 segment45の一部が残っています こうして パブリッシング遅延を縮めます 次はセグメント発見の最適化です
方法はブロッキング プレイリストリロードです EXT-X-SERVER-CONTROLのタグに CAN-BLOCK-RELOADの属性を付け Serverがその機能に対応していると 知らせます クライアントが属性を見つけると 事前に次のプレイリストを要求 このように知らせます
Serverが要求を受け取ると プレイリストが更新されるまで 要求を保持します
では 特定のセグメントを持つ 特定のプレイリストを どうやって指定するのでしょう? HLSのメディアシーケンス番号を 使用します 全てのセグメントには 固有の連続した番号が付いています 最初のセグメントの番号は MEDIA-SEQUENCEタグにあります この場合 1800ですね 次の番号は1を足した数字になります 例え DISCONTINUITYタグで セグメントが離れても 番号は1つずつ増え続けていきます
ということは このプレイリストがあれば 次のセグメントの番号が 分かるということです なので 次のセグメントを このように要求すればいいのです 1803のメディアシーケンス番号を 含んだプレイリストの更新が欲しいと これがそうです これはm3u8のプレイリストを GETリクエストするものです そして HLS msn=1803の クエリパラメータを使って 特定の番号が入ったプレイリストを Serverに要求します クライアントが受け取ると 次の更新の1804を要求します CDNは全く違うURLだと認識します たった1つ値が違うだけでも CDNにとっては異なるキャッシュなので キャッシュバスティングになります
これはパーツにも使えます こんな感じです 2つ目のサンプルはこのような内容です 番号1803の最初のパーツを含む プレイリストの更新が欲しい
さらにPushの クエリパラメータがあります これは何か? 覚えていますか? 5つの改善点の1つは― セグメントのラウンドトリップタイムを なくすことです そのためにはPushが必要です それを可能にするのがHTTP/2です
HTTP/2を詳しく知らない人のために 簡単に説明します
HTTP/2はHTTP/1の次のバージョンです IATFにより2015年に承認されました 以降 ウェブServerやCDNで 広く普及しました
低遅延HLSでは必要不可欠です プロトコルの交換の効率化に 必要な機能が備わっているからです それがPushです Pushの仕組みは? HTTP/2でもクライアントが リソースを要求する時 ServerにGETリクエストを送ります HTTP/2では新たに Serverがリクエストを受け取ると 別のリソースもServerから提案されます 要求されたリソースを返すのと同時に まだ必要としない次のリソースも クライアントに送ることができます そうすることによって 次のリソースは要求せずとも 受け取れます 低遅延HLSでは セグメントプッシュを利用します クライアントがServerに 次のセグメントを含んだ プレイリストの更新を要求します プレイリストの更新を返す時 次のセグメントもプッシュすると そのセグメントを新たに要求する 往復の時間を排除できます
それでは 最初の3つの最適化が 通常のHLSの流れに― どのように影響するか 比較しながら見ていきましょう 左が通常です 右が低遅延のクライアントと 低遅延Serverの流れです まず クライアントが 事前にプレイリストを要求 Serverが要求を保持します その間 Serverは最初のパーツを生成 この見本ではパーツの長さは1秒なので エンコードに1秒かかります その後 プレイリストにパーツを追加し 要求を実行します 同時に 最初のパーツを クライアントにプッシュします クライアントはすぐに表示ができます すぐにプレイリストの更新を 要求することで 最速で次のパーツを 受け取ることができます この例ではパーツの長さは1秒です それでも Serverからクライアントが 1フレームを受け取る時間が 劇的に短縮されたのが分かります
最後の2つの改善点は この流れを最適化することです
1つ目は転送で生じるオーバーヘッドを 削減することです なぜ重要か? もし転送しているプレイリストに 3~5時間分のセグメントがあり それを1秒間に3~4回転送すれば gzipを使っても膨大な量です そのため 私たちは差分更新を追加します その方法は Serverがクライアントに 対応していることを伝えます CAN-SKIP-UNTILの属性を使います ライブから数秒前までセグメントを スキップするのです クライアントは最後の更新が いつか分かるので 差分更新により情報が 欠如することはありません そして 次の差分更新は 明確にリクエストできます
その更新が含んでいるものは ライブに最も近いセグメントのある プレイリストなのです 既に持っている部分はスキップされます
これが例です ここではクライアントが 差分更新を要求しています クエリパラメータは HLS skip=YESで GETリクエストしています
戻ってきたプレイリストには CAN-SKIP-UNTILがあります これは差分更新を要求された時 最新の映像から36秒前までを スキップすることを意味します そして 新しいタブのスキップタグは― このように考えることができます 完全な更新にあったはずの セグメント17XXの代理です
この差分更新のおかげで 常にプレイリストを更新する 通信量を最小にできます HLSの普遍性や能力を 保持したままにです では 最後の改善点です ビットレートの切り替えを高速化する レンディションレポートです クライアントが特定のビットレートで プレイリストを読み込む時 クライアントが変更するかもしれない レンディションの情報も 加えておこうという考えです
最新のメディアシーケンス番号と パーツの番号を含んでいるため 最新のプレイリストを取得する URLを記述できます こんな感じです
ここではクライアントは1Mで プレイリストを要求しています 同時にクエリパラメータを使用して 2Mでもプレイリストの情報を要求します
プレイリストには レンディションレポートタグがあり 他のレンディションの情報が 記載されています
5つの改善点を全て適用すると―
どれだけ時間が短縮されるのか?
デモが見たい? (拍手) やってみよう セッションの内容について 話し合ってる時 クパチーノからの ライブ配信を考えました でも より遠い場所からの方が 演出が派手ですよね? 例えば 約1万2000キロ離れた― オーストラリアのシドニーからとか? (拍手と歓声) でも 知り合いはいたかな?
マットがいる 電話しよう
さて マットが起きてるといいけど
やあ ロジャー マット 調子は? 良いよ すばらしい 今 WWDCのセッションで 低遅延HLSのデモを見せたいんだが まだストリームしてる? もちろん すばらしい 画面を切り替えて 試してみよう Apple TVはどこに… ああ そこにあった よし 画面が写った デモ用のアプリケーションがあるので シドニーを選びます
シドニーが写りませんね もう一度試します
今度はクパチーノを試して 誰かが映ると… クパチーノにいる サイモンが映りました (笑い) サイモンは順調そうです それでは もう一度試しましょう
おっと どうやって開いたらいいんだ
マット まだ… 映った いるよ すばらしい
後ろは旧シドニー中央郵便局舎? そうだよ まったく… 悪いが 再度試すよ
今日はストリームが 思うように動作しない
サイモンはまだいる
まったく
よし マットが映った 一時停止ボタンでも押した?
仕方がないから サイモンに電話することにしよう デモを見せたかったのに残念だ
今回はどうだろう 大丈夫そうか? 再起動した? ネットワークが途切れた 途切れたのか 最低だな
それじゃあ… 接続が間違っているのかも
本当に困りものだ
ダブルタップして…
アプリケーションを閉じて 成功するか?
何てこった じゃあ もう一度だけ試してみよう もうバックアッププランでいこう マット ストリームに問題があるようだ 今日はありがとう 少し映ったけど クパチーノに変更だ 了解です 残念だけど サイモンに電話しよう このためのバックアップだな
サイモンいるかい? いるよ 調子は? 良いよ 彼もオーストラリア出身だったな オーストラリア人が多いね
サイモン 低遅延HLSのデモを見せたいんだ そうだね こうしよう 君に手を上げてもらう 君が手を上げたら 上げたと言ってくれ そうすれば音と映像のズレで 遅延がよく分かるから 了解だよ
手を上げて やあ 手を上げたよ いいぞ 手は上げたままで 手を下げたね じゃあ 指を3本出して 3本指 上出来だ つまりこれが… 遅延が2秒未満の 低遅延HLSストリームです ありがとう サイモン 残りのWWDCを楽しんで ありがとう
改めて… これが低遅延HLSです どうすれば利用できるか 疑問に思っている人もいるでしょう 皆さん 開発者なので アプリケーションについて話しますね 特に何もする必要がありません AVPlayerで再生するなら 標準で低遅延HLSが使えます
新しいAPIが2つあります 1つは ライブと再生箇所の時間差 2つ目はラウンドトリップタイム を元にした推奨値を出します 組み合わせて設定すれば ライブから近すぎることによる 読み込みの停止を防げます 2つ目はライブ配信の再生位置を 維持する方法です 今は視聴中に電波が途切れたり バッファが10秒生じたら 復帰後に停止位置から再生します 再生が止まれば止まるほど ライブから遅れます automaticallyPreserves TimeOffsetFromLiveをYESにすると 再生を再開した際には自動的に ライブの位置までスキップします 次はCDNの設定について考えます
避けるべきことは… 特殊な要件をCDNに課すことです CDNは使いやすいものであるべきです シンプルさを維持しました HLSセグメントとプレイリストを 配信するならHTTP/2を使いましょう Pushや優先順位の制御にも対応 冗長化したServerでも良いですが 1つはティアの完全なラダーを 配置するべきです 接続セットアップ時間を最小化できます また 同じ要求を まとめるようCDNを設定します 例えば 2つのクライアントが 同じプレイリストを要求しても オリジンServerに転送する要求を 1つに制限するといった設定です Apache Traffic Serverでは Read While Writerと呼ばれる機能です 設定してください
ここでの主な仕事は Origin APIの実行と パーツを承認するPackagerの変更です 低遅延HLSの仕様を 公開しています サイトの当セッションページに リンクを載せています まだドラフトですが 年末には仕様が固まる予定です Server設定プロファイルも 新たに加わります クライアントによる 低遅延HLSの利用を可能にする 属性セットが含まれています その属性がなければ 通常のHLSが利用されます
低遅延HLSの生成や ストリームを試すために リファレンス実装が提供されます “低遅延HLSベータツール パッケージ”です カメラなどからプレイリスト生成し 低遅延ストリームに パッケージ化することが可能になります 含まれるのはOrigin APIを実行する Apacheのフロントエンド ブロッキングプレイリストリロード 差分更新 レンディションレポートです これらの低遅延機能を アプリケーションで試したり バックエンドでの実行と比較も出来ます 以上がデベロッパーにとって 必要なことです 次はユーザの話です 低遅延HLSが大きな変化だと 認識しています そのため よく知ってもらうための 時間を設けました クライアントがさらに大きな 規模で実行できるようにです まず 低遅延モードの エンタイトルメントが必要です 許可することでTestFlightを使って 最大1万人にテスト配信できます ベータテストで動作に問題がなければ App Storeに提出できます まとめると仕様はこうです 低遅延HLSに対応する バックエンドをビルドしてください 今週はHLSのラボを 2つ用意しています 私や私のチームメンバーが 低遅延HLSなどに関する質問に 何でもお答えします 最初は木曜日の16時~18時 2回目は金曜日の11時~13時です 本日はご参加いただき ありがとうございました (拍手)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。