Crossfade-concatenate clips, optionally overlaying one audio track
Description
Joins videos in order, dissolving each transition over fade
seconds (the duplicated conditioning overlap, so the blend is between
near-identical frames and is invisible). When audio is given it
becomes the sole audio track – the right move for chained chunks, whose
per-chunk audio has a silent conditioning head; the continuous narration has
no such gaps. Without audio, the first clip’s audio is mapped through.
Usage
crossfade_concat(videos, output, fade = 0.375, audio = NULL,
transition = "dissolve", cuts = NULL, windows = NULL,
overwrite = TRUE, dry_run = FALSE)
Arguments
videos: Character vector of video paths, in order. Must share resolution / fps / pixel format (xfade requires it).output: Output video path.fade: Crossfade duration in seconds: a scalar applied to every join, or a vector with one duration per join (lengthlength(videos) - 1). A join withfade0 is a plain butt join – no overlap consumed, no dissolve – for boundaries where the next clip has no duplicated conditioning head (seealign_overlaps). Default 0.375 (= 9 frames @ 24fps, the default conditioning overlap).audio: Optional path to a continuous audio track to overlay as the sole audio (e.g. the track’s full narration mp3).transition: xfade transition name (default"dissolve").cuts: Optional logical vector, one per join (length `length(videos)- 1
).TRUEmakes that join a hard cut (trim the next clip's head by that join'sfadeand butt-join) instead of a crossfade.NULL(default) = all crossfades. Output length is the same either way; a cut at a zero-fade` join is just a butt join. windows: Optional list, one element per video:c(start, end)in seconds selecting the part of the file to feed in (NAend = to the end of file), orNULLfor the whole file. For a crossfaded join the incoming window should include the head handle the fade consumes (the fade eatsfadeseconds off the window’s front against the previous clip’s tail). Used byrender_timelineto honor OTIO source ranges.overwrite: Overwriteoutput(default TRUE).dry_run: If TRUE, return the ffmpeg command string without running.
Details
Each join consumes its fade seconds of overlap, so the result runs
sum(durations) - sum(fades) long – slightly shorter than a hard
concat. One ffmpeg pass via xfade.
Value
Invisibly, output (or the command string when dry_run).
Examples
crossfade_concat(c("chunk01.mp4", "chunk02_chained.mp4", "chunk03_chained.mp4"),
"video.mp4", fade = 0.375, audio = "audio.mp3")