Search code examples
ffmpegscale

ffmpeg - when scaling, how to keep shapes of people's heads


Ok, I'm quite familiar with FFMPEG utility in general, and have used it for years to cut short snippets from videos, etc. But it's only in the last month that and I decided to learn to use it to transcode with video-filters etc. (Before that, I was using other tools such as 'Handbrake' and 'FreeMake' and VLC, etc.)

For my ffmpeg transcodes, my target output resolution will always be constant, from one transcode run to the next. But the resolution and display aspect-ratio of the input file, from one transcode run to the next, will vary...could be almost any values. The input files will never already have black-bars when displayed.

So, the relevant portion [ i.e. the video-filter(s) part) of my cmd line ] presently is as follows:

ffmpeg ... -vf "scale=720:406,setsar=1,pad=720:506:0:40:Black" ...

Also note: I do NOT use the "-aspect" option in the cmd-line. (Maybe I'll need to (???) to solve my issue, but I'm unsure about how that interacts with scaling.)

( EDIT: Oh, I happen to have chosen that resolution value of 720x406, for the image-area (i.e. inside the top/bottom black bars) because it has an aspect ratio of 16:9 (Of course, 16:9 ratio is common these days. )

My cmd always executes cleanly and produces an output file (a WebM, tho I doubt that container types and/or vcodec choices matter at all to scaling algorithm issues).

So the issue/problem that I'm trying to solve is how to prevent any stretching in either direction. In other words, a round soccer ball in the input file must yield a round ball in the output file ! (NOT oval-shaped in either axis).

( Edit #2: Oh, I forgot to mention that I'm not have the same amount of stretching from one ffmpeg output file to the next. Sometimes there is no stretch in my output file, and with some other input file, the people are too tall in the output, and some other output file will have people are too wide. I'm assuming there is some single cmd that will always work for each randomly sized input file, WITHOUT having to resort to examining meta-data of each input and then having to adjust portions of the needed ffmpeg cmd.
I assume this because I have used a tool called "FreeMake" that needs no such adjustment. When you do a 'scale' with that program, it asks you to choose one of four adjustment-algorithms labeled "original" "stretched", "zoom..." and "auto". If I recall correctly, it was the "auto" choice that prevented any stretching.)

The goal of that last filter (i.e. the "pad=720:506:0:40:Black" phrase) is to add a black bar of 40 pixels to the top and 60 pixels to the bottom. (That filter IS producing the black-bands, as desired. I mention it, because I'm unsure whether it could be having any effect on the altered shape of the 'round soccer ball'). If the "pad" filter IS part of the issue, then maybe I'll need to make multiple ffmpeg cmds to achieve my overall goal (!?!?). [I'd LIKE to be able to do everything in just one ffmpeg cmd, as shown.]

OK?

So are there any image-processing and ffmpeg gurus out there that know how to fix my problem?

TIA...

Dave


Solution

  • Two sources of distortion can be present here. First, the original video raster may not be 16:9, but since you're scaling to a fixed output size, that may produce distortion. Second, the input video may not have square pixels, so it is stored distorted in the source and only stretched/squashed by the video player during playback. This is a legacy of analogue NTSC/PAL signals.

    To correct for this, the scaler arguments should factor in the source aspect ratio. So, assuming that the final result should feature 40 pixels of black on top and 60 below, use

    -vf "scale=720:720/dar,setsar=1,pad=720:ih+100:0:40:black"