ffmpeg 9.0 与 8.1 的 overlay 行为语法一致,但 9.0 在参数校验、硬件加速桥接、分辨率自适应、时间戳对齐上更严格:未定义变量、缺失 hwcontext、硬编码 w/h、未规整 pts 均导致直接报错而非警告。

overlay 坐标表达式在 9.0 和 8.1 中行为一致,但底层执行更严格
直接说结论:overlay=W-w-10:H-h-10 这类写法在 FFmpeg 8.1 和 9.0 中都能正常工作,语法没变。真正区别不在命令本身,而在参数校验和滤镜图初始化逻辑——9.0 对 filter_complex 中变量未定义、类型不匹配、或 PTS 时间基准错位的容忍度大幅降低。比如你在 8.1 里漏传水印图(-i watermark.png),可能只报 warning 就继续跑;9.0 会直接 abort 并提示 Error initializing complex filters: Invalid argument。
硬件加速水印链路在 9.0 中必须显式声明 hwcontext
如果你用 NVENC 或 VAAPI 加速编码 + overlay 水印,8.1 可能隐式完成像素格式转换(如把 RGB 水印图自动转为 NV12);9.0 要求你明确插入 format=nv12 或 hwupload 步骤,否则大概率报 Unsupported pixel format。典型失败命令:
ffmpeg -hwaccel cuda -i in.mp4 -i logo.png -filter_complex "overlay=10:10" -c:v h264_nvenc out.mp4
正确写法需补全硬件上下文桥接:
ffmpeg -hwaccel cuda -i in.mp4 -i logo.png -filter_complex "[1]scale=200:80,format=nv12,hwupload[wm];[0:v][wm]overlay=10:10" -c:v h264_nvenc out.mp4
-
scale和format必须在hwupload前,否则 GPU 内存上传失败 -
hwupload后的水印流必须和主视频流同属一个硬件设备上下文(-hwaccel_device 0等参数不能漏) - 若水印是 PNG 且含 alpha 通道,还需加
alphaextract+alphamerge,否则透明区域变黑
多分辨率自适应水印在 9.0 中必须用 scale2ref 替代硬编码 W/w
8.1 里用 overlay=x=W-w-10:y=H-h-10 在固定分辨率视频上没问题;但遇到混合源(如一批含 4K/1080p/720p 的 MP4),8.1 仍会按第一个输入帧的 W/H 值计算所有帧,导致小分辨率视频水印溢出。9.0 默认启用更严格的帧级分辨率感知,硬编码 W/H 会触发警告,且实际坐标可能被截断。工程推荐写法:
ffmpeg -i in.mp4 -i logo.png -filter_complex "[0:v][1:v]scale2ref=w='iw*0.15':h='ow/iw*ih'[vid][logo];[vid][logo]overlay=x=W-w-10:y=H-h-10" -c:v libx264 out.mp4
关键点:
-
scale2ref把水印缩放到主视频宽度的 15%,保证物理尺寸比例一致 -
W和w此时指代的是[vid]和[logo]流各自的宽,不是全局静态值 - 该写法在 8.1 中也能运行,但 9.0 下是唯一能通过严格模式校验的方式
时间戳对齐错误在 9.0 中暴露得更早、报错更具体
如果输入视频带非零 start_time(如某些手机录屏、监控流导出文件),8.1 的 overlay 可能静默跳过前几秒,水印延迟出现;9.0 会在初始化阶段就报 Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future.,并中断执行。解决办法不是忽略警告,而是提前规整时间轴:
- 加
-fflags +genpts强制生成 PTS - 或用
-vf "setpts=PTS-STARTPTS"重置视频时间基 - 若水印需随音频同步(如动态文字水印),必须用
enable='between(t,10,20)'而非依赖输入时间戳
9.0 不再帮你“猜意图”,它只按你写的 filter 表达式字面执行——这反而让问题定位更快,但要求你对 PTS/DTS、帧率继承、滤镜时序依赖有真实理解。











