ABRが可能な配信形式に変換する
まず、ABRがどういう仕組みで動いているかを理解していきましょう。冒頭に記載した通り、ABRは様々な条件を加味して複数定義されたストリームから最適なストリームを選択できるようになる技術です。「どれが最適か?」の判断はクライアント(プレイヤー)側で行われるため、判断と切り替えに必要な各ストリームの情報(ストリームのURL/ビットレート/解像度/フレームレート/コーデック等々)をプレイヤーに提供する必要があります。
極論ではありますが、それらの情報さえ提供すればどんなストリームであってもABRすることは可能です。例えばここまで何度も紹介してきたプログレッシブMP4でもABRを実現することは可能ですし、実際に動作させるライブラリ等もあったりはします。しかしながら、互換性の面やストリーム切替時のオーバーヘッドの多さを考えると、やはりABRの実現を初めから見据えられて作られた配信形式を利用する方が無難であると言えるでしょう。
そういったABRを念頭に置いて設計された配信形式には、HLSやMPEG-DASHなどがあります。これらの配信形式を用いると、各種情報を容易にプレイヤーに提供することできます。なおかつストリームの切り替えが考慮されたデータ構造になっているため、オーバーヘッドが少なく安定してストリームを切り替えることができます。
今回はHLS(HTTP Live Streaming)を用いていきます。HLSはプレイリスト(playlist)と呼ばれるテキストファイルと、チャンク(chunk)と呼ばれるストリームの実データで構成されています。プレイリストには2種類あり、ABRの対象となるストリームの一覧と、各ストリームの情報(ビットレートやコーデック情報)が記載されているマスタープレイリストと、チャンクに関する情報が記載されているプレイリストファイル(チャンクリスト(chunklist)と呼ぶこともあります)です。チャンクは時系列で映像を分割したデータとなっており、チャンクリストにはそのストリームを構成するチャンクの一覧と、それぞれ個々のチャンクが対応する再生位置が記載されています。
プレイリストはマルチメディアプレイリストファイル(M3U:Moving Picture Experts Group Audio Layer 3 Uniform Resource Locator)を拡張したExtended M3Uの形式になっており、専門知識がなくてもある程度目で見て理解できる内容となっています。

大雑把に説明すると、各ストリームは数秒ごとに分割されチャンクとなっており、プレイリストと呼ばれる「地図」のようなもので、「このビットレートでこの秒数のチャンクはこれ」というような情報がまとめられているという感じです。
HLSと共によく使われるMPEG-DASHも似たファイル構成です。MPEG-DASHではマニフェスト(manifest)と呼ばれるXMLファイルと、セグメント(segment)と呼ばれるストリームの実データで構成されています。前者がプレイリストと同様の役割を持っており、後者がチャンクと同様の役割を持っています。
さて、それでは先程作成したMP4ファイルを入力として、ABRに対応したHLSのストリームを用意していきます。
ffmpeg \ -i 240p.mp4 \ -i 480p.mp4 \ -i 720p.mp4 \ -i 1080p.mp4 \ -map 0 \ -bsf:v:0 h264_mp4toannexb \ -c copy \ -hls_list_size 0 \ -movflags +faststart \ -hls_time 4 \ -map 1 \ -bsf:v:1 h264_mp4toannexb \ -c copy \ -hls_list_size 0 \ -movflags +faststart \ -hls_time 4 \ -map 2 \ -bsf:v:2 h264_mp4toannexb \ -c copy \ -hls_list_size 0 \ -movflags +faststart \ -hls_time 4 \ -map 3 \ -bsf:v:3 h264_mp4toannexb \ -c copy \ -hls_list_size 0 \ -movflags +faststart \ -hls_time 4 \ -master_pl_name playlist.m3u8 \ -master_pl_publish_rate 4 \ -var_stream_map "v:0,a:0,name:240p v:1,a:1,name:480p v:2,a:2,name:720p v:3,a:3,name:1080p" "%v/output.m3u8"
「-hls_time」はチャンクを作る際に切り刻む秒数を設定しています。ABRをスムーズに実行するために、すべてのストリームで同じ値にするようにしましょう。プレイヤーの実装にもよりますが、大抵は新しいチャンクの読み込み時に別のストリームに切り替えるかどうかの判断が行われます。今回は4秒に設定しているので、4秒に1回ストリームが切り替わる可能性があります。
これによってHLSのプレイリストファイル(.m3u8)と、ストリームの本体であるチャンク(.ts)が完成しました。「playlist.m3u8」と言うファイルと、「240p」「480p」「720p」「1080p」というディレクトリができていると思うので、これまで使ってきたindex.htmlと同じディレクトリに移動させておいてください。
なお、HLSで扱えるチャンクには様々なコンテナ形式があります。よく使われるものとしてMPEG-2 TS(.ts)やFragmented MP4(.fmp4/mp4)があります。コンテナ形式によっても、特徴やできることが変わってくるため、要件次第ではその部分も熟考することが必要となります。