Search code examples
ffmpeg

Cross-fade video to itself with FFmpeg for seamless looping


I have found some questions&answers concerning cross-fading between two images or videos, but which ffmpeg CLI commands are needed to fade a video with itself?

Explanation of the desired effect:

  • Some frames (let's say 1 second) are removed from the video's beginning
  • Starting in the video's last 1 second, the frames removed from the beginning are faded in over the end frames
  • This results in a smooth loop playback.

Solution

  • To expand a little on @llogan's answer using the times I was working with:

    -filter_complex "[0]trim=end=1,setpts=PTS-STARTPTS[begin];[0]trim=start=1,setpts=PTS-STARTPTS[end];[end][begin]xfade=wipedown:duration=1:offset=2"

    This is almost exactly what I was looking for (fade a video's end into its own beginning for looping) as well, after messing with the filters to figure out what they actually do. First off, here is a slightly clearer explanation of the xfade filter, which is actually super awesome and I'm stoked to know it exists. Try using one of the more dramatic fades to get a clearer picture of your transition.

    Breaking down the filtergraph a bit (the timestamps reflect the 4-second video I was looping):

    -filter_complex

    Call the filtergraph

    "[0]trim=end=1,setpts=PTS-STARTPTS[begin];

    Taking the first input ([0]) use the trim filter to make the section you want to fade in at the end of the video. Set the end of this excerpt to be at second 1 (it could be whatever, this makes a 1-second exerpt). Then use the setpts filter to set the timestamp (of the excerpt?) to start at zero. [begin] is the arbitrary label for the output of this first filter chain, but you can call it [thomas] or whatever.

    [0]trim=start=1,setpts=PTS-STARTPTS[end];

    Now use trim to make another input that's actually the entire video, minus the same 1 second that you'll be fading into at the end. This tripped me up a bit until I realized you're setting the end of the first chunk at the same point of the start of the main chunk. This main chunk gets the label [end].

    [end][begin]xfade=fade:duration=1:offset=2"

    Now use the xfade filter using the fade mode (there are examples of all the others in the link above) to dissolve from [end] into [begin]. You set the duration of the fade to last 1 second and offset the beginning of the fade at the 2 second mark. Keep in mind, this was a 4-second video that just got the first second basically trimmed and overlaid onto the end, so you now have a 3-second video. You could just as easily left the [end] chunk starting at 0 as well (the OP asked for what's described here tho).

    Give it an output.mov path and you're good to go.