5

I'm using ffmpeg to stack two videos vertically. They might be different size so I need to scale them to same size. I have found following commands.

First one works for different sizes (but won't scale to proper size):

ffmpeg -i input1 -i input2 -filter_complex '[0:v]pad=iw:ih*2[int];[int][1:v]overlay=0:H/2[vid]' -map [vid] -c:v libx264 -crf 23 -preset veryfast output

Second one works if videos have same width and same pixel format:

ffmpeg -i input1 -i input2 -filter_complex vstack output

How to get width of first input inside complex filter argument so second input could be scaled to same width? What would be the command to do so? I would prefer vstack filter since it should be faster than combination of pad and overlay.

2 Answers 2

10

You need to use the scale2ref filter.

ffmpeg -i input1 -i input2
 -filter_complex '[1][0]scale2ref[2nd][ref];[ref][2nd]vstack'
 -map [vid] -c:v libx264 -crf 23 -preset veryfast output

Note that this only works well if the aspect ratios of both the videos are the same. If not, and you know the aspect ratio of the 2nd video, use [1][0]scale2ref=iw:iw*(H/W)[2nd][ref] where (H/W) should be replaced with the ratio of the height to width of the 2nd video.


With a build of a recent git version of ffmpeg, a simplified version is possible,

ffmpeg -i input1 -i input2
 -filter_complex '[1][0]scale2ref=oh*mdar:ih[2nd][ref];[ref][2nd]vstack'
 -map [vid] -c:v libx264 -crf 23 -preset veryfast output

This will automatically preserve the 2nd input's aspect ratio.

4
  • 1
    As of this writing, you can reference the aspect ratio of the 2nd video using these new variables: ffmpeg.org/ffmpeg-filters.html#scale2ref , if you have a custom build of ffmpeg from the master branch. That means you don't have to run another command to figure out the aspect ratio explicitly first (as of this writing, it's not available on the release branches yet though)
    – bhh1988
    Oct 2, 2017 at 1:14
  • demo command added.
    – Gyan
    Oct 2, 2017 at 4:47
  • 1
    instead of manually putting in H and W, ffmpeg now supports the main_h and main_w variables in expressions. So a generic version of this would be: [1][0]scale2ref=iw:iw*(main_h/main_w)[2nd][ref]
    – Chris
    Nov 20, 2020 at 0:01
  • Both commands raise "No such filter: '[1][0]scale2ref[2nd][ref]..." (ffmpeg 6.0)
    – Apostolos
    Aug 18, 2023 at 6:45
0
  1. you can get the dimensions by:

ffprobe -v error -show_entries stream=width,height -of default=noprint_wrappers=1 -of json input_video

  1. store the output in a variable, e.g. ffprobe_output. then get the width:

width = ffprobe_output['streams'][0]['width']

for m4v files, you must get them in the second array:

width = ffprobe_output['streams'][1]['width']

  1. scale with that width:

3.a) scale with given width and keep aspect ratio

ffmpeg -i input_movie -vf scale=width:-1 output_movie

3.b) scale with given width, keep aspect ratio, but make height divisible by 2 (required by many pixel formats):

ffmpeg -i input_movie -vf scale=width:-2 output_movie

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .