最近のストリーミング(HLS配信)では、画質や解像度を選択できるようになっていることがほとんどですよね。
ffmpegでストリームを選択して動画をダウンロードし保存する方法をまとめておきます。
そもそも解像度を選べるストリーミングの仕組みは?
はじめに解像度を選択できる仕組みを軽く理解しておきましょう。
解像度を選択して再生できるようになっているストリーミング(HLS配信)では、各解像度の動画が異なるストリームとして用意されています。プレイリスト(m3u8)の内容を確認すると、解像度ごとに別個のストリームが用意されていることがわかります。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=300000,NAME="1080p",RESOLUTION=1920x1080
xxxx=.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=150000,NAME="720p",RESOLUTION=1280x720
xxyy==.m3u8
ユーザーが解像度を選択すると、該当するチャンクリストがダウンロードされ、指定された解像度の動画が再生される仕組みになっています。
mapオプションを使えば、ダウンロードする動画の解像度を選べる!
このように解像度を選べる方式のHLS配信は、ffmpegのmapオプションを使うと任意の解像度の動画をダウンロードできます。
mapオプションはストリームを選択するためのオプションです。複数のストリームが用意されているソースから任意のストリームを抽出することができます。HLS配信についてもmapオプションを使うことにより、任意の解像度の動画を抽出することが可能です。
ちなみにDVDの多重音声もストリームにより実現されているので、多重音声のソースから任意の言語の音声を取り出すのに使ったりすることもできます。ほかにも動画と音声データをくっつけたり、いろいろと活用できるオプションです。
サンプル
実際にやってみます。まずはmapオプションをつけずにffmpegを実行し、ストリーム情報を確認してみましょう。
m3u8を-iオプションに指定してffmpegを実行すると、以下のようにストリーム情報が出力されます。
$ ffmpeg -i "xxx.m3u8" -c -copy out.ts
Program 0
Metadata:
variant_bitrate : 3000000
Stream #0:0: Data: timed_id3 (ID3 / 0x20334449)
Metadata:
variant_bitrate : 3000000
Stream #0:1: Video: h264 (Constrained Baseline) ([27][0][0][0] / 0x001B), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
Metadata:
variant_bitrate : 3000000
Stream #0:2: Audio: aac (LC) ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp
Metadata:
variant_bitrate : 3000000
Program 1
Metadata:
variant_bitrate : 1500000
Stream #0:3: Data: timed_id3 (ID3 / 0x20334449)
Metadata:
variant_bitrate : 1500000
Stream #0:4: Video: h264 (Constrained Baseline) ([27][0][0][0] / 0x001B), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
Metadata:
variant_bitrate : 1500000
Stream #0:5: Audio: aac (LC) ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp
Metadata:
variant_bitrate : 1500000
もちろん情報の確認だけならffprobeでもOKです。ffprobeでストリーム情報を確認したいときは、次のコマンドとなります。
$ ffprobe "xxx.m3u8" -hide_banner -show_streams
出力されているProgramの番号をmapオプションに指定することで、任意のストリームを取り出すことができます。
例えば、上の例で1280×720の動画を抽出し、ローカルに保存したい場合はProgram 1をmapすることになるので、以下のようなコマンドになります。
ffmpeg -i "https://....m3u8" -map 0:p:1 -c copy "output.ts"
0:p:につづけて、Programの番号を指定します。すると、該当するProgramのストリームがファイルに保存されます。
”timed_id3 codec not currently supported”と表示されるとき
timed_id3のストリームが含まれているとき-c copyと併用するとエラーとなることがあります。
この場合はmapオプションにストリーム番号を直接指定します。
ffmpeg -i "https://....m3u8" -map 0:4 -map 0:5 -c copy "output.t
Program1のストリーム情報を見ると、映像が#0:4 音声が#0:5となっていることがわかるため、mapオプションに0:4と0:5を指定します。こうすることで正常に任意のストリームを保存することができます。
まとめ
ストリームを選択して、HLS配信されている動画をダウンロードする方法をメモしておきました。
mapオプションについては、公式ドキュメントにさらに詳しい使い方が載っていますので、参考にしてみてください。
コメント