HLSの中で変数や定数を使う
続けてのタグはこちらです。
EXT-X-DEFINE
プログラム経験がある方ならよく見る単語ですね。DEFINEは直訳すると「定義する」というような英単語ですが、よく定数などの定義命令として使用されています。Pythonのdefもdefineの略ですね。ということで名前の通り、HLSの中で定数を定義するためのタグになります。
HLSが高機能になっていくことで、どんどん記述が増えて行き視認性が悪くなっていきますので、こういったもので定数化しておいておくという流れは非常に有難いですね。
変数/定数機能を知る
ドラフトを見る
ドラフトの仕様はとても簡潔なのでぜひ目を通しておきましょう。
A Playlist MUST indicate an EXT-X-VERSION of 11 or higher if it contains:
* An EXT-X-DEFINE tag with a QUERYPARAM attribute.
またこのような記載もありますので、EXT-X-DEFINEのQUERYPARAMを使用する際にはEXT-X-VERSIONを11以上にしないといけないことがわかります。あとNAMEやIMPORTも8以上を要求します。このあたりも重要なポイントです。
想定される使用場面
定数化するシーンとしては、プログラムでもよくあるように、一か所を変えるだけで全体の動きを変えたいなどの場合ではないでしょうか。また定数ではなく変数としても使用できるので、その場合は状況によって動きを変えたい場合など、値を動的に変える必要がある場合などかと思います。
実質的に、HLSで簡単なプログラムが動かせるようになったという言い方をすると非常にその意義がわかるのではないかと思います。それではその想定で色々と動作を見て行きましょう。
HLSへの組み込み
NAME VALUE
まずは以前に作成したファイルを書き換えることで動かしてみましょう。
$ cp -r 1_normal/ 3_define/
$ cd 3_define
$ vi master.m3u8
再生が確認できている以前のストリームを再利用して確認していきます。
まずは確認ができればよいので、適当に一部を定数化してみます。
#EXTM3U
#EXT-X-VERSION:8
#EXT-X-DEFINE:NAME="audio_codec",VALUE="mp4a.40.2"
#EXT-X-DEFINE:NAME="playlist_name",VALUE="playlist"
#EXT-X-STREAM-INF:BANDWIDTH=1915831,AVERAGE-BANDWIDTH=761359,RESOLUTION=640x360,CODECS="avc1.64001e,{$audio_codec}"
v0/{$playlist_name}.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=713105,AVERAGE-BANDWIDTH=402205,RESOLUTION=426x240,CODECS="avc1.640015,{$audio_codec}"
v1/{$playlist_name}.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=379287,AVERAGE-BANDWIDTH=229047,RESOLUTION=256x144,CODECS="avc1.64000c,{$audio_codec}"
v2/{$playlist_name}.m3u8
音声コーデック情報が同じだったので試しに定数化してみました。
ただこれだけだと対応していないプレイヤーでも万が一再生できてしまうのではと思ったので、もっとクリティカルな部分としてプレイリスト名も定数化してみています。これなら完全にこのタグを解釈できるプレイヤーじゃないと再生が始まらないと思います。
さて、再生はできたでしょうか?この辺りはまだ対応していないプレイヤーもあり、全てが再生できるわけではありませんが、機能としては理解できたのではないでしょうか?
もちろんこれは単機能として使用するというよりは、他のタグと織り交ぜて使う際に補助的に使用するようなものになると思います。前の記事で書いたマルチCDNなどでも、CDNのアドレスなんかを定数にしておけばより見やすく、さらに別のCDNに変える場合なども一か所だけ変えればよいのでメンテナンス性が高まります。
IMPORT
次にIMPORTのテストの為、一つ前のファイルをコピーして書き換えてみます。
まずはマスタープレイリストですね。
$ cp -r 3_define/ 3_define_import/
$ cd 3_define_import
$ vi master.m3u8
EXT-X-DEFINE tags containing the IMPORT attribute MUST NOT occur in Multivariant Playlists; they are only allowed in Media Playlists.とあるように、基本形としてIMPORTはmaster.m3u8には記載しません。ここでは定義だけを行います。
#EXTM3U
#EXT-X-VERSION:8
#EXT-X-DEFINE:NAME="file_name",VALUE="segment"
このような形でmaster.m3u8に記載しておき、それをメディアプレイリストでインポートします。
vi v0/playlist.m3u8
:%s:/segment/{$file_name}/g
あとは上記の様なコマンドで置き換え処理をしてみます。
#EXTM3U
#EXT-X-VERSION:8
#EXT-X-DEFINE:IMPORT="file_name"
#EXT-X-TARGETDURATION:18
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.416667,
{$file_name}_000.ts
#EXTINF:12.625000,
{$file_name}_001.ts
#EXTINF:10.416667,
{$file_name}_002.ts
#EXTINF:10.416667,
{$file_name}_003.ts
これでmaster.m3u8で定義した定数を、下層のplaylist.m3u8でも使用することができます。上記の例でいえば、master.m3u8で定義したfile_name = segmentに従って、playlist.m3u8にてそれをインポートし、{$file_name}をsegmentに置き換えて再生しているという形になります。
QUERYPARAM
EXT-X-DEFINEの中でもQUERYPARAMは外部からの値を変数に代入できるという事で、非常に可能性のあるタグになっています。こちらもまずは動作確認をしてみましょう。
$ cp -r 1_aes/ 3_define_queryparam/
$ cd 3_define_queryparam
$ vi v0/playlist.m3u8
$ vi master.m3u8
これまでは、master.m3u8でNAMEで定義し、下層のplaylist.m3u8ではIMPORTをするという挙動でしたが、QUERYPARAMでそれをもっと簡単に実現してみましょう。まずはマスターを以下のように変更します。
#EXTM3U
#EXT-X-VERSION:11
#EXT-X-DEFINE:QUERYPARAM="file_name"
#EXT-X-DEFINE:QUERYPARAM="hls_ext"
#EXT-X-STREAM-INF:BANDWIDTH=1915831,AVERAGE-BANDWIDTH=761359,RESOLUTION=640x360,CODECS="avc1.64001e,mp4a.40.2"
v0/playlist.m3u8?file_name={$file_name}&hls_version={$hls_version}
#EXT-X-STREAM-INF:BANDWIDTH=713105,AVERAGE-BANDWIDTH=402205,RESOLUTION=426x240,CODECS="avc1.640015,mp4a.40.2"
v1/playlist.m3u8?file_name={$file_name}&hls_version={$hls_version}
#EXT-X-STREAM-INF:BANDWIDTH=379287,AVERAGE-BANDWIDTH=229047,RESOLUTION=256x144,CODECS="avc1.64000c,mp4a.40.2"
v2/playlist.m3u8?file_name={$file_name}&hls_version={$hls_version}
続いてメディアプレイリストも以下のように変更します。
#EXTM3U
#EXT-X-VERSION:11
#EXT-X-DEFINE:QUERYPARAM="file_name"
#EXT-X-DEFINE:QUERYPARAM="hls_ext"
#EXT-X-TARGETDURATION:18
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.416667,
{$file_name}_000.{$hls_ext}
#EXTINF:12.625000,
{$file_name}_001.{$hls_ext}
こちらに対して、master.m3u8?file_name=segment&hls_ext=tsのようにクエリパラメータを付与してアクセスする形になります。またmaster.m3u8に渡したクエリを引き継ぎ、そのままplaylist.m3u8でも使用できます。また前述したようにQUERYPARAMを使用する場合にはEXT-X-VERSIONは11以上にしておきましょう。
ただこちらの機能もまだプレイヤー側の対応が完全ではない為、まだまだ再生できない環境もあるかと思います。はやく完全な規格として確立してほしいですね。
またfile_nameとhls_extの2つを定義しましたが、片方だけでは再生はされないようです。
Error: EXT-X-DEFINE QUERYPARAM: "hls_ext" does not match any query parameter in URIというエラーが出ておりましたので、定義したものはすべて設定するようにしましょう。ただ多い分には無視されるようです。エラーになるのは足りない場合のみですね。まあプレイヤーの実装にもよりそうではありますが。
まとめ
NAMEやIMPORTはあまりピンとこなかったのですが、QUERYPARAMはクライアント毎に違う動きをさせられる可能性があるので非常に期待している機能です。ただTHEOなど一部プレイヤーではまだ動かないですね。今後の対応に期待しつつ待とうと思います。
Discussion