Search code examples
videoffmpegcutcross-fade

ffmpeg - seamless crossfade loop for the part of video


I need to apply crossfade to the last X frames of a video with the first X frames in order to obtain a seamless loop, but making this for the necessary part of video.

Here's the answer for looping the entire video.

Currently what I have: (Whole video duration = 25. Cutted (result) part = 15 sec (from 5 to 20 sec pos). Transition = 1 sec.)

ffmpeg -i input.mp4 -ss 5 -to 20 -filter_complex
    "[0]split[body][pre];
     [pre]trim=duration=1,format=yuva420p,fade=d=1:alpha=1,setpts=PTS+( (15+(5-1)) /TB)[jt];
     [body]trim=1,setpts=PTS-STARTPTS[main];
     [main][jt]overlay"  -c:v libx264 -preset veryslow -b:v 2500K output.mp4
 

In this case, everything works, but at the end of the resulting video, a piece from the original video is superimposed, which starts from 0 to 1 second, and not from 4 to 5 seconds of the original video, as it should be.

I read the official ffmpeg documentation, tried some actions on "start/end" parameters for "trim/fade" with changing of "setpts", but I always got just another batch of bugs.


Solution

  • After spending some more time, I decided to start from something easier for understanding (easier logic). I just remove -ss/-to and modify the -filter_complex by spliting the original video into 3 streams, from which I cut out the corresponding parts. The last 2 streams of the same length I have superimposed on each other using the method from my question. After that, I re-combined them in the correct sequence.

    (For clarity, I enclosed variables in more and less signs.)

    -filter_complex "[0]split=3[var1][var2][var3];
    [var1]trim= <cut_start> : (<cut_start> + <duration> - <fade_time>),setpts=PTS-STARTPTS[v0];
    [var2]trim= (<cut_start> + <duration> - <fade_time>) : (<cut_start> + <duration>),setpts=PTS-STARTPTS[v1];
    [var3]trim= (<cut_start> - <fade_time>) : <cut_start> ,format=yuva420p,fade=start_time= (<cut_start> - <fade_time>) :duration= <fade_time> :alpha=1,setpts=PTS-STARTPTS[v2];
    [v1][v2]overlay[v3];
    [v0][v3]concat=n=2:v=1:a=0[out]" -map "[out]"