FFMPEG(libx264)“高度不能被2整除”


188

我正在尝试使用libx264编解码器使用FFMPEG从一组帧中编码.mp4视频。

这是我正在运行的命令:

/usr/local/bin/ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4

有时会出现以下错误:

[libx264 @ 0xa3b85a0] height not divisible by 2 (520x369)

经过一番搜索后,问题似乎与缩放算法有关,可以通过添加-vf参数来解决。

但是,就我而言,我不想进行任何缩放。理想情况下,我希望尺寸与框架完全相同。有什么建议吗?h264是否执行某种长宽比?


@AleksandrDubinsky但是LordNeckbeard的答案并没有保留原始的宽度和高度。在这里,我们需要手动指定宽度或高度。如果使用-vf scale = -2:ih或-vf scale = iw:-2,则不会如果工作高度和宽度都uneven..Please解释这个问题的答案是如何更优化的..谢谢?
varmashrivastava

1
@varmashrivastava好吧,SO的工作方式是最初可能存在一个问题,然后Google派遣了一群有不同问题的人,他们随后劫持了该页面。就是这样,尽量不要与之抗争。原始问题的正确答案是-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2",这甚至不是答案之一。回答其他人问题的正确答案是LordNeckbeard。
Aleksandr Dubinsky '18

@varmashrivastava我已经解决了第一个答案。希望它不会被mod破坏。
Aleksandr Dubinsky '18

@AleksandrDubinsky谢谢..用户可以使用"scale="而不是"pad="如果他/她不想使用固定的填充像素?
varmashrivastava '18

Answers:


269

答案在原来的问题,其也不会要缩放的视频:

-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

命令:

ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

基本上,.h264需要偶数尺寸,因此此过滤器将:

  1. 将原始高度和宽度除以2
  2. 将其舍入到最接近的像素
  3. 再次乘以2,从而使其成为偶数
  4. 将黑色填充像素添加到该数字

您可以通过添加filter参数来更改填充的颜色:color=white。请参阅pad的文档


3
这不是错误。不必执行缩放也没关系,因为输出将继承输入的帧大小。
llogan 2013年

5
作为记录,我只是在做一些从图像创建视频的事情,它使用yuvj444p作为像素格式。它不在乎视频大小。然后我需要将其转换为yuv420p,然后它才关心视频的大小。我在维基百科上查找了yuv420p,我认为它是一种多像素颜色格式,需要将图像设置为特定大小。不过,不确定为什么压缩很重要。
lahwran 2015年

7
您最好使用pad而不是scale来添加黑色的行/列。将图像放大一个像素会使其模糊。
Glenn Maynard

5
@NickeManarin,此过滤器应在垂直尺寸上添加1像素的白色填充,视频位于左上方: -vf pad="width=iw:height=ih+1:x=0:y=0:color=white"。ffmpeg垫文档在这里: ffmpeg.org/ffmpeg-filters.html#pad-1
Mark Berry

4
这是一个仅向奇数尺寸添加填充像素的解决方案:-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"
danneu

250

只需使用 -2

比例过滤器文档中

如果其中一个值是-nwith n > 1,则比例过滤器还将使用一个值,该值保持从另一个指定尺寸计算出的输入图像的长宽比。但是,此后,请确保所计算的尺寸可以被整除,n并在必要时调整该值。

例子

将width设置为1280,将自动计算高度以保留长宽比,并且该高度可以被2整除:

-vf scale=1280:-2

与上面相同,但声明了高度;剩下的宽度由过滤器处理:

-vf scale=-2:720

“被2整除”

根据x264的要求,YUV 4:2:0色度子采样输出需要“宽度和高度的2整除”。4:2:2需要“宽度除以2”,而4:4:4没有这些限制。但是,大多数非基于FFmpeg的播放器只能正确解码4:2:0,因此这就是为什么在输出H.264视频时经常看到ffmpeg带有该-pix_fmt yuv420p选项的命令的原因。

警告

不幸的是您不能同时使用-2宽度高度,但是如果您已经指定了一个尺寸,则使用-2是一个简单的解决方案。


14
我认为应将tihis标记为正确答案,因为不涉及“技巧”。韦思以给予好评超过一次
LucaM

1
为什么不起作用-vf scale=-2:-2?就我而言,我想尽可能地保留原始文件的大小。对我有用的是-vf scale=-2:ih。但是,如果两个硬件都不均衡,则无法正常工作。
Pascal 2015年

2
@tuner的结果值-2取决于另一个维度的声明值。
llogan 2015年

3
在我的情况下,这给了我以下错误:Size values less than -1 are not acceptable.但是@Zbyszek的回答非常有效。
朱利安

1
@朱利安不是ffmpeg。您可以下载静态版本
llogan'Oct

64

如果要设置一些输出宽度并以与原始比例相同的比例输出

scale=720:-1 

而不是陷入这个问题,那么你可以使用

scale="720:trunc(ow/a/2)*2"

(仅适用于搜索如何缩放的人)


16
对于固定高度,它是scale="trunc(oh*a/2)*2:720"
Tom

20

scale此处解决方案的问题在于,它们扭曲了源图像/视频,而这几乎永远都不是您想要的。

相反,我发现最好的解决方案是在奇数尺寸上添加一个1像素的焊盘。(默认情况下,填充为黑色,很难注意到。)

其他pad解决方案的问题在于它们无法在任意尺寸上泛化,因为它们总是填充。

此解决方案仅在高度和/或宽度为奇数时添加一个1像素的填充块:

-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"

这是理想的,因为即使不需要填充,它也总是做正确的事情。


缩放比例解决方案最多将像素数更改为1。这几乎不会扭曲图片。如果您担心过滤速度,请使用scale=iw+mod(iw,2):ih+mod(ih,2):flags=neighbor。如果需要,这只能将每个尺寸增加1,并且将复制最后一行/列。
吉安

@Gyan距离解决这个问题已经很久了(我的回答是从我很久以前的评论中提取的),但是我记得在某些情况下按单个像素缩放确实引入了明显的视觉伪像,这就是为什么要打扰我的原因首先。我不记得确切,也许从单个像素变化中出现不成比例的模糊?也许仅在某些vid /图像格式上?我只能说我用此修复程序处理了数千个视频,这是有利的转换。
danneu

19

可能是由于以下事实:在应用压缩之前,H264视频通常从RGB转换为4:2:0的YUV空间(尽管格式转换本身是一种有损压缩算法,可节省50%的空间)。

YUV-420从RGB(红绿蓝)图片开始并将其转换为YUV(基本上是一个强度通道和两个“色相”通道)。然后,通过为色相的每2X2平方创建一个色相样本来对色相通道进行二次采样。

如果水平或垂直具有奇数个RGB像素,则YUV帧的二次采样色相空间中最后一个像素列或行的数据将不完整。


2
另一个有趣的事实...使用Microsoft Media Foundation进行解码时,您需要对H264使用16的倍数。因此1080P视频实际上会解码为1088高的缓冲区(尽管您忽略了最后8行)。
2015年

2

LordNeckbeard有正确答案,非常快

-vf scale=1280:-2

对于android,不要忘记添加

"-preset ultrafast" and|or "-threads n"

您无需声明线程:这是自动处理的。我相信,编码到H.264时Andriod速度缓慢的原因是人们使用了流行的“ WritingMinds / ffmpeg-android”,该文件--disable-asm在其x264构建脚本中使用。这会导致不必要的和显着的速度下降(您可以检查ffmpeg日志,如果显示出来using cpu capabilties: none!则表明效果不好)。我不确定为什么要添加这些内容,但是我不是Android开发人员。
llogan

1

您也可以使用bitandfunction代替trunc

bitand(x,65534)

trunc(x/2)*2在我看来,它的作用与之相同,并且更加透明。
(请在此处考虑65534的神奇数字;))


我的任务是自动将许多视频文件缩放到一半分辨率

scale=-2,ih/2导致图像稍微模糊

原因:

  • 输入视频的显示纵横比(DAR)已设置
  • scale 缩放实际框架尺寸
  • 在预览期间,必须使用DAR校正新视频的尺寸,如果视频的分辨率较低(360x288,DAR 16:9),可能会导致模糊

解:

-vf "scale='bitand(oh*dar, 65534)':'bitand(ih/2, 65534)', setsar=1"

说明:

  • output_height = input_height / 2
  • output_width = output_height * original_display_aspect_ratio
  • output_widthoutput_height现在由2舍入到最接近的较小数整除
  • setsar=1表示output_dimensions现在是最终的,不应应用任何宽高比校正

有人可能会觉得这很有帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.