FFmpeg xfade Chain for N Clips — effect skill for transitions

For AI agents: find the right skill in one call — curl -s "https://skills.varg.ai/api/search?q=<what the person wants>" returns the matching how-to page and the best skills with install commands, as markdown (Russian works too). Full index: https://skills.varg.ai/llms.txt. Every page has a markdown twin: add .md to its path. Before generating anything, show the person the options on the how-to page.

Chain xfade + acrossfade across N clips; offset of the k-th transition = d1+…+dk − k·T.

What it does

Every join gets the same transition; total length = sum of clip durations − (N−1)·T.

When: Batch slideshows, AI-shot sequences and reels where an agent must join many clips with transitions in one render.

Watch out: Offsets computed from the source clips instead of the running output; and clips shorter than T.

Timing: T usually 0.3–1.0 s; same T for every join keeps the math simple

Also called: xfade offset math, chained xfade, acrossfade chain, slideshow transitions

In FFmpeg

Each xfade's offset is measured on its first input, which is the output of the previous xfade (already shortened by (k−1)·T). So offset_k = (d1 + … + dk) − k·T. acrossfade overlaps audio by the same T, keeping it in sync.

#!/usr/bin/env bash
# xfade-chain.sh <transition> <T> out.mp4 clip1 clip2 [clip3 ...]   (tested with ffmpeg 8.1)
set -euo pipefail
TR=$1; T=$2; OUT=$3; shift 3
W=1080; H=1920; FPS=30; n=$#; i=0; off=0; f=""; inputs=()
for c in "$@"; do
  inputs+=(-i "$c")
  f+="[$i:v]fps=$FPS,scale=$W:$H:force_original_aspect_ratio=decrease,pad=$W:$H:(ow-iw)/2:(oh-ih)/2,setsar=1,format=yuv420p,settb=AVTB,setpts=PTS-STARTPTS[v$i];"
  f+="[$i:a]aresample=48000,aformat=channel_layouts=stereo,asetpts=PTS-STARTPTS[a$i];"
  i=$((i+1))
done
vp=v0; ap=a0; i=1
for c in "${@:1:$((n-1))}"; do
  d=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$c")
  off=$(echo "$off + $d - $T" | bc -l)            # offset_k = d1+..+dk - k*T
  f+="[$vp][v$i]xfade=transition=$TR:duration=$T:offset=$off[vx$i];"
  f+="[$ap][a$i]acrossfade=d=$T[ax$i];"
  vp=vx$i; ap=ax$i; i=$((i+1))
done
ffmpeg -y "${inputs[@]}" -filter_complex "${f%;}" -map "[$vp]" -map "[$ap]" \
  -c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac -movflags +faststart "$OUT"

Tested: 5 s + 4 s + 6 s with T = 0.5 → 14.0 s output.

Where this comes from

Use when

Not for

Install

Example output

https://s3.varg.ai/how-to/previews/4f24964231a8/take-ffmpeg-xfade-chain.mp4 — fade between two shots, with the timeline strip of the edit. Footage: Coffee Run (2020), Blender Studio | studio.blender.org, CC BY 4.0; Coffee Run (2020), Blender Studio | studio.blender.org, CC BY 4.0. (credit: Rendered by varg · Coffee Run (2020))

More transitions skills