2つの動画をクロスフェードした動画を作るには FFmpeg の xfade フィルタを使う

試した環境

本題

1番目の動画の終わりと2番目の動画の始めとを重ねてフェードしながら切り替わるつなぎ方をクロスフェードと言います。 AviUtl では以下のタイムライン画像のようにシーンチェンジフィルタの「クロスフェード」を使うことで実現できます。

f:id:kakashibata:20201122232451p:plain

しかし、このくらい単純な動画編集の場合、動画編集ソフトを使わずとも FFmpeg で済ませられないか考えたくなります。
FFmpegクロスフェードでつなげた動画を作成するには xfade フィルタを使います。
以下のバッチスクリプトでは、1番目の動画の最終2秒と2番目の動画の開始2秒とをクロスフェードでつなげた動画を生成します。 ここでは1番目の動画が5秒のためフェード時間を引いた3秒をoffset=3オプションで指定しています。

set INPUT1=./countup_b.mp4
set INPUT2=./countup_g.mp4
set OUTPUT=fade01.mp4

ffmpeg -i %INPUT1% -i %INPUT2%^
  -filter_complex xfade=transition=fade:duration=2:offset=3^
  %OUTPUT% -y

上記のスクリプトで生成される動画ではフェード中も動画が再生されている状態ですが、 フェード中は静止画にしたい場合もあると思います。 AviUtl では以下のタイムライン画像のように「直前オブジェクト」や再生速度を0にしたオブジェクトを使用することで実現できます。

f:id:kakashibata:20201122232454p:plain

FFmpeg でこれを実現するには tpad フィルタで重なる部分をパディングします。 以下のバッチスクリプトで1番目の動画の最終フレームと2番目の動画の開始フレームとを2秒間クロスフェードでつなげた動画を生成します。 ここでは1番目の動画が5秒のためoffset=5オプションを指定しています。

set INPUT1=./countup_b.mp4
set INPUT2=./countup_g.mp4
set OUTPUT=fade02.mp4

ffmpeg -i %INPUT1% -i %INPUT2%^
  -filter_complex "[0]tpad=stop_mode=clone:stop_duration=2[vfirst]; [1]tpad=start_mode=clone:start_duration=2[vsecond]; [vfirst][vsecond]xfade=transition=fade:duration=2:offset=5"^
  %OUTPUT% -y

参考

Xfade – FFmpeg