0

You can specify multiple inputs to FFMPEG and mix them into a single output. I understand the basics of this, for example:

ffmpeg -i vid1.mp4 -i vid2.mp4 [commands] output.mp4

What I can't figure out is how I can specify different commands for each input. For example, I have the following I'm trying to do:

 ffmpeg -i vid1.m2t -i vid2.mp4 -map 0:a -filter_complex "[0:v:0][1:v:0]vstack=inputs=2" -crf 24 -c:a aac -b:a 128k -ac 1 -movflags +faststart output.mp4

vid1.m2t is a 1440 anamorphic hdv mpeg stream, and vid2.mp4 is a regular 1920 h.264. Using -filter_complex "[0:v:0][1:v:0]vstack=inputs=2" I'm trying to stack vid1 on top of vid2, but I get the error that says it can't proceed because the two videos are not the same width. Well, yes, except in display the m2t is actually 1920 wide, not 1440.

When I'm converting just the hdv by itself, I use -filter_complex "scale=1920:1080,setsar=1" to ensure square pixels. I know that works well, but how can I incorporate that into this vstack command? If I put it in with the other I get errors. I've tried a variety of different ways, including before the input (thinking that would make ffmpeg apply it only to the input before sending it to the other commands for output), but they all make errors.

Additionally, I wonder if the -crf 24 command can be specified for each input. When converting individually the m2t needs to be at 24 or less, or it looks bad, while the mp4 can be as high as 30. I might be misunderstanding what vstack does, but I would think that if I can tell ffmpeg to give different attention to quality for each input would lessen file size.


I have the same issue with hstack. FFMPEG will render the output, but the m2t file comes out 1440 wide, therefore skewed. So the total video width is 3360 wide, instead of 3840.


Maybe more specific to this exact problem, how can I use vstack or hstack when the inputs have different dimensions?

1 Answer 1

1

Suppose a video stream is 1440x1080 with sample/pixel aspect ratio of 1.333, leading to a display of 1920x1080. Realize that the actual resolution of the stream, and what's stored in the file, is 1440x1080. The aspect ratio flag tells the consuming app (player/editor..) that the intended display proportion is different than the raw ratio of the width to height and that it should use the aspect ratio to rescale the video to produce an accurate display. FFmpeg will not automatically make a video square-pixel since the user may not want that.

The stack filters require that all streams have the same size at the interface that they are joined at - for hstack, that's height, and for vstack, that's width. Only the raw size matters, the aspect ratio is just an informational flag.

So, you'll have to rescale the first input before stacking.

Use

ffmpeg -i vid1.m2t -i vid2.mp4 -filter_complex "[0:v:0]scale=iw*sar:ih,setsar=1[vid1];[vid1][1:v:0]vstack=inputs=2" -map 0:a -crf 24 -ac 1 -c:a aac -b:a 128k -movflags +faststart output.mp4

As far as the encoder is concerned, it is just presented with one stream of 1920x2160 - the historical provenance and composition is lost. Now, if you want to apply different levels of compression to parts of the frame, that's called Region Of Interest encoding. Some initial patches were applied last month to allow this for x264 and x265, but it is not operational yet. I'll update this answer when it becomes so, but for now, you can only assign a single CRF value for the whole frame.

2
  • Thanks, Gyan. Works as expected. I also had the need to adjust the brightness and saturation on the m2t, but not the mp4, so I fiddled with it and came up with -filter_complex "[0:v:0]scale=iw*sar:ih,setsar=1,eq=brightness=0.2:saturation=1.5[vid1];[vid1][1:v:0]vstack=inputs=2". I'm very happy it works, but I'm failing to understand the syntax in this command. Can you explain a bit how the , ; and [vid1] are working here?
    – user3643
    Feb 24, 2019 at 17:23
  • Answering my own question here: Separate filters with a , . A string of , separated filters is called a filter chain. Separate filter chains with a ;. A string of ; separated filter chains is called the filter graph. Reference inputs with [x] at the beginning of the chain. A [y] at the end of the chain can be sent down the filter graph to another chain. [0:v:0] calls the first input (specifically the first video stream only). Filters are applied in the chain, then that output is named [vid1]. [vid1] is then immediately called as if it's an input in the next filter chain.
    – user3643
    May 11, 2019 at 1:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.