ffmpeg 4.5から使える予定のフィルタ。いままではselect、aselect
フィルタで複数の区間をフィルタ内で分割できたのがより直感的に分割できるようになった。タイムライン編集が使えないフィルタを使ったり、エンコードパラメータを複数使い分けて1つのファイルに戻すなどに使う。
特定の映像フレームや音声サンプルを出力するselect, aselect
Tがあればタイムライン編集に対応している。
ffmpeg -filters : gist.github.com
基本コマンド
最初から90秒まで、90秒から180秒まで、180秒から最後まで分割出力する。setpts、asetpts
フィルタを使いPTSをリセットする。
ffmpeg -i input -filter_complex "segment=90|180[0v][1v][2v];[1v]setpts=PTS-STARTPTS[1v];[2v]setpts=PTS-STARTPTS[2v];asegment=90|180[0a][1a][2a];[1a]asetpts=PTS-STARTPTS[1a];[2a]asetpts=PTS-STARTPTS[2a]" -map [0v] -map [0a] output1.mp4 -map [1v] -map [1a] output2.mp4 -map [2v] -map [2a] output3.mp4
タイムライン編集が使えないaddroi
フィルタを使い、区間ごとに品質を変更する。
ffmpeg -i input -filter_complex "segment=90|180[0v][1v][2v];[1v]addroi=0:0:iw:ih:-2/51,setpts=PTS-STARTPTS[1v];[2v]addroi=0:0:iw:ih:2/51,setpts=PTS-STARTPTS[2v];[0v][1v][2v]concat=n=3:v=1:a=0" -c:v libx264 -crf 23 -c:a copy output.mp4
秒指定ではなくhh:mm:ss形式はシングルクォートで挟みエスケープする。
ffmpeg -i input -filter_complex "segment='00\:01\:00|00\:01\:30'[0v][1v][2v];[1v]addroi=0:0:iw:ih:-2/51,setpts=PTS-STARTPTS[1v];[2v]addroi=0:0:iw:ih:2/51,setpts=PTS-STARTPTS[2v];[0v][1v][2v]concat=n=3:v=1:a=0" -c:v libx264 -crf 23 -c:a copy output.mp4
concat
フィルタで連結せずに分割のままエンコードパラメータを変更してx264のstitchableを有効にしてエンコードし、改めて1つのファイルにconcat
する方法もある。この場合はsegmentmuxerで分割しても同じことができる。2番目以降のエンコードパラメータ部分のあるmdatをbsf
フィルタで消すことでバイナリを少し小さくできる。音声を分割出力すると後で連結したときに分割部分が瞬間的に途切れることがあるのでconcat
で連結して出力する。
ffmpeg -i input -filter_complex "segment=90|180[0v][1v][2v];[1v]setpts=PTS-STARTPTS[1v];[2v]setpts=PTS-STARTPTS[2v];asegment=90|180[0a][1a][2a];[1a]asetpts=PTS-STARTPTS[1a];[2a]asetpts=PTS-STARTPTS[2a];[0a][1a][2a]concat=n=3:v=0:a=1[a]" -map [0v] -crf 23 -x264-params stitchable=1 output1.mp4 -map [1v] -crf 20 -x264-params stitchable=1 -bsf:v filter_units=remove_types=6 output2.mp4 -map [2v] -crf 27 -x264-params stitchable=1 -bsf:v filter_units=remove_types=6 output3.mp4 -map [a] audio.m4a
concat.txt file output1.mp4 file output2.mp4 file output3.mp4
分割部分が一定間隔でないとfpsがおかしくなることがあるのでsetts
ビットストリームフィルタで修正する。
ffmpeg -f concat -safe 0 -i concat.txt -i audio.m4a -bsf:v setts=dts=N/((24000/1001)*TB):pts=PTS+N/((24000/1001)*TB)-DTS -c copy output.mp4
特定フレーム間に別のエンコードパラメータを使い分ける方法にx264のzonesがある。
ffmpeg_libx264.md : gist.github.com
concat
フィルタの代わりにinterleave
フィルタで連結する方法もある。こちらはPTSリセットが不要なのと、出力オプションに元の映像のフレームレート-rを指定しないと正常なフレームで出力できない。
ffmpeg -i input -filter_complex "segment=90|180,interleave=3" -r 30000/1001 output
ffmpeg -i input -filter_complex "segment=90|180,interleave=3;asegment=90|180,ainterleave=3" -r 30000/1001 output
公式ドキュメント:FFmpeg Filters Documentation : segment, asegment
オプション
|毎に分割する時間を指定し、指定数プラス1が出力数になる。時間指定のほかに映像はフレーム指定、音声はサンプル指定ができる。各数値の接頭辞に+をつけると前の分割位置からの相対位置指定になる。
- timestamps[string]
時間指定。秒指定と、hh:mm:ss指定ができる。hh:mm:ss形式はシングルクォートで挟みエスケープする - frames[string]
フレーム指定。segment
フィルタで使える - samples[string]
サンプル指定。asegment
フィルタで使える