我需要使用 FFmpeg 转换一堆视频文件。我运行了一个可以很好地转换所有文件的 Bash 文件,但是如果转换的文件不是 16:9 格式,则会出现问题。
当我将屏幕尺寸固定为 -s 720x400 时,如果原始的纵横比是 4:3,FFmpeg 会创建一个 16:9 的输出文件,从而搞砸纵横比。
是否有允许将纵横比设置为主要参数并调整大小的设置(例如,仅通过固定 X 或 Y 尺寸)?
我需要使用 FFmpeg 转换一堆视频文件。我运行了一个可以很好地转换所有文件的 Bash 文件,但是如果转换的文件不是 16:9 格式,则会出现问题。
当我将屏幕尺寸固定为 -s 720x400 时,如果原始的纵横比是 4:3,FFmpeg 会创建一个 16:9 的输出文件,从而搞砸纵横比。
是否有允许将纵横比设置为主要参数并调整大小的设置(例如,仅通过固定 X 或 Y 尺寸)?
-vf "scale=640:-1"
效果很好,直到您遇到错误
[libx264 @ 0x2f08120] height not divisible by 2 (640x853)
所以最通用的方法是使用过滤器表达式:
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:
ffmpeg -y -i import.media -aspect 16:9 scale=640x360,pad=640:480:0:60:black output.media
纵横比 16:9 ,尺寸宽度 640 像素 => 高度 360 像素:
最终输出尺寸为 640x480,填充 60 像素黑色图像(顶部和底部):
"-vf scale=640x360,pad=640:480:0:60:black"
我很久以前就问过这个问题,但实际上我有一个我当时不知道的解决方案——为了保持纵横比,你应该使用视频滤镜比例,这是一个非常强大的功能筛选。
您可以像这样简单地使用它:
-vf "scale=640:-1"
这将固定宽度并提供保持纵横比所需的高度。但是您也可以使用许多其他选项甚至数学函数,请查看此处的文档 - http://ffmpeg.org/ffmpeg.html#scale
尽管这些答案中的大多数都很棒,但我一直在寻找一个可以在保持纵横比的同时调整到目标尺寸(宽度或高度)的命令。我能够使用 ffmpeg 的Expression Evaluation来完成此任务。
这是相关的视频过滤器,目标维度为 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)'
如果宽度大于高度,则返回目标,否则,返回比例宽度。
对于输出高度:
'if(gt(iw,ih),trunc(ow/a/2)*2,512)'
如果宽度大于高度,则返回比例高度,否则返回目标。
使用force_original_aspect_ratio
, 来自ffmpeg trac:
ffmpeg -i input.mp4 -vf scale=720:400:force_original_aspect_ratio=decrease output.mp4
如果您正在尝试拟合边界框,那么force_original_aspect_ratio
按照xmedeko 的回答使用是一个很好的起点。
但是,如果您的输入视频具有奇怪的大小并且您正在编码为要求尺寸可以被 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(<scaling factor>*iw/2)*2
并trunc(<scaling factor>*iw/2)*2
确保尺寸可以被 2 整除,方法是除以 2,使结果为整数,然后再乘以 2。这消除了在编码之前查找输入视频尺寸的需要。
您可以使用 ffmpeg -i 获取原始文件的尺寸,并在您的命令中使用它进行编码。你在哪个平台上使用 ffmpeg?
如果存在“-aspect x:y”且输出文件格式为 ISO 媒体文件格式 (mp4),则 ffmpeg 将 pasp-atom (PixelAspectRatioBox) 添加到视频轨道的 stsd-box 中,以向播放器指示预期的宽高比。播放器应分别缩放视频帧。无需在编码或转码之前缩放视频以适应宽高比,它应该由播放器执行。
由于 ffmpeg 要求宽度/高度可被 2 整除,并且我想您想指定其中一个尺寸,因此可以选择:
ffmpeg -i input.mp4 -vf scale=1280:-2 output.mp4
上面的答案很好,但它们中的大多数都假设特定的视频尺寸并且不在通用的纵横比上运行。
无论具体尺寸如何,您都可以使用以下方法填充视频以适应任何宽高比:
-vf 'pad=x=(ow-iw)/2:y=(oh-ih)/2:aspect=16/9'
16/9
我在我的例子中使用了这个比率。上面是一个捷径,只需要做一些像这样的手动操作:
pad='max(iw,(16/9)*ih)':'max(ih,iw/(16/9))':(ow-iw)/2:(oh-ih)/2
这可能会输出奇数(不是偶数)视频尺寸,因此您可以确保输出是这样的:
pad='trunc(max(iw,(16/9)*ih)/2)*2':'trunc(max(ih,iw/(16/9))/2)*2':(ow-iw)/2:(oh-ih)/2
但你真正需要的是pad=x=(ow-iw)/2:y=(oh-ih)/2:aspect=16/9
对于上述所有示例,如果 INPUT 视频具有奇数尺寸,您将收到错误消息。pad=iw:ih
如果输入是奇数大小,甚至会给出错误。通常你不会有奇数大小的输入,但如果你有,你可以先使用这个过滤器来修复它:pad='mod(iw,2)+iw':'mod(ih,2)+ih'