php-ffmpeg 是 ffmpeg 命令行工具的封装,需系统预装 ffmpeg 并确保权限、路径、版本正确;应提前用 getstreams() 验证源文件,用 addfilter() 精确控制转码参数,异步转码需配合消息队列而非 saveasync()。

PHP-FFMpeg 库本身不直接执行转码,它只是 ffmpeg 命令行工具的 PHP 封装;没装好系统级 ffmpeg,库再完整也跑不起来。
确认系统已安装可用的 ffmpeg 命令
这是最容易卡住的第一步。PHP-FFMpeg 不自带二进制,它默认调用全局 ffmpeg 命令。很多开发者在 Docker 或共享主机里直接 composer install 就以为完事了,结果 RuntimeException: Unable to launch a new process 或 command not found。
- 终端执行
which ffmpeg或ffmpeg -version,必须返回版本号 - 如果用 Docker,要在镜像里显式安装,比如 Debian 系:
apt-get update && apt-get install -y ffmpeg - Windows 下确保
ffmpeg.exe在系统 PATH,或在初始化时手动指定路径:FFMpeg::create(['ffmpeg.binaries' => 'C:/ffmpeg/ffmpeg.exe']) - PHP 进程用户(如 www-data)必须有权限执行该二进制,SELinux 或某些云函数环境会静默拦截
FFMpeg::open() 后立即调用 getStreams() 验证源文件可读
很多“转换失败”实际是源视频损坏、权限不足或格式不被识别,但错误直到 save() 才抛出,堆栈深、定位难。提前探测能快速暴露问题。
-
$video = FFMpeg::open('/path/to/input.mp4')->getStreams()->videos();—— 若返回空数组,说明 FFmpeg 根本没解析出视频流 - 常见原因:文件路径含中文或空格(需
urlencode或改用绝对路径)、NFS 挂载延迟、MP4 文件头损坏(ffprobe /path可验证) - 注意:某些 HEVC 编码的 MP4 在旧版
ffmpeg里可能被跳过,升级到 4.4+ 更稳妥
用 addFilter() 控制关键参数,别只依赖 resize()
resize() 是快捷封装,底层仍走 scale filter,但实际生产中常需精确控制帧率、关键帧间隔、编码器选项——这些必须用 addFilter() 显式传入字符串参数。
- 例如强制恒定帧率 + 关键帧每 2 秒:
$video->addFilter('-r 30 -g 60') - H.265 转码需指定编码器:
$video->addFilter('-c:v libx265 -crf 28'),否则默认还是libx264 - 音频务必处理:
$video->addFilter('-c:a aac -b:a 128k'),否则可能丢音轨或采样率异常 - 过滤器顺序敏感:缩放(
scale)应在帧率控制(-r)之后,否则尺寸可能意外改变
异步转码时注意临时文件生命周期和回调可靠性
调用 saveAsync() 并不等于“后台运行”,它只是 fork 出子进程并监听 stdout/stderr;PHP 主进程退出、Web 请求超时、或 proc_open 被禁用都会导致任务静默终止。
- Web 环境慎用
saveAsync():建议改用消息队列(如 Redis Queue)触发save(),由独立 worker 执行 - 临时文件(如滤镜中间帧)默认写在系统 tmp 目录,磁盘满会导致
Cannot write to file,可通过setTempDirectory()指向有空间的路径 - 回调函数里的
$message参数内容不稳定(取决于 ffmpeg 输出),不要依赖其结构做逻辑判断,只用于日志记录
真正麻烦的从来不是怎么写那几行 PHP,而是 ffmpeg 版本差异、容器权限、临时目录配额、以及原始视频里那些 FFmpeg 自己都懒得报错的隐性损坏。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











