Video Transition with ffmpeg . Crossfade

ffmpeg -y -i video1.mp4 -i video2.mp4    -filter_complex "   \
[0:v] scale=w=min(iw*720/ih\,1280):h=min(720\,ih*1280/iw),   \
pad=w=1280:h=720:x=(1280-iw)/2:y=(720-ih)/2,   \
fade=out:st=3:d=2:alpha=1, setpts=PTS-STARTPTS  [video1];    \
[1:v] scale=w=min(iw*720/ih\,1280):h=min(720\,ih*1280/iw),   \
pad=w=1280:h=720:x=(1280-iw)/2:y=(720-ih)/2,   \
fade=in:st=0:d=2:alpha=1, setpts='PTS+3/TB' [video2];    \
[video1][video2]overlay[v]  " -map "[v]" -c:v h264 -crf 18 \
-preset veryfast crossfade.mp4

All sources in php available on my github

Image animation. Rotate

Ok, and last part – rotate image:

  • rotate cw
    ffmpeg -y -loop 1 -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 -filter_complex \
    " [1:v] scale=w=1920:h=1080 [fg];  \
    [0:v] scale=w='if( gt(iw, ih), -2, 2202.9071700823 )':h='if( gt(iw,ih), 2202.9071700823, -2  )', \
    rotate=a=0.39269908169872*t/5:c=black:ow=1920:oh=1080, setsar=1 [bg];  \
    [bg][fg]overlay=shortest=1[v] " \
    -map "[v]" -c:v h264 -crf 18 -preset veryfast rotate_cw.mp4
    

  • rotate ccw
    ffmpeg -y -loop 1 -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 -filter_complex \
    " [1:v] scale=w=1920:h=1080 [fg];  \
    [0:v] scale=w='if( gt(iw, ih), -2, 2202.9071700823 )':h='if( gt(iw,ih), 2202.9071700823, -2  )', \
    rotate=a=-0.39269908169872*t/5:c=black:ow=1920:oh=1080, setsar=1 [bg];  \
    [bg][fg]overlay=shortest=1[v] " \
    -map "[v]" -c:v h264 -crf 18 -preset veryfast rotate_ccw.mp4
    

All sources in php available on my github

Image animation. Zoom

Today we will check zoom in and out effects:

  • zoom in
    ffmpeg -y \
    -loop 1 -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 \
    -filter_complex " [1:v] scale=w=1920:h=1080 [fg];  \
    scale=w=-2:h=3*1080 , crop=w=3*1920:h=3*1080,  \
    zoompan=z=min(max(zoom\,pzoom)+0.0008\,1.1):d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1920x1080,  \
    setsar=1 [bg];  \
    [bg][fg]overlay=shortest=1[v] " \
    -map "[v]" -c:v h264 -crf 18 -preset veryfast zoom_in.mp4
    

  • zoom out
    ffmpeg -y -loop 1 \
    -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 \
    -filter_complex " [1:v] scale=w=1920:h=1080 [fg];  \
    [0:v] scale=w=-2:h=3*1080 , crop=w=3*1920:h=3*1080,  \
    zoompan=z=if(lte(zoom\,1.0)\,1/0.9\,max(1.0\,zoom+-0.0008)):d=25*5:x='iw/2-(iw/zoom/2)':\
    y='ih/2-(ih/zoom/2)':s=1920x1080,  setsar=1 [bg] ; \
    [bg][fg]overlay=shortest=1[v] " \
    -map "[v]" -c:v h264 -crf 18 -preset veryfast zoom_out.mp4
    

All sources in php available on my github

Image animation. Pan

There are several simple pan effects for image animation:

  • pan up
    ffmpeg -y -loop 1 -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 \
    -filter_complex " [1:v] scale=w=1920:h=1080 [fg];  \
    [0:v] scale=w=-2:h=3*1080 , crop=w=3*1920/1.2:h=3*1080/1.2:y=t*(in_h-out_h)/5,  \
    scale=w=1920:h=1080,  setsar=1 [bg] ; \
    [bg][fg]overlay=shortest=1[v] " \
    -map "[v]" -c:v h264 -crf 18 -preset veryfast pan_up.mp4
    

  • pan down
    ffmpeg -y \
    -loop 1 -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 \
    -filter_complex " \
    [1:v] scale=w=1920:h=1080 [fg];  \
    [0:v] scale=w=-2:h=3*1080 , crop=w=3*1920/1.2:h=3*1080/1.2:y=(in_h-out_h)-t*(in_h-out_h)/5,  \
    scale=w=1920:h=1080,  setsar=1 [bg] ;\
    [bg][fg]overlay=shortest=1[v] \
    " -map "[v]" -c:v h264 -crf 18 -preset veryfast pan_down.mp4
    

  • pan left
    ffmpeg -y -loop 1 -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 \
    -filter_complex " [1:v] scale=w=1920:h=1080 [fg];  \
    [0:v] scale=w=-2:h=3*1080 , crop=w=3*1920/1.05:h=3*1080/1.05:x=t*(in_w-out_w)/5,  \
    scale=w=1920:h=1080,  setsar=1 [bg] ; [bg][fg]overlay=shortest=1[v] " \
    -map "[v]" -c:v h264 -crf 18 -preset veryfast pan_left.mp4
    

  • pan right
    ffmpeg -y -loop 1 -i bgimage.png -ss 0 -t 5 \
    -r 1 -loop 1 -i front.png -ss 0 -t 5 \
    -filter_complex " [1:v] scale=w=1920:h=1080 [fg];  \
    [0:v] scale=w=-2:h=3*1080 , \
    crop=w=3*1920/1.05:h=3*1080/1.05:x=(in_w-out_w)-t*(in_w-out_w)/5,  \
    scale=w=1920:h=1080,  setsar=1 [bg] ; [bg][fg]overlay=shortest=1[v] " \
    -map "[v]" -c:v h264 -crf 18 -preset veryfast pan_right.mp4
    

All sources in php available on my github

Concatenation videos with different resolution. Part 3. Blur

One more way – use original size of videos ( scale only if video size large, than our canvas ) but add blurred background.

ffmpeg -y -loglevel warning
-i 5sec_640x480.mp4
-i 5sec_1920x1080.mp4
-i 5sec_720x1280.mp4
-filter_complex " 
[0:v] split=2 [video0-1][video0-2];
[1:v] split=2 [video1-1][video1-2];
[2:v] split=2 [video2-1][video2-2];
[video0-1] scale=w=1280:h=720,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1, setsar=1  [bg0];
[video1-1] scale=w=1280:h=720,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1, setsar=1  [bg1];
[video2-1] scale=w=1280:h=720,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1, setsar=1  [bg2];
[video0-2] scale=w=min( iw\, min(iw*720/ih\,1280)):h=min( ih\, min(720\,ih*1280/iw)), setsar=1 [video0-2-scaled];
[video1-2] scale=w=min( iw\, min(iw*720/ih\,1280)):h=min( ih\, min(720\,ih*1280/iw)), setsar=1 [video1-2-scaled];
[video2-2] scale=w=min( iw\, min(iw*720/ih\,1280)):h=min( ih\, min(720\,ih*1280/iw)), setsar=1 [video2-2-scaled];
[bg0][video0-2-scaled] overlay=x=(W-w)/2:y=(H-h)/2 [video0];
[bg1][video1-2-scaled] overlay=x=(W-w)/2:y=(H-h)/2 [video1];
[bg2][video2-2-scaled] overlay=x=(W-w)/2:y=(H-h)/2 [video2];
[video0][video1][video2] concat=n=3:v=1[v]" 
-map "[v]" -an -c:v h264 -crf 18 -preset veryfast -f mp4 output.mp4

or version with concatenation audio streams too


ffmpeg -y -loglevel warning
-i 5sec_640x480.mp4
-i 5sec_1920x1080.mp4
-i 5sec_720x1280.mp4
-filter_complex " 
[0:v] split=2 [video0-1][video0-2];
[1:v] split=2 [video1-1][video1-2];
[2:v] split=2 [video2-1][video2-2];
[video0-1] scale=w=1280:h=720,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1, setsar=1  [bg0];
[video1-1] scale=w=1280:h=720,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1, setsar=1  [bg1];
[video2-1] scale=w=1280:h=720,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1, setsar=1  [bg2];
[video0-2] scale=w=min( iw\, min(iw*720/ih\,1280)):h=min( ih\, min(720\,ih*1280/iw)), setsar=1 [video0-2-scaled];
[video1-2] scale=w=min( iw\, min(iw*720/ih\,1280)):h=min( ih\, min(720\,ih*1280/iw)), setsar=1 [video1-2-scaled];
[video2-2] scale=w=min( iw\, min(iw*720/ih\,1280)):h=min( ih\, min(720\,ih*1280/iw)), setsar=1 [video2-2-scaled];
[bg0][video0-2-scaled] overlay=x=(W-w)/2:y=(H-h)/2 [video0];
[bg1][video1-2-scaled] overlay=x=(W-w)/2:y=(H-h)/2 [video1];
[bg2][video2-2-scaled] overlay=x=(W-w)/2:y=(H-h)/2 [video2];
[0:a] anull [audio0];
[1:a] anull [audio1];
[2:a] anull [audio2];
[video0][audio0][video1][audio1][video2][audio2] concat=n=3:v=1:a=1 [v][a]
" -map "[v]" -map "[a]" -c:a aac -c:v h264 -crf 18 -preset veryfast -f mp4 output.mp4

Result:

Concatenation videos with different resolution. Part 2. Crop

Ok, another way, resize all videosresize all videos by smaller side ( by width or height ) and crop to output size. We will use ffmpeg filter ‘crop
The same 3 videos with resolution 640×480, 1920×1080 and vertical video 720×1280.

ffmpeg -y -loglevel warning
-i 5sec_640x480.mp4
-i 5sec_1920x1080.mp4
-i 5sec_720x1280.mp4
-filter_complex " 
[0:v] scale=w=max(iw*480/ih\,640):h=max(480\,ih*640/iw), setsar=1, crop=w=640:h=480 [video0]; 
[1:v] scale=w=max(iw*480/ih\,640):h=max(480\,ih*640/iw), setsar=1, crop=w=640:h=480  [video1];
[2:v] scale=w=max(iw*480/ih\,640):h=max(480\,ih*640/iw), setsar=1, crop=w=640:h=480  [video2];
[video0][video1][video2] concat=n=3:v=1 [v]" 
-map "[v]" -an -c:v h264 -crf 18 -preset veryfast -f mp4 output.mp4

The same but with concatenation audio streams too.

ffmpeg -y -loglevel warning
-i 5sec_640x480.mp4
-i 5sec_1920x1080.mp4
-i 5sec_720x1280.mp4
-filter_complex " 
[0:v] scale=w=max(iw*480/ih\,640):h=max(480\,ih*640/iw), setsar=1, crop=w=640:h=480 [video0]; 
[1:v] scale=w=max(iw*480/ih\,640):h=max(480\,ih*640/iw), setsar=1, crop=w=640:h=480  [video1];
[2:v] scale=w=max(iw*480/ih\,640):h=max(480\,ih*640/iw), setsar=1, crop=w=640:h=480  [video2];
[0:a] anull [audio0];
[1:a] anull [audio1];
[2:a] anull [audio2];
[video0][audio0][video1][audio1][video2][audio2] concat=n=3:v=1:a=1 [v][a]
" -map "[v]" -map "[a]" -c:a aac -c:v h264 -crf 18 -preset veryfast -f mp4 output.mp4

Result:

Concatenation videos with different resolution. Part 1. Pad

We can concatenate video with different codec, resolution or framerate in different way. Because, video have different resolution, we can:

  • resize all videos by bigest side ( by width or height ) and add pad to videos on the smaller side
  • resize all videos by smaller side ( by width or height ) and crop
  • use original size, but add background to videos

Today we will use ffmpeg filter ‘pad
For example, we have 3 videos with resolution 640×480, 1920×1080 and vertical video 720×1280.

ffmpeg -y -loglevel warning
-i 5sec_640x480.mp4
-i 5sec_1920x1080.mp4
-i 5sec_720x1280.mp4
-filter_complex " 
[0:v] scale=w=min(iw*480/ih\,640):h=min(480\,ih*640/iw), pad=w=640:h=480:x=(640-iw)/2:y=(480-ih)/2  [video0]; 
[1:v] scale=w=min(iw*480/ih\,640):h=min(480\,ih*640/iw), pad=w=640:h=480:x=(640-iw)/2:y=(480-ih)/2  [video1];
[2:v] scale=w=min(iw*480/ih\,640):h=min(480\,ih*640/iw), pad=w=640:h=480:x=(640-iw)/2:y=(480-ih)/2  [video2];
[video0][video1][video2] concat=n=3:v=1 [v]
" -map "[v]" -an -c:v h264 -crf 18 -preset veryfast -f mp4 output.mp4

The same but with concatenation audio streams too.

ffmpeg -y -loglevel warning
-i 5sec_640x480.mp4
-i 5sec_1920x1080.mp4
-i 5sec_720x1280.mp4
-filter_complex " 
[0:v] scale=w=min(iw*480/ih\,640):h=min(480\,ih*640/iw), pad=w=640:h=480:x=(640-iw)/2:y=(480-ih)/2  [video0]; 
[1:v] scale=w=min(iw*480/ih\,640):h=min(480\,ih*640/iw), pad=w=640:h=480:x=(640-iw)/2:y=(480-ih)/2  [video1];
[2:v] scale=w=min(iw*480/ih\,640):h=min(480\,ih*640/iw), pad=w=640:h=480:x=(640-iw)/2:y=(480-ih)/2  [video2];
[0:a] anull [audio0];
[1:a] anull [audio1];
[2:a] anull [audio2];
[video0][audio0][video1][audio1][video2][audio2] concat=n=3:v=1:a=1 [v][a]
" -map "[v]" -map "[a]" -c:a aac -c:v h264 -crf 18 -preset veryfast -f mp4 output.mp4

Notes:
All videos in this sample will be scaled to 640×480, but you can set any other resolution for output video.
Result: