[FFmpeg-user] Automatic Aspect Ratio Conversion

Dan Flett dflett at bigpond.net.au
Tue Jul 26 06:51:39 CEST 2011


Hi all,
 
For a while I'd been wondering if ffmpeg could correctly aspect ratio
convert (ARC) a video to a specified width/height/Display Aspect Ratio(DAR),
without needing to know the width/height/Display Aspect Ratio of the source
file.

I wanted to have the choice of padding (pillar or letterboxing) or cropping
(centre cut).  After reading the libavfilter documentation closely I found
the answer under my nose.

http://ffmpeg.org/libavfilter.html

There is an example under the "pad" section:

# pad the input to get a final w/h ratio of 16:9
pad="ih*16/9:ih:(ow-iw)/2:(oh-ih)/2"

This example assumes that the input is thinner/taller than 16:9 - if the
input video is wider/shorter than 16:9 it will fail with error - because the
input width will be wider than ih*16/9 and pad doesn't allow an output width
thinner than the input video.

Another example is:

# pad the input to get a squared output with size equal to the maximum
# value between the input width and height, and put the input video at
# the center of the padded area
pad="max(iw\,ih):ow:(ow-iw)/2:(oh-ih)/2"

This gives an output that is always padded square, regardless of the input
video dimensions.

To get the best of both examples (output 16:9 but works with any input
dimensions) I did this:
"pad=max(iw\,ih*(16/9)):ow/(16/9):(ow-iw)/2:(oh-ih)/2" -aspect 16:9

This example selects the maximum of either the input width as-is, or the
input height * 16/9.  The output height is the output width * 16/9.

This gives an output that is always 16:9, padding either the sides or
top/bottom, as appropriate.  The video is always centred.

However I found that if the input video is anamorphic (i.e. non-square
pixel), the output is also anamorphic, and the DAR / SAR information is
lost.

To fix this, I did this:
"scale=iw*sar:ih , pad=max(iw\,ih*(16/9)):ow/(16/9):(ow-iw)/2:(oh-ih)/2"
-aspect 16:9

This scales the input width to make the pixels square.  This means that
subsequent padding/cropping/scaling operations are done on square-pixel
video frames.

To crop the input video to 16:9 instead of padding, I do this:
"scale=iw*sar:ih , crop=min(iw\,ih*(16/9)):ow/(16/9)" -aspect 16:9
This chops off the sides or top/bottom, as appropriate to get a 16/9 output.

Dan



More information about the ffmpeg-user mailing list