必须指定 -pix_fmt yuv420p,否则 web 播放器因不支持 yuv444p/yuv422p 等格式而黑屏或花屏;该参数须置于视频编码器后,且 10-bit 选项不被 html5 原生支持。

ffmpeg 转 MP4 时必须指定 pix_fmt,否则可能黑屏或颜色异常
PHP 本身不处理像素格式,所有色彩空间控制都由 ffmpeg 命令决定。Web 播放器(Chrome、Safari、Firefox)只认 yuv420p,其他格式如 yuv444p 或默认的 yuv422p 会导致视频加载后纯黑、花屏或静音——不是 PHP 错,是浏览器拒绝解码。
常见错误现象:PHP 调用 ffmpeg 成功返回 0,output.mp4 文件存在且能用 VLC 播放,但嵌入网页后黑屏或只出声音。
- 强制使用
-pix_fmt yuv420p是硬性要求,不能省略 - 该参数必须放在视频编码器选项之后(如
-c:v libx264后),否则会被忽略 - 若输入源是 PNG 序列或合成画面,
yuv420p还能避免色带(banding)问题 - 不要依赖
-vf format=yuv420p,它不如直接写-pix_fmt可靠
正确命令示例:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -c:a aac output.mp4
ffmpeg 不支持直接设置“色深”(bit depth),但可通过编码器参数间接控制
MP4 容器标准(ISO/IEC 14496-12)和 H.264 编码规范(AVC)只定义 8-bit 色深为基线兼容格式。所谓“10-bit MP4”实际是 HEVC/H.265 容器,不能被 <video></video> 标签原生支持——即使 PHP 强行生成,浏览器也会静默失败或降级为黑屏。
所以:你在 PHP 里调用 ffmpeg 生成 MP4 时,没有合法的 10-bit 选项;强行加 -profile:v high10 或 -pix_fmt yuv420p10le 会生成无法在网页播放的文件。
- Web 场景下唯一安全的组合是:
-pix_fmt yuv420p+-profile:v baseline或-profile:v main -
-profile:v high虽然也属 8-bit,但部分老旧 Android 浏览器不支持,慎用 - 如果原始素材是 10-bit(如专业摄像机录制),转 MP4 前必须先降为 8-bit:
-pix_fmt yuv420p已隐含此转换,无需额外操作 - 真要保留高色深,应输出为
.mp4容器内的 HEVC(需用户设备支持),但目前<video></video>对video/mp4; codecs="hev1"兼容性极差,不推荐
PHP 调用时漏掉 pix_fmt 的典型陷阱
很多人复制网上教程的命令,删掉了 -pix_fmt yuv420p,只留 -c:v libx264,以为“默认就对”。结果在本地测试正常(VLC / ffplay 支持宽泛),上线后用户集体报黑屏。
- PHP 的
exec()或shell_exec()不会自动补全任何参数,你写什么就是什么 - 用
escapeshellarg()包裹路径时,别顺手把-pix_fmt yuv420p也包进去——它是固定字符串,不是路径 - 检查生成文件是否合规:运行
ffprobe -v quiet -show_entries stream=pix_fmt -of default=nw=1 input.mp4,输出必须是pix_fmt=yuv420p - Nginx/Apache 日志里看不到这个错误,只能靠前端
<video></video>的onerror事件或 Network 面板看响应体是否损坏
色彩空间搞错比分辨率更难排查
分辨率错了顶多是拉伸或模糊,但 pix_fmt 错了,整个视频帧数据结构不匹配,浏览器连第一帧都解不出来。它不会报错,只是静默卡在 loading 状态,或者显示黑底+音频——这时候翻日志、查返回码都没用,得直奔 ffprobe 验证输出文件本身。
真正容易被忽略的点是:哪怕你用了 PHP-FFmpeg 扩展,它的 save() 方法默认也不设 pix_fmt,必须手动链式调用 addFilter('-pix_fmt', 'yuv420p') 或用底层命令构造器显式传入。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











