我需要使用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"
-aspect 16:9 -vf scale=960x720,pad=1280:720:160:0:white
(我也需要白色填充而不是黑色)。谢谢! - Peter K.-vf“scale=1440x1080,pad=1920:1080:240:0:black”
- whereisalextffmpeg -y -i 01.mp4 -vf "scale=640x360,pad=640:480:0:60:black" 02.mp4
- John Trichereau我很久以前问过这个问题,但事实上我现在有了一个解决方案--为了保持宽高比,你应该使用视频滤镜缩放,它是一个非常强大的滤镜。
你可以简单地像这样使用它:
-vf "scale=640:-1"
这将固定宽度并提供所需的高度以保持纵横比。但您还可以使用许多其他选项甚至数学函数,请在此处查看文档-http://ffmpeg.org/ffmpeg.html#scale
-vf "scale=640:-2"
。 - cocoforce_original_aspect_ratio
:ffmpeg -i input.mp4 -vf scale=720:400:force_original_aspect_ratio=decrease output.mp4
ffmpeg
本身无法解决除以2的问题(不幸的是)。我已经通过在Python脚本中计算宽高比,然后传递我想要的 ffmpeg scale=
参数来解决了这个问题。 - xmedeko719x400
,但没有出现任何错误。我可以使用VLC媒体播放器播放它(在右侧看到了额外的像素)。Ubuntu本地视频播放器也能够很好地播放它。之后,ffmpeg可以读取该文件并将其转换为另一个文件。 - Kostanos-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)'
如果宽度大于高度,则返回相应的高度,否则返回目标高度。
如果你想要适应一个边界框,那么按照xmedeko的回答中提到的使用force_original_aspect_ratio
是一个好的起点。
但是,如果你的输入视频尺寸很奇怪,且你正在将其编码为需要宽高为偶数的格式时,这种方法就不适用了,会导致错误。
在这种情况下,可以在scale
函数中使用表达式求值,就像Charlie的回答所示。
假设输出边界框为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,使结果为整数,然后再乘回来,确保尺寸是偶数。这消除了在编码之前找到输入视频尺寸的需求。
由于ffmpeg需要宽度/高度可被2整除, 而我猜想您想指定其中一个维度,因此这将是选项:
ffmpeg -i input.mp4 -vf scale=1280:-2 output.mp4
0
符合此条件,但会导致意外的扭曲。 -2
是一个令人恼火的简洁解决方法,而且它确实有效!+1 - 1owk3y-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
对于以上所有示例,如果输入视频具有奇数尺寸,则会出现错误。即使是pad=iw:ih
,如果输入是奇数大小也会出错。通常情况下,您不会有奇数大小的输入,但如果确实有,您可以先使用此过滤器进行修复:pad='mod(iw,2)+iw':'mod(ih,2)+ih'
你可以使用ffmpeg -i命令获取原始文件的尺寸,并在编码命令中使用它。你在哪个平台上使用ffmpeg?
scale=trunc(oh*a/2)*2:min(480\,iw)
。 - Christian Davénscale=640:trunc(ow/a/2)*2
和scale=640:-2
都是足够的答案,但不一定等价。前者中的截断可能会根据输入源的大小而使值小 2 像素,例如。 - systemexit