1

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.
PhilLab
  • 4,777
  • 1
  • 25
  • 77

3 Answers3

5

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.

camposquinn
  • 106
  • 1
  • 8
3

Use the trim, setpts, and xfade filters:

ffmpeg -i input.mp4 -filter_complex "[0]trim=end=1,setpts=PTS-STARTPTS[begin];[0]trim=start=1,setpts=PTS-STARTPTS[end];[end][begin]xfade=fade:duration=0.5:offset=8.5" output.mp4
llogan
  • 121,796
  • 28
  • 232
  • 243
  • the offset=8.5 is problematic here as I don't know the video length in general – PhilLab Feb 04 '20 at 14:50
  • Additionally, I can't observe the fade effect in the resulting video, even if I increase the fade duration and set the offset to a smaller value – PhilLab Feb 04 '20 at 15:03
  • @PhilLab 1. [Use `ffprobe` to get duration value](https://superuser.com/questions/650291/how-to-get-video-duration-in-seconds/945604#945604). 2. Show your command and the full log. You can [edit](https://stackoverflow.com/posts/60043174/edit) your question to include this info. – llogan Feb 04 '20 at 18:26
0

I couldn't get these answers to work. Processing would stop/pause at frame 75 and keep "running" doing nothing.

This answer worked well, and it worked fast for a longer video:

https://stackoverflow.com/a/38189232/901739

Dev Null
  • 716
  • 1
  • 8
  • 20