ビデオストリーミングは、現代のインターネット体験の不可欠な部分です。携帯電話、デスクトップコンピュータ、テレビ、さらにはウェアラブルなど、どこにでもあります。低速のモバイル接続、WiFi、ファイアウォールの背後など、すべてのデバイスとネットワークタイプで問題なく動作する必要があります。 AppleのHTTPライブストリーミング (HLS)は、これらの課題を念頭に置いて正確に作成されました。
最近のほとんどすべてのデバイスには、ビデオを再生するのに十分な速度の最新のハードウェアが搭載されているため、ネットワークの速度と信頼性が最大の問題として浮上しています。何故ですか?数年前まで、ビデオを保存および公開する標準的な方法は、RTPのようなUDPベースのプロトコルでした。これは多くの点で問題があることがわかりました。ほんの数例を挙げます。
もちろん、これらすべての問題は簡単に解決できると思うかもしれません。ビデオファイル(mp4ファイルなど)をhttpサーバーに保存し、お気に入りのCDNサービスを使用して世界中のどこにでも提供できます。
これは、いくつかの理由で最善の解決策とはほど遠いです。 それらの1つである効率 。オリジナルのビデオファイルをフル解像度で保存すると、接続性の悪い地方や世界の一部のユーザーはそれらを楽しむのに苦労します。彼らのビデオプレーヤーは、実行時に再生するのに十分なデータをダウンロードするのに苦労します。
したがって、ダウンロードされるビデオの量が再生できる量とほぼ同じになるように、ファイルの特別なバージョンが必要です。たとえば、ビデオの解像度と品質が5秒でさらに5秒のビデオをダウンロードできるようなものである場合、それが最適です。ただし、3秒分のビデオをダウンロードするのに5秒かかる場合、プレーヤーは停止し、ストリームの次のチャンクがダウンロードされるのを待ちます。
一方、品質と解像度をさらに下げると、帯域幅を不必要に節約するため、より高速な接続でのユーザーエクスペリエンスが低下するだけです。ただし、3番目の方法があります。
ユーザーごとに異なるバージョンの動画をアップロードすることもできますが、その場合は、プレーヤーを制御し、接続とデバイスに最適なストリームを計算する機能が必要になります。次に、プレーヤーはそれらを切り替える必要があります(たとえば、ユーザーが3GからWiFiに切り替える場合)。それでも、クライアントがネットワークタイプを変更した場合はどうなりますか?次に、プレーヤーは別のビデオに切り替える必要がありますが、最初からではなく、ビデオの途中で再生を開始する必要があります。では、要求するバイト範囲をどのように計算しますか?
ビデオプレーヤーがネットワークタイプと利用可能な帯域幅の変化を検出し、最適なストリームが見つかるまで(同じビデオが異なる速度で準備されている)異なるストリームを透過的に切り替えることができれば、すばらしいでしょう。
まさにそれです アダプティブビットレートストリーミング 解決します。
注意: このHLSチュートリアルでは、暗号化、同期再生、およびIMSC1については説明しません。
HTTPライブストリーミングは、2009年にAppleによって導入されたアダプティブビットレートストリーミングプロトコルです。m3u8ファイルを使用してメディアストリームを記述し、サーバーとクライアント間の通信にHTTPを使用します。これは、すべてのデフォルトのメディアストリーミングプロトコルです。 iOSデバイス 、ただし、AndroidおよびWebブラウザーで使用できます。
HLSストリームの基本的な構成要素は次のとおりです。
基本的な質問に答えることから始めましょう: M3U8ファイルとは ?
M3U(またはM3U8) は、MP3ファイルのコレクションを整理するために元々作成されたプレーンテキストファイル形式です。この形式はHLS用に拡張されており、メディアストリームの定義に使用されます。 HLSには、2種類のm3u8ファイルがあります。
いわゆるM3U8ライブストリームURLは、次のようなM3U8ファイルへのURLにすぎません。 https://s3-us-west-2.amazonaws.com/hls-playground/hls.m3u8 。
M3U8ファイルには、いくつかの追加のメタデータを含むURLまたはローカルファイルパスのリストが含まれています。メタデータ行は#で始まります。
この例は、単純なHLSストリームのM3U8ファイルがどのように見えるかを示しています。
#EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-ALLOW-CACHE:YES #EXT-X-TARGETDURATION:11 #EXTINF:5.215111, 00000.ts #EXTINF:10.344822, 00001.ts #EXTINF:10.344822, 00002.ts #EXTINF:9.310344, 00003.ts #EXTINF:10.344822, 00004.ts ... #EXT-X-ENDLIST
EXT-X-VERSION
はM3U8形式のバージョンです(EXTINF
エントリを使用する場合は少なくとも3である必要があります)。EXT-X-TARGETDURATION
タグには、各動画の「チャンク」の最大継続時間が含まれます。通常、この値は約10秒です。 #EXTINF:10.344822, 00001.ts
これはビデオの「チャンク」です。これは00001.ts
を表します正確に10.344822秒の長さのチャンク。クライアントビデオプレーヤーがビデオの特定のポイントからビデオを開始する必要がある場合、どの.ts
を簡単に計算できます。以前に表示されたチャンクの期間を合計することにより、要求する必要のあるファイル。 2行目は、ローカルファイル名またはそのファイルへのURLにすることができます。
.ts
を含むM3U8ファイルファイルは、HLSストリームの最も単純な形式であるメディアプレイリストを表します。簡単な例を開くことができます ここに 。
すべてのブラウザがデフォルトでHLSストリームを再生できるわけではないことに注意してください。
前のM3U8の例は、一連の.ts
を指しています。チャンク。それらは元のビデオファイルから作成され、サイズ変更されてエンコードされ、チャンクに分割されます。
つまり、導入部で概説した問題がまだ残っているということです。非常に遅い(または異常に速い)ネットワーク上のクライアントはどうでしょうか。または、画面サイズが非常に小さい高速ネットワーク上のクライアントですか?光沢のある新しいスマートフォンでファイルをすべて表示できない場合は、ファイルを最大解像度でストリーミングしても意味がありません。
HLSは、M3U8の別の「レイヤー」を導入することでこの問題を解決します。このM3U8ファイル しない .ts
へのポインタを含むファイルですが、他のM3U8ファイルへのポインタがあり、特定のビットレートと解像度用に事前に準備されたビデオファイルが含まれています。
このようなM3U8ファイルの例を次に示します。
#EXTM3U #EXT-X-STREAM-INF:BANDWIDTH=1296,RESOLUTION=640x360 https://.../640x360_1200.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=264,RESOLUTION=416x234 https://.../416x234_200.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=464,RESOLUTION=480x270 https://.../480x270_400.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=1628,RESOLUTION=960x540 https://.../960x540_1500.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=2628,RESOLUTION=1280x720 https://.../1280x720_2500.m3u8
ビデオプレーヤーは、次のような行のペアを選択します。
#EXT-X-STREAM-INF:BANDWIDTH=1296,RESOLUTION=640x360 https://.../640x360_1200.m3u8
これらは呼ばれます バリアント 異なるネットワーク速度と画面解像度用に準備された同じビデオの。この特定のM3U8ファイル(640x360_1200.m3u8
)には、サイズ変更されたビデオのビデオファイルチャンクが含まれています 640x360 ピクセルとビットレートの準備 1296kbps 。報告されるビットレートは考慮に入れる必要があることに注意してください ビデオストリームとオーディオストリームの両方 ビデオで。
ビデオプレーヤーは通常、最初のストリームから再生を開始します バリアント (前の例では、これは640x360_1200.m3u8です)。そのため、どのバリアントがリストの最初になるかを決定するために特別な注意を払う必要があります。他のバリアントの順序は重要ではありません。
最初の.tsファイルのダウンロードに時間がかかりすぎる場合(「バッファリング」が発生する、つまり次のチャンクを待機する)、ビデオプレーヤーはビットレートの小さいストリームに切り替わります。そしてもちろん、それが十分に速くロードされれば、それはより良い品質に切り替えることができることを意味します バリアント 、ただし、ディスプレイの解像度に意味がある場合に限ります。
インデックスM3U8リストの最初のストリームが最適なストリームではない場合、クライアントは適切なバリアントで解決するまで1〜2サイクル必要になります。
これで、HLSの3つのレイヤーができました。
.ts
ファイル (チャンク) ビデオの一部を含むバイナリファイルです。インデックスM3U8ファイルの例を見ることができます ここに (繰り返しますが、ブラウザ/ OSによって異なります)。
クライアントが低速または高速のネットワーク上にあることを事前に知っている場合があります。その場合、インデックスM3U8ファイルに別の最初のバリアントを提供することで、クライアントが適切なバリアントを選択できるようにすることができます。これを行うには2つの方法があります。
http://.../index_wifi.m3u8
を要求する必要があります。またはhttp://.../index_mobile.m3u8
。AppleのHTTPライブストリーミングには2つの重要な構成要素があります。 1つはビデオファイルの保存方法(後でHTTP経由で提供される)であり、もう1つは M3U8 プレーヤー(ストリーミングクライアントアプリ)にどのビデオファイルを取得するかを指示するインデックスファイル。
ビデオファイルから始めましょう。 HLSプロトコルは、ビデオファイルが同じ長さ(通常はそれぞれ10秒)の小さなチャンクに保存されることを想定しています。元々、これらのファイルはMPEG-2 TSファイル(.ts
)に保存し、MP3、HE-AAC、またはAC-3のオーディオでH.264形式でエンコードする必要がありました。
つまり、30秒のビデオは3つの小さい.ts
に分割されますそれぞれ約10秒の長さのファイル。
最新バージョンのHLSでは、断片化された.mp4ファイルも使用できることに注意してください。これはまだ新しいことであり、一部のビデオプレーヤーはまだ実装する必要があるため、この記事の例では.ts
を使用します。ファイル。
チャンクは、各ファイルの先頭にキーフレームを使用してエンコードする必要があります。各ビデオにはフレームが含まれています。フレームは画像ですが、ビデオ形式では完全な画像が保存されないため、ディスク容量が多すぎます。前のフレームとの違いだけをエンコードします。ビデオの中間点にジャンプする場合、プレーヤーは、最初の画像を表示するために、これらすべての差分を適用する場所から「開始点」を必要とし、次にビデオの再生を開始します。
だから.ts
チャンクの先頭にはキーフレームが必要です。プレイヤーはチャンクの途中から始める必要がある場合があります。プレーヤーは、最初のキーフレームからのすべての「差分」を追加することにより、常に現在の画像を計算できます。ただし、開始から9秒で開始する場合は、9秒の「差」を計算する必要があります。その計算を高速化するには、数秒ごとにキーフレームを作成するのが最善です(最高のcca3s)。
複数のビデオクリップを連続して再生したい場合があります。これを行う1つの方法は、元のビデオファイルをマージしてから、そのファイルを使用してHLSストリームを作成することですが、これには複数の理由で問題があります。動画の前後に広告を表示したい場合はどうなりますか?すべてのユーザーに対してこれを実行したくない場合や、ユーザーごとに異なる広告が必要な場合があります。もちろん、事前に異なる広告を含むHLSファイルを準備する必要はありません。
その問題を修正するために、タグ#EXT-X-DISCONTINUITY
があります。これはm3u8プレイリストで使用できます。この行は基本的に、この時点から.ts
という事実に備えて事前に準備するようにビデオプレーヤーに指示します。ファイルは異なる構成で作成される場合があります(たとえば、解像度が変更される場合があります)。プレイヤーはすべてを再計算し、場合によっては別のバリアントに切り替える必要があり、そのような「不連続」ポイントに備える必要があります。
「ビデオストリーミング」には基本的に2種類あります。 1つは ビデオオンデマンド (( VOD )事前に録画され、ユーザーが決定したときにユーザーにストリーミングされるビデオの場合。そこには 生放送 。 HLSはHTTPLive Streamingの略語ですが、これまでに説明したことはすべてVODを中心にしていますが、HLSを使用してライブストリーミングを作成する方法もあります。
M3U8ファイルにいくつかの変更があります。まず、#EXT-X-MEDIA-SEQUENCE:1
が必要ですバリアントM3U8ファイルのタグ。次に、M3U8ファイル してはいけません で終わる#EXT-X-ENDLIST
(それ以外の場合は、常に最後に配置する必要があります)。
ストリームを録画している間、常に新しい.ts
があります。ファイル。それらをM3U8プレイリストに追加する必要があり、新しいプレイリストを追加するたびに、#EXT-X-MEDIA-SEQUENCE:
のカウンターが追加されます。 1増やす必要があります。
ビデオプレーヤーがカウンターをチェックします。前回から変更された場合、ダウンロードして再生する新しいチャンクがあるかどうかがわかります。クライアントは新しいチャンクが再生されるのを待ってM3U8ファイルをリロードし続けるため、M3U8ファイルがキャッシュなしのヘッダーで提供されていることを確認してください。
HLSストリームのもう1つの興味深い機能は、Webビデオテキストトラックを埋め込むことができることです。 (MTB) それらのファイル。 VTTファイルはさまざまな用途に使用できます。たとえば、Web HLSプレーヤーの場合、ビデオのさまざまな部分の画像スナップショットを指定できます。ユーザーがビデオタイマー領域(ビデオプレーヤーの下)にマウスを移動すると、プレーヤーはビデオ内のその位置からスナップショットを表示できます。
VTTファイルのもう1つの明らかな用途は、字幕です。 HLSストリームは、複数の言語に対して複数の字幕を指定できます。
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID='subs',NAME='English',DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE='en',CHARACTERISTICS='public.accessibility.transcribes-spoken-dialog, public.accessibility.describes-music-and-sound',URI='subtitles/eng/prog_index.m3u8'
次に、theprog_index.m3u8
次のようになります:
#EXTM3U #EXT-X-TARGETDURATION:30 #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:30, 0000.webvtt #EXTINF:30, 0001.webvtt ...
実際のVTT(たとえば0000.webvtt
):
WEBVTT X-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000 00:00:01.000 --> 00:00:03.000 Subtitle -Unforced- (00:00:01.000) 00:00:03.000 --> 00:00:05.000 ...text here... -Unforced- (00:00:03.000) ...text here...
Appleは最近、VTTファイルに加えて、ストリーミング配信用に最適化された新しい字幕フォーマットであるIMSC1のサポートをHLSが特徴とすることを発表しました。その最も重要な利点は、CSSを使用してスタイルを設定できることです。
Appleは、いくつかの便利なHSLツールを導入しました。これらのツールについては、 公式HLSガイド 。
mediastreamsegmenter
という名前のツールを用意しました進行中のビデオストリームからその場でセグメントファイルを作成します。mediastreamvalidator
です。 M3U8プレイリストをチェックし、ビデオファイルをダウンロードして、さまざまな問題を報告します。たとえば、報告されたビットレートが.tsファイルから計算されたものと同じでない場合です。ビデオで最も頻繁に発生する問題の1つは、オーディオの同期です。一部のHLSストリームの音声がビデオと同期していないことがわかった場合(つまり、俳優が口を開いたが、音声が数ミリ秒早いか遅いことに気付いた場合)、元のビデオファイルが撮影された可能性があります可変フレームレートを使用します。必ず固定ビットレートに変換してください。
可能であれば、ソフトウェアが一定のフレームレートでビデオを録画するように設定されていることを確認することをお勧めします。
私は準備しました HLSAndroidアプリケーション Googleのを使用して事前定義されたHLSをストリーミングします ExoPlayer プレーヤー。ビデオとその下のHLS「イベント」のリストが表示されます。これらのイベントには次のものが含まれます:すべての.ts
ダウンロードされたファイル、またはプレーヤーがより高いまたはより低いビットレートストリームに切り替えることを決定するたび。
ビューアの初期化の主要部分を見ていきましょう。最初のステップでは、デバイスの現在の接続タイプを取得し、その情報を使用してm3u8
を決定します。取得するファイル。
String m3u8File = 'hls.m3u8'; ConnectivityManager connectivity = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = connectivity.getActiveNetworkInfo(); if (activeNetwork != null && activeNetwork.isConnectedOrConnecting()) { int type = activeNetwork.getType(); int subType = activeNetwork.getSubtype(); if (type == ConnectivityManager.TYPE_MOBILE && subType == TelephonyManager.NETWORK_TYPE_GPRS) { m3u8File = 'hls_gprs.m3u8'; } } String m3u8URL = 'https://s3-us-west-2.amazonaws.com/hls-playground/' + m3u8File;
これは厳密には必要ないことに注意してください。 HLSプレーヤーは、数チャンク後に常に正しいHLSバリアントに調整されますが、これは、最初の5〜20秒で、ユーザーがストリームの理想的なバリアントを視聴できない可能性があることを意味します。
m3u8
の最初のバリアントを覚えておいてくださいファイルは、ビューアが開始するファイルです。私たちはクライアント側にいて、接続タイプを検出できるので、少なくともm3u8
をリクエストすることで、最初のプレーヤーによるバリアント間の切り替えを回避することができます。この接続タイプ用に事前に準備されたファイル。
次のステップでは、HLSプレーヤーを初期化して起動します。
Handler mainHandler = new Handler(); DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder() .setEventListener(mainHandler, bandwidthMeterEventListener) .build(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); LoadControl loadControl = new DefaultLoadControl(); SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
次に、プレーヤーを準備し、このネットワーク接続タイプに適したm3u8をフィードします。
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, 'example-hls-app'), bandwidthMeter); HlsMediaSource videoSource = new HlsMediaSource(Uri.parse(m3u8URL), dataSourceFactory, 5, mainHandler, eventListener); player.prepare(videoSource);
そしてここに結果があります:
iOS上のビデオストリーミングアプリについては、Appleからの要件があります。 しなければならない ビデオが10分より長い場合、または5 MBより大きい場合は、HLSを使用してください。それ自体が、HLSが存続することを保証するものです。 HLSとMPEG-DASHについていくつかの懸念があり、どちらがWebブラウザの分野で勝者になるかについての懸念がありました。 HLSは、すべての最新のブラウザーに実装されているわけではありません(前のm3u8 URLの例をクリックすると、おそらく気づいたでしょう)。たとえば、Androidでは、4.0未満のバージョンではまったく機能しません。 4.1から4.4までは、部分的にしか機能しません(たとえば、オーディオが欠落している、またはビデオが欠落しているがオーディオは機能します)。
しかし、この「戦い」は最近少し単純になりました。林檎 発表 新しいHLSプロトコルは断片化されたmp4ファイル(fMP4
)を許可します。以前は、HLSとMPEG-DASHの両方をサポートしたい場合は、ビデオを2回エンコードする必要がありました。これで、同じビデオファイルを再利用して、メタデータファイル(HLSの場合は.m3u8
、MPEG-DASHの場合は.mpd
)のみを再パッケージ化できるようになります。
もう1つの最近の発表は、高効率ビデオコーデック(HEVC)のサポートです。使用する場合は、断片化されたmp4ファイルにパッケージ化する必要があります。そしてそれはおそらくHLSの未来がfMP4
であることを意味します。
ブラウザの世界の現在の状況では、タグの一部のブラウザ実装のみがHLSをすぐに再生できます。しかし、HLS互換性を提供するオープンソースおよび商用ソリューションがあります。それらのほとんどはFlashフォールバックを使用してHLSを提供しますが、JavaScriptで完全に記述された実装がいくつかあります。
この記事は特にHTTPライブストリーミングに焦点を当てていますが、概念的には、アダプティブビットレートストリーミング(ABS)がどのように機能するかについての説明として読むこともできます。結論として、HLSはビデオストリーミングの多くの重要な問題を解決するテクノロジーであると言えます。
最終的にHLSとMPEG-DASHのどちらを使用するかに関係なく、どちらのプロトコルも同様の機能を提供する必要があり、HLSにフラグメント化されたmp4(fMP4)が導入されたことで、同じビデオファイルを使用できます。つまり、ほとんどの場合、両方のプロトコルの基本を理解する必要があります。幸いなことに、それらは同じ方向に動いているように見えます。これにより、習得が容易になるはずです。
M3U(またはM3U8)は、MP3ファイルのコレクションを整理するために元々作成されたプレーンテキストファイル形式です。この形式はHLS用に拡張されており、メディアストリームの定義に使用されます。
c ++学習ガイド
HTTPライブストリーミング(HLS)は、2009年にAppleによって導入されたアダプティブビットレートストリーミングプロトコルです。m3u8ファイルを使用して、サーバーとクライアント間の通信用のメディアストリームとHTTPを記述します。これは、すべてのiOSデバイスのデフォルトのメディアストリーミングプロトコルです。
MPEG-DASHは、Apple HLSと同じようにHTTPを中心に構築された、広く使用されているストリーミングソリューションです。 DASHは、Dynamic Adaptive Streaming overHTTPの略です。
近年、HLSサポートがほとんどのブラウザに追加されました。ただし、違いは存続します。たとえば、ChromeとFirefoxは、デスクトッププラットフォームで部分的にしかサポートされていません。