使用FFmpeg保持宽高比

Maintaining aspect ratio with FFmpeg

我需要使用FFmpeg转换一堆视频文件。 我运行了一个Bash文件,可以很好地转换所有文件,但是如果转换的文件不是16:9格式,则会出现问题。

当我将屏幕尺寸固定为-s 720x400时,如果原始屏幕的宽高比为4:3,则FFmpeg会创建一个16:9的输出文件,从而搞砸了宽高比。

是否有设置可以将长宽比设置为主要参数,并且可以调整尺寸(例如,仅通过固定X或Y尺寸)?


1
-vf"scale=640:-1"

很好,直到遇到错误

1
[libx264 @ 0x2f08120] height not divisible by 2 (640x853)

因此,最通用的方法是使用过滤器表达式:

1
scale=640:trunc(ow/a/2)*2

它使用输出宽度(ow),将其除以长宽比(a),除以2,将小数点后的数字截断,再乘以2。它确保将得到的高度除以2。

归功于ffmpeg trac

更新

正如评论所指出的那样,更简单的方法是使用-vf"scale=640:-2"
感谢@BradWerth提供的优雅解决方案


例如:

1920x1080纵横比16:9 => 640x480纵横比4:3:

1
ffmpeg -y -i import.media -aspect 16:9 scale=640x360,pad=640:480:0:60:black output.media

宽高比16:9,大小宽度640像素=>高度360像素:
最终输出尺寸为640x480,并填充60像素的黑色图像(顶部和底部):

1
"-vf scale=640x360,pad=640:480:0:60:black"


我很久以前就问过这个问题,但实际上我有一个当时尚不为人所知的解决方案-为了保持宽高比,您应该使用视频滤镜比例,这是一个非常强大的功能过滤。

您可以像这样简单地使用它:

1
-vf"scale=640:-1"

这将固定宽度并提供保持纵横比所需的高度。但是您还可以使用许多其他选项甚至数学函数,请在此处查看文档-http://ffmpeg.org/ffmpeg.html#scale


使用ffmpeg追踪中的force_original_aspect_ratio

1
ffmpeg -i input.mp4 -vf scale=720:400:force_original_aspect_ratio=decrease output.mp4


尽管这些答案大多数都不错,但我一直在寻找一个可以在保持纵横比的同时将其调整为目标尺寸(宽度或高度)的命令。我能够使用ffmpeg的表达评估来完成此任务。

这是相关的视频过滤器,目标尺寸为512:

-vf"thumbnail,scale='if(gt(iw,ih),512,trunc(oh*a/2)*2)':'if(gt(iw,ih),trunc(ow/a/2)*2,512)'"

对于输出宽度:

'if(gt(iw,ih),512,trunc(oh*a/2)*2)'

如果width大于height,则返回目标,否则返回比例宽度。

对于输出高度:

'if(gt(iw,ih),trunc(ow/a/2)*2,512)'

如果宽度大于高度,则返回比例高度,否则返回目标。


如果您要拟合边界框,那么根据xmedeko的答案使用force_original_aspect_ratio是一个很好的起点。

但是,如果输入视频的大小很奇怪,并且您编码的格式要求尺寸必须被2整除,则此方法将不起作用,从而导致错误。

在这种情况下,您可以在scale函数中使用表达式求值,就像在查理的答案中使用的那样。

假设输出边框为720x400:

-vf"scale='trunc(min(1,min(720/iw,400/ih))*iw/2)*2':'trunc(min(1,min(720/iw,400/ih))*ih/2)*2'"

分解:

  • min(1,min(720/iw,400/ih)查找缩放因子以适合边界框(从此处开始),将其限制为最大1以确保仅缩小比例,以及
  • trunc(*iw/2)*2trunc(*iw/2)*2确保通过除以2将尺寸除??以2,使结果为整数,然后再乘以2。

这消除了在编码之前寻找输入视频尺寸的需求。


如果存在'-aspect x:y'并且输出文件格式为ISO媒体文件格式(mp4),则ffmpeg将pasp-atom(PixelAspectRatioBox)添加到视频轨道的stsd-box中,以向播放器指示期望的
长宽比。播放器应分别缩放视频帧。
不需要在编码或转码之前缩放视频以使其适合宽高比,它应该由播放器执行。


您可以使用ffmpeg -i获取原始文件的尺寸,并在命令中使用该尺寸进行编码。您在什么平台上使用ffmpeg?