必须显式指定-pix_fmt yuv420p,因为FFmpeg默认输出yuv444p等格式在MP4容器、移动端及HLS中不兼容,易致黑屏或解码失败;该参数须置于输出选项区(-i之后、输出文件前),且需在-vf之后,PHP调用时须防引号/空格导致参数丢失。

为什么 pix_fmt 必须显式指定
FFmpeg 默认输出的像素格式(如 yuv444p)在部分播放器、移动端或 HLS 封装中不兼容,会导致黑屏、解码失败或无法硬解。MP4 容器规范强制要求使用 yuv420p —— 这是唯一被广泛支持的色度采样格式。漏设 -pix_fmt yuv420p 是 PHP 调用 FFmpeg 生成 MP4 后“能生成但播不了”的最常见原因。
ffmpeg -pix_fmt yuv420p 的实际写法与位置
该参数必须放在输出选项部分(即 -i 输入之后、输出文件路径之前),且优先级高于编码器默认行为。错误地把它放错位置(比如塞在输入参数里)会被忽略。
- ✅ 正确:
ffmpeg -i input.avi -c:v libx264 -pix_fmt yuv420p output.mp4 - ❌ 错误:
ffmpeg -pix_fmt yuv420p -i input.avi -c:v libx264 output.mp4(此处在输入阶段指定,无效) - ⚠️ 注意:若同时用
-vf(如缩放、裁剪),-pix_fmt必须写在-vf之后,否则滤镜输出可能覆盖它
PHP 中调用时的典型陷阱
在 exec() 或 shell_exec() 中拼接命令时,pix_fmt 很容易因引号、空格或变量插值被吞掉或错位。
- 必须用
escapeshellarg()包裹所有路径,但-pix_fmt yuv420p是固定参数,无需包裹 - 不要写成
"-pix_fmt yuv420p "(末尾空格),某些 shell 会截断导致参数失效 - 若用 PHP-FFmpeg 扩展,它默认已设
yuv420p,但自定义X264格式时仍需手动调用setPixelFormat('yuv420p') - 验证是否生效:转码后运行
ffprobe -v quiet -show_entries stream=pix_fmt -of default=nw=1 input.mp4,输出应为pix_fmt=yuv420p
其他相关色度采样格式要不要碰
除 yuv420p 外,yuv422p 和 yuv444p 虽然画质略高,但 MP4 播放兼容性极差——iOS Safari、Android MediaPlayer、大部分 HTML5 <video> 标签均拒绝解码。除非你明确控制全链路(如只用于本地 VLC 播放或后续转封装为 MOV),否则一律回避。
立即学习“PHP免费学习笔记(深入)”;
真正需要关注的是:确保 yuv420p 与 -profile:v baseline(兼容老设备)或 -movflags +faststart(优化首帧加载)配合使用,而不是纠结更高阶采样。



















