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

And*_*Hin 162 ffmpeg h.264 libx264

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

这是我正在运行的命令:

/usr/local/bin/ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4
Run Code Online (Sandbox Code Playgroud)

我有时会收到以下错误:

[libx264 @ 0xa3b85a0] height not divisible by 2 (520x369)
Run Code Online (Sandbox Code Playgroud)

在稍微搜索之后,似乎问题与缩放算法有关,可以通过添加-vf参数来修复.

但是,在我的情况下,我不想做任何缩放.理想情况下,我希望保持尺寸与框架完全相同.有什么建议?是否存在h264强制执行的某种宽高比?

And*_*Hin 241

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

-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"
Run Code Online (Sandbox Code Playgroud)

命令:

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

基本上,.h264需要均匀的尺寸,因此这个过滤器将:

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

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

  • 您可能最好使用pad而不是scale,以添加黑色行/列.将图像向上缩放一个像素会使图像模糊. (7认同)
  • 为了记录,我只是做了一些用图像创建视频的东西,它使用yuvj444p作为像素格式; 它并不关心视频大小.然后我需要将其转换为yuv420p,然后它关心视频大小.我在维基百科上查找yuv420p,我认为它是一种多像素颜色格式,需要图像为特定大小.但不确定为什么压缩很重要. (5认同)
  • @NickeManarin,这个过滤器应该可以在垂直方向上添加1像素的白色填充,视频位于左上角:`-vf pad ="width = iw:height = ih + 1:x = 0:y = 0:颜色=白色"`.ffmpeg pad文档位于:https://ffmpeg.org/ffmpeg-filters.html#pad-1. (5认同)
  • 这里的解决方案只是将填充像素添加到奇数维度:`-vf pad ="width = ceil(iw/2)*2:height = ceil(ih/2)*2"`. (4认同)
  • 这不是一个错误.由于输出将继承输入的帧大小,因此您不执行缩放并不重要. (3认同)
  • @danneu这是正确的答案.缩放将使视频看起来很糟糕,填充更好.. (3认同)
  • 高度能被 2 整除并不是 h264 的要求,而是所使用的像素格式的要求:yuv420p。如果您使用 yuv422p,则不必处理此限制。 (3认同)
  • 而不是填充,如果你喜欢裁剪。这是公式`crop=floor(iw/2)*2:floor(ih/2)*2` (2认同)
  • 命令 '-vf pad=..." 应放在输出 video.mp4 之前,否则不会执行填充。我的示例: ffmpeg -i test.h264 -vcodec libx264 -vf pad="width=iw+16: height=ih+16:color=white" -frames 10 -y -an test.mp4 (2认同)

llo*_*gan 214

只是用 -2

比例过滤器文档:

如果这些值中的一个是-nn > 1,规模过滤器也将使用该保持输入图像的纵横比的值,与其它指定的尺寸来计算.之后,它将确保计算出的尺寸可以被整除,n并在必要时调整该值.

例子

将宽度设置为1280,将自动计算高度以保持纵横比,并且高度可以被2整除:

-vf scale=1280:-2
Run Code Online (Sandbox Code Playgroud)

与上面相同,但具有声明的高度; 离开宽度由过滤器处理:

-vf scale=-2:720
Run Code Online (Sandbox Code Playgroud)

"可被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是一个简单的解决方案.

  • 我认为这应该被标记为正确答案,因为没有涉及"技巧".Whish to upvote不止一次 (14认同)
  • @tuner`-2` 的结果值取决于另一个维度的声明值。 (3认同)
  • 在我的情况下,这给了我以下错误:`大小值小于-1是不可接受的.但@Zbyszek的答案工作得很好. (3认同)
  • @Julien [这不是`ffmpeg`](http://stackoverflow.com/a/9477756/1109017)。您可以[下载静态版本](http://johnvansickle.com/ffmpeg/)。 (2认同)

Zby*_*zek 63

如果要设置一些输出宽度并使输出具有与原始相同的比率

scale=720:-1 
Run Code Online (Sandbox Code Playgroud)

而不是与这个问题,然后你可以使用

scale="720:trunc(ow/a/2)*2"
Run Code Online (Sandbox Code Playgroud)

(仅适用于通过缩放搜索如何执行此操作的人员)

  • 对于固定的高度,它是`scale ="trunc(oh*a/2)*2:720"` (16认同)

Adi*_*sak 18

这可能是由于H264视频通常在应用压缩之前从RGB转换为YUV空间为4:2:0(尽管格式转换本身是有损压缩算法,因此节省了50%的空间).

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

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

  • 另一个有趣的事实......当您使用 Microsoft Media Foundation 的东西进行解码时,您需要对 H264 使用 16 的倍数。所以 1080P 视频实际上解码成一个 1088 高的缓冲区(尽管你忽略了最后 8 行)。 (2认同)

dan*_*neu 14

scale这里的解决方案的问题是它们扭曲了源图像/视频,这几乎不是你想要的.

相反,我发现最好的解决方案是在奇数维上添加1像素的垫.(默认情况下,涂层是黑色的,很难注意到.)

其他pad解决方案的问题在于它们不会在任意维度上进行推广,因为它们总是填充.

此解决方案仅在高度和/或宽度上添加1像素焊盘(如果它们是奇数):

-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"
Run Code Online (Sandbox Code Playgroud)

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

  • 刚刚遇到这个问题,并且可以确认这个答案有效。或者,如果您使用复杂的过滤器,这样的解决方案将起到作用 `-filter_complex "[0:v] {您拥有的一些过滤器} [outv]; [outv]pad='width=ceil(iw/2)* 2:高度=ceil(ih/2)*2'[outvpad]" -map "[outvpad]"` (3认同)
  • @Gyan自从我解决这个问题以来已经太久了(我的答案是从我很久以前发表的评论中提取的),但我记得按单个像素缩放*确实*在某些条件下引入了明显的视觉伪像,这就是为什么我一开始就很烦恼。我不太记得了,也许单个像素的变化造成了不成比例的模糊?也许只适用于某些视频/图像格式?我只能说,我通过此修复处理了数千个视频,这是有利的转换。 (2认同)
  • 可以确认;填充像素不会增加伪影。即使仅拉伸单个像素,也会因锯齿而增加一些小伪影。 (2认同)