xfade は、2本の動画の切り替わりに、クロスフェードやワイプなどの効果(トランジション)をかけるフィルタです。
基本構文
2つのクリップを、1秒のクロスフェードでつなぐ例です。
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=fade:duration=1:offset=4[v]" -map "[v]" output.mp4
offset は、トランジションを始める位置です。1本目のクリップの開始から数えた秒数で指定します。
| パラメータ | 説明 | デフォルト |
|---|---|---|
transition |
トランジションの種類 | fade |
duration |
トランジションの長さ(秒) | 1 |
offset |
トランジションを始める位置(秒) | 0 |
offset の計算方法
たとえばクリップ1が10秒で、最後の2秒をトランジションにしたいときは offset=8 にします。
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=fade:duration=2:offset=8[v]" -map "[v]" output.mp4
出力の長さは、自動で offset + クリップ2の長さ になります(10 秒のクリップ 2 本なら 8 + 10 = 18 秒)。これは「クリップ1の長さ + クリップ2の長さ − トランジションの長さ」と同じ値なので、-t で長さを指定する必要はありません。
計算式は offset = クリップ1の長さ − duration です。この式から外れた値にすると、次のようなことが起きます。
offset + durationがクリップ1より短いとき:クリップ1の残りは切り捨てられます。5 秒のクリップ 2 本をoffset=1:duration=2でつなぐと、出力は 6.0 秒(1 + 5)です。offsetがクリップ1の長さを超えているとき:トランジションは起きず、クリップ2 がまるごと消えます。同じクリップでoffset=8にすると、出力はクリップ1とほぼ同じ長さ(5.03 秒)です。2 本目が出てこないときは、まずここを確認してください。
利用可能なトランジション
transition= の値を変えるだけで、効果が切り替わります。
フェード系
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=fade:duration=1:offset=4[v]" -map "[v]" output.mp4
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=fadeblack:duration=1:offset=4[v]" -map "[v]" output.mp4
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=fadewhite:duration=1:offset=4[v]" -map "[v]" output.mp4
スライド系
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=slideleft:duration=0.8:offset=4[v]" -map "[v]" output.mp4
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=slideright:duration=0.8:offset=4[v]" -map "[v]" output.mp4
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=slideup:duration=0.8:offset=4[v]" -map "[v]" output.mp4
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=slidedown:duration=0.8:offset=4[v]" -map "[v]" output.mp4
ワイプ系
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=wipeleft:duration=0.5:offset=4[v]" -map "[v]" output.mp4
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=wipetl:duration=1:offset=4[v]" -map "[v]" output.mp4
ズーム・円形ワイプ
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=zoomin:duration=0.8:offset=4[v]" -map "[v]" output.mp4
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=circleopen:duration=1:offset=4[v]" -map "[v]" output.mp4
その他のトランジション一覧
fade, fadeblack, fadewhite, distance, wipeleft, wiperight, wipeup, wipedown, slideleft, slideright, slideup, slidedown, smoothleft, smoothright, smoothup, smoothdown, circleopen, circleclose, vertopen, vertclose, horzopen, horzclose, dissolve, pixelize, diagtl, diagtr, diagbl, diagbr, hlslice, hrslice, vuslice, vdslice, hblur, fadegrays, wipetl, wipetr, wipebl, wipebr, squeezev, squeezeh, zoomin, fadefast, fadeslow, circlecrop, rectcrop, radial, hlwind, hrwind, vuwind, vdwind, coverleft, coverright, coverup, coverdown, revealleft, revealright, revealup, revealdown
このほか custom を選ぶと、expr に書いた式で効果を自作できます。使える名前は ffmpeg -h filter=xfade でも確認できます。
音声付きクロスフェード(acrossfade)
映像と一緒に音声もクロスフェードさせるには、acrossfade を組み合わせます。
ffmpeg -i input.mp4 -i input.mp4 -filter_complex "[0:v][1:v]xfade=transition=fade:duration=1:offset=4[v];[0:a][1:a]acrossfade=d=1[a]" -map "[v]" -map "[a]" output.mp4
acrossfade=d=1 は、音声を1秒かけてクロスフェードする指定です。-map "[v]" -map "[a]" で、つないだ映像と音声の両方を出力に入れています。
acrossfade には offset がなく、いつも1本目の最後の d 秒と2本目の最初を重ねます。そのため、映像と音声の切り替わりがそろうのは、offset が「クリップ1の長さ − duration」のときだけです(この例は 5 秒のクリップを想定しています)。たとえば 5 秒のクリップ 2 本を offset=1:duration=2 と acrossfade=d=2 でつなぐと、映像は 6.0 秒、音声は 8.03 秒になり、ずれます。
3本以上のクリップを連結する
3本のクリップを、順番にフェードでつなぐ例です。
ffmpeg -i input.mp4 -i input.mp4 -i input.mp4 \
-filter_complex "[0:v][1:v]xfade=transition=fade:duration=1:offset=4[v01];[v01][2:v]xfade=transition=fade:duration=1:offset=8[vout]" \
-map "[vout]" output.mp4
まず1本目と2本目をつなぎ、その結果([v01])に3本目をつなぎます。offset はどちらも、1本目の開始から数えた通しの秒数で指定します。
注意事項
つなぐ2本は、解像度とフレームレートに加えて、タイムベース(時刻を数える単位)もそろっている必要があります。解像度とフレームレートが同じでも、タイムベースが違うと First input link main timebase (1/15360) do not match the corresponding second input link xfade timebase (1/90000) のようなエラーで止まります。違うときは、先にそろえてください。下の例では、scale と fps で2本を同じ解像度とフレームレートにして書き出してから、xfade でつないでいます。同じ fps で MP4 に書き出すと、タイムベースもそろいます。
ffmpeg -i clip1.mp4 -vf "scale=1280:720,fps=30" -c:v libx264 clip1_norm.mp4
ffmpeg -i clip2.mp4 -vf "scale=1280:720,fps=30" -c:v libx264 clip2_norm.mp4
ffmpeg -i clip1_norm.mp4 -i clip2_norm.mp4 -filter_complex "[0:v][1:v]xfade=transition=fade:duration=1:offset=4[v]" -map "[v]" output.mp4
中間ファイルを作らずに、フィルタの中でそろえることもできます: [0:v]scale=1280:720,fps=30,format=yuv420p,settb=AVTB[a];[1:v]scale=1280:720,fps=30,format=yuv420p,settb=AVTB[b];[a][b]xfade=transition=fade:duration=1:offset=4[v]