現状の ffmpeg では VTT字幕と、映像と音声のセグメントを合わせたマスタープレイリストを作れないので、マスタープレイリストを編集しなければならない。2020年4月9日以降はVTT字幕と、映像と音声のセグメントを合わせたマスタープレイリストを作れるようになった。多くのブラウザがプレイリストの直接再生に対応していないのでライブラリを使う。さらに ARIB字幕のある動画はlibaribb24、またはlibaribcaptionを有効化していないと変換できないうえ、有効化してないときは字幕を無効(-sn)にしないとエラーになる。有効化してないときは字幕の処理は行わない。

ffmpeg で Apple HTTP Live Streaming(HLS)を扱う

準備

HTML5 プレイヤの例

ffmpeg で HLS 出力するときに注意する点はいくつかあり、エンコード設定、解像度やフレームレート、ライブかVODか、遅延、視聴環境などそれぞれに対応する必要があるが、今回は試しやすい Windows10 での Edge、firefox、Chrome で再生確認し、配信環境を nginx、ngrok で作っている。

nginx: download
ngrok – secure introspectable tunnels to localhost

ngrok 導入方法 – Qiita
少しでも安全にngrokを使用する(Basic認証) – Qiita

ARIB字幕を変換するにはlibaribb24、またはlibaribcaptionを有効にする。
ARIB字幕をdemuxする libaribb24
ARIB字幕をdemuxするlibaribcaption

コーデックは H.264/AAC を使うので映像コーデックにはソフトウェアエンコード、ハードウェアエンコードそれぞれ配信環境に合わせて使う。AACエンコーダは配布できない FDK-AAC(-c:a libfdk_aac)があるので、こちらを試すなら media-autobuild_suiteでバイナリを用意する。

通常のARIB字幕付きHLS配信

デュアルモノラルのときだけ音声コーデックをcopyすると HLS で再生できない。それ以外はコピーしても再生できる(はず)。

[確認]NHK解説放送のmp4エンコード · Issue #244 · l3tnun/EPGStation

ffmpeg -analyzeduration 10MB -probesize 10MB -fix_sub_duration -i input.ts -vf yadif,scale=1280:720 -c:v libx264 -c:a aac -c:s webvtt -map 0:v -map 0:a:0 -map 0:s -f hls -var_stream_map "0:v:0,a:0,s:0,sgroup:subtitle" -master_pl_name master.m3u8 -hls_list_size 0 720p.m3u8

master.m3u8 の出力例。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subtitle",NAME="subtitle_0",DEFAULT=YES,URI="720p_vtt.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2",SUBTITLES="subtitle"
720p.m3u8

字幕原語をつける書き換え例。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subtitle",NAME="Japanese",DEFAULT=YES,LANGUAGE="jp",URI="720p_vtt.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2",SUBTITLES="subtitle"
720p.m3u8

BANDWIDTHタグはビットレートの目安となり、DEFAULT, AUTOSELECT, FORCEDタグは字幕の表示設定に関わる。GROUP-IDタグで指定したものをSUBTITLESタグで指定することでそのストリームに字幕を載せることができる。

VTT字幕付きで再生するには hls.jsを使う。HLSを使って重い動画をWEBサイトに実装する – Qiitaを参考に、html ファイルを作成して、hls.loadSource 内のプレイリストを master.m3u8 に変更する。参照している(https://cdn.jsdelivr.net/npm/hls.js@latest)は Releases · video-dev/hls.jsの hls.min.js と同じである。

これで最初から字幕付きのHLSで再生できる。最初から字幕を非表示にするにはDEFAULT, AUTOSELECT, FORCEDを無指定にしておく。

映像と音声のプレイリストと字幕のプレイリストを出力する例。
ffmpeg -analyzeduration 10MB -probesize 10MB -fix_sub_duration -i input.ts -vf yadif,scale=1280:720 -c:v libx264 -c:a aac -c:s webvtt -map 0:v -map 0:a:0 -map 0:s -f hls -hls_list_size 0 720p.m3u8

vtt字幕付きのプレイリストは4.3.1時点で通常には読み込めないので入力オプションに-strict experimentalをつける。

コーデックコピーすると字幕はそのままvtt形式になりPCで見るならおそらく再生できる。
ffmpeg -strict experimental -i "https://example.com/master.m3u8" -c copy output.mkv

モバイル端末向けには字幕をmov_text形式に変更しMP4出力にする。
ffmpeg -strict experimental -i "https://example.com/master.m3u8" -c copy -c:s mov_text output.mp4

途中の字幕を映像と一緒にコピーするにはその時間までデコード(入力ファイルの後ろに-ss)してからコーデックコピーする。
ffmpeg -i input -c:v copy -c:a copy -c:s copy -ss 0:23:10.5 -to 0:24:40 output

ffmpeg で指定時間でカットするまとめ

字幕をファイルではなく映像に焼き付けるにはsubtitlesフィルタを使う。

字幕ファイルは別途ファイルとして入力しなければならない。
ffmpeg -i "https://example.com/master.m3u8" -vf subtitles=sub.vtt -c:a copy output.mp4

字幕ファイルを動画に焼き付ける subtitles

複数言語の音声に、言語に合わせたvtt字幕を別ファイルで読み込む場合。

ffmpeg -i sample.mp4 -i sample-vtt-en.vtt -i sample-vtt-es.vtt \
  -map 0:v -map 0:a -map 0:a -map 1 -map 2 \
  -c:v copy -c:a copy -c:s webvtt \
  -metadata:s:s:0 language=en \
  -metadata:s:s:1 language=es \
  -start_number 0 -hls_time 10 -hls_list_size 0 -f hls \
  -var_stream_map "v:0,name:video a:0,s:0,language:eng,name:english a:1,s:1,language:spa,name:espanol" \
  -master_pl_name master.m3u8 \
  out/sample.m3u8

http live streaming – Converting MP4 into m3u8 with multiple subtitle tracks using ffmpeg – Stack Overflow

fmp4 に変更する

上のコマンド例に-hls_segment_type 1を追加する。
ffmpeg -analyzeduration 10MB -probesize 10MB -fix_sub_duration -i input.ts -vf yadif,scale=1280:720 -c:v libx264 -c:a aac -c:s webvtt -map 0:v -map 0:a:0 -map 0:s -f hls -var_stream_map "v:0,a:0,s:0,sgroup:subtitle" -master_pl_name master.m3u8 -hls_list_size 0 -hls_segment_type 1 720p.m3u8

hevcにエンコードする。
ffmpeg -analyzeduration 10MB -probesize 10MB -fix_sub_duration -i input.ts -vf yadif,scale=1280:720 -c:v libx265 -tag:v hvc1 -c:a aac -c:s webvtt -map 0:v -map 0:a:0 -map 0:s -f hls -var_stream_map "v:0,a:0,s:0,sgroup:subtitle" -master_pl_name master.m3u8 -hls_list_size 0 -hls_segment_type 1 720p.m3u8

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)