crossfade between 2 videos using ffmpeg

28

14

I've been trying to achieve a crossfade transition between 2 video clips using ffmpeg but have failed so far. I'm new to ffmpeg and am mostly relying on tweaking what I can find in the documentation and existing examples online. From what I read so far, using either the blend or overlay filter should help in achieving what I'm after but I can't figure out the command line details to get it to work.

The fade and concat filters are great for fade-out of video 1, fade-in to video 2 and concat the 2 into 1 clip type transitions but I'd appreciate help in getting a command to transition from video 1 to video 2 without any going to black in between. I couldn't find any examples for exactly this problem anywhere, maybe I'm looking for the wrong keywords...?

More speficially, my videos are mp4s (h264 video, no sound, in case that matters), each is 5 seconds long and I'm after a transition from approx. 4.5s of video 1 to 0.5s of video 2.

Similar to what this tutorial does using MLT and frames (see 2:25 for an example fade), though I'm looking for a way to do this just in ffmpeg without calling any other progs. http://www.youtube.com/watch?v=3PRZ9L_KLdI

Any pointers or maybe a command line to get a fade like this would be much appreciated, thanks very much!

Mugba

Posted 2014-07-09T05:22:52.203

Reputation: 323

Answers

23

I suggest to do that way:

  • Create black background with the same duration and resolution as output video should be
  • Add alpha channel to each video
  • Add fade to alpha effect to each video
  • Use overlay on each video with black background

So the command for adding crossfade to 2 video (5 sec) each should be:

ffmpeg -i 1.mp4 -i 2.mp4 -f lavfi -i color=black -filter_complex \
"[0:v]format=pix_fmts=yuva420p,fade=t=out:st=4:d=1:alpha=1,setpts=PTS-STARTPTS[va0];\
[1:v]format=pix_fmts=yuva420p,fade=t=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+4/TB[va1];\
[2:v]scale=960x720,trim=duration=9[over];\
[over][va0]overlay[over1];\
[over1][va1]overlay=format=yuv420[outv]" \
-vcodec libx264 -map [outv] out.mp4

This will fade out first video to alpha at 4th second (st=4) during 1 second (d=1), fade in the second one at 0 second (st=0) during 1 second (d=1) and moves it's display time forward to 4 sec (+4/TB). Then we just cut 9 second of black color, scale it to output video size and overlay the stuff.

Hope it helps.

ptQa

Posted 2014-07-09T05:22:52.203

Reputation: 1 599

Hi @ptQa, thanks very much, the crossfade effect works like a charm. Though what happens in the output video is that it only shows a top left section of the original videos and the rest of the frame is missing. I looked at the resolution, input is 960 x 720 and output is 320 x 240 but it doesn't scale down the whole video, instead cuts out a 320 x 240 section in the top left and shows that in the output video, rest of the input videos is missing. Is there an addition to your command line that prevents this? – Mugba – 2014-07-10T00:42:24.147

Oh, I got it, you should also scale black color to resolution that you want to get. See updated answer. I've added scale to filter graph. – ptQa – 2014-07-10T08:39:43.023

That solved it, thanks. I uploaded a sample video showing the crossfading in case anyone wants to see it in action, http://youtu.be/JqorgXAjjTo

– Mugba – 2014-07-11T00:42:32.793

Same problem; I have a variant of this working on some of my own video -- thanks. Question: How would this be modified to also cross-fade the videos' audio tracks, following the same pattern as the video fade? – Jim Miller – 2014-09-17T05:06:10.537

1BTW, I think there's an error in the answer's sample command -- it should be -i 1.mp4 -i 2.mp4..., right? – Jim Miller – 2014-09-17T05:07:23.210

I had an issue of the video freezing in transition using this command. FFmpeg v2.6. I found that using frames instead of seconds for the frame filters would fix the issue, e.g. fade=out:120:30 for a 30fps video. Is this a bug with FFmpeg? @ptQa – Jon G – 2015-05-20T16:27:32.993

It sounds like you have a video container without PTS/DTS or you do not have container at all. Try to convert video to mpeg2ts and see if it helps. – ptQa – 2015-05-20T20:27:43.470

What's with the squeezed frame when i use 2 full HD videos and set the resolution of the black input to 1920x1080. It's squeezing the original videos and putting them between black bars on each side but the overall dimensions of the video are full HD. – Emery King – 2016-03-22T23:00:49.817

How would you be able to do this for a variable number of videos like 5? How would the filter_complex be structured? – jrkt – 2016-09-26T20:05:56.007

The scale filter sets the SAR/DAR, so you can get a squeezed/stretched video (same problem as @MarshallHouse ?). Using color=size=960x720 as source (and removing the filter) solves this. – Remko – 2017-08-02T07:55:23.257

What's with the extraneous scale (resize) filter? That confuses things. A bare bones example would be great. – r_alex_hall – 2018-01-01T00:43:40.930

7

This is how I did :

  • ffmpeg version N-77197-gdf2ce13
  • 2 videos of 4 seconds each.
  • Need to join it with fade between them.
  • videos are 25 fps.

1) Add fade out (light to dark) at the end of the 1st and fade in (dark to light) at the beggining of the 2nd:

ffmpeg -i 1.mp4 -y -vf fade=out:76:24 1f.mp4

ffmpeg -i 2.mp4 -y -vf fade=in:0:25 2f.mp4

76:24 mean the fade out will start frame 76 and will finish 24 frames later = 1s fade out.

0:25 mean the fade in will start frame 0 and will finish 25 frames later.

2) Merge the 2 videos

Convert all to TS

ffmpeg -i 1f.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts 1f.ts

ffmpeg -i 2f.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts 2f.ts

Merge

ffmpeg -i "concat:1f.ts|2f.ts" -bsf:a aac_adtstoasc -c copy output.mp4

Thanks to:

http://www.bogotobogo.com/FFMpeg/ffmpeg_fade_in_fade_out_transitions_effects_filters.php

Erwan

Posted 2014-07-09T05:22:52.203

Reputation: 95

6This is not a crossfade. – Gyan – 2016-01-27T15:33:10.657

4What @Mulvya said. A crossfade fades one clip out at the same time as another is fading in. The first clip has its transparency steadily increased over the duration of the crossfade; the second has its transparency steadily decreased. – intuited – 2016-05-23T06:44:38.523

7

ffmpeg-concat is the easiest way to accomplish what you want and allows you to use a bunch of sexy OpenGL transitions, with the default being crossfade.

ffmpeg-gl-transition is a custom ffmpeg filter which allows you to use GLSL to smoothly transition between two video streams. This filter is significantly easier to use and customize than the alternatives listed here.

This filter supports a large list of transition types, with the default being crossfade.

./ffmpeg -i 0.mp4 -i 1.mp4 -filter_complex "gltransition=duration=4:offset=1.5" out.mp4

fisch2

Posted 2014-07-09T05:22:52.203

Reputation: 171

5Have you considered submitting a patch to FFmpeg? – llogan – 2017-12-05T22:44:40.243

1I definitely will, I just need to fix some small issues and test more first. Good call! – fisch2 – 2017-12-06T04:41:26.267

1is this in the official FFmpeg? I can't seem to locate it – kraftydevil – 2019-03-01T05:58:56.370