mobile-ffmpeg使用filter_complex输出yuv420p时遇宽高非整除2编码报错
问题核心原因
- 编码器硬规则触发:libx264处理yuv420p格式时有强制要求,视频宽、高必须是能被2整除的偶数,任意一维为奇数的话,编码器直接初始化失败,抛出的报错和你日志里的
width not divisible by 2完全对应。 - 动态计算逻辑引入的不稳定:你的filter链路里有两处会动态计算画面尺寸的逻辑——一是scale滤镜开了
eval=frame逐帧求值,二是rotate滤镜用rotw()/roth()函数动态算旋转后的画布大小。这类计算结果没有做偶数对齐的硬约束,某次任务算出来的尺寸是奇数就炸,是偶数就正常跑,这就是为啥报错只出现在部分任务里。 - 不需要额外加-vf:你了解的-vf和filter_complex不能共用的规则没错,但根本不需要单独写-vf,所有尺寸调整操作直接写到filter_complex链路里就行,完全不冲突。
具体修改方案
所有缩放、旋转、叠加、淡入效果全部处理完之后,在filter_complex链路的最后、设置yuv420p输出格式之前,加一个专门的偶数对齐滤镜,直接满足编码器要求,还不会改动你之前做的所有视觉效果。
需要加的滤镜参数为:scale=trunc(iw/2)*2:trunc(ih/2)*2
逻辑非常直接:
- 把当前画面的宽度除以2,用trunc取整之后再乘2,得到最接近原宽度的最大偶数
- 高度按同样的方法计算,得到最接近原高度的最大偶数
- 整个操作是像素级对齐的,不会拉伸变形,最多就是把奇数的1像素边缘裁掉,人眼根本看不出差别。
修改后的filter_complex参考写法
把你原来滤镜链最后一段从
[bg2][img3]overlay=44:22:shortest=1:format=auto,format=yuv420p
调整为
[bg2][img3]overlay=44:22:shortest=1:format=auto,scale=trunc(iw/2)*2:trunc(ih/2)*2,format=yuv420p
避坑提醒
- 这个对齐滤镜一定要放在所有动态计算环节的最后,不能插在链路中间——不然后面的rotate、scale操作还是会把画布尺寸算成奇数,等于白加。
- 如果你的非0旋转任务不需要给旋转后的内容留额外的黑边,可以把rotate里的
oh='roth(角度)'、ow='rotw(角度)'改成和输入帧一致的尺寸,从源头减少旋转环节算出奇数尺寸的概率。 - 别觉得一开始给背景设了
-s 700x900就万事大吉,只要链路里有动态尺寸计算,随时可能把最终输出画布改成非标准尺寸,最后一步的偶数对齐是必加的兜底步骤。
内容的提问来源于stack exchange,提问作者najam ulhassan
相关产品推荐
相关产品推荐

