必须显式指定ffmpeg和ffprobe完整路径,因php-fpm环境变量与shell不同;用ffmpeg::create(['ffmpeg.binaries'=>'/usr/local/bin/ffmpeg','ffprobe.binaries'=>'/usr/local/bin/ffprobe'])并验证web用户有执行权限。

FFmpeg找不到可执行文件怎么办
PHP-FFMpeg 报 ExecutableNotFoundException,本质是它根本没找到 ffmpeg 或 ffprobe 命令。这不是 PHP 代码写错了,而是环境路径或配置没对上。
- 先在终端手动运行
which ffmpeg和which ffprobe,确认它们真实存在且路径一致 - 不要依赖系统
PATH—— PHP-FPM 的环境变量往往和 shell 不同,必须显式指定路径 - 创建实例时直接传入完整路径:
FFMpeg::create(['ffmpeg.binaries' => '/usr/local/bin/ffmpeg', 'ffprobe.binaries' => '/usr/local/bin/ffprobe']) - 如果用 Docker,确保二进制文件在容器内、且 PHP 进程有执行权限(
chmod +x)
视频上传后转码失败但无报错
常见现象是输出目录空空如也,或者生成一个几 KB 的损坏文件,shell_exec() 返回空字符串——其实 FFmpeg 已经失败,只是错误被吞掉了。
- 务必把
2>&1加到命令末尾,例如:ffmpeg -i input.mp4 -c:v libx264 output.mp4 2>&1 - 用
proc_open()捕获stderr更可靠,避免 shell 层级干扰 - 检查
$_FILES['video']['error']是否为UPLOAD_ERR_OK,否则后续操作全是徒劳 - 输入文件若本身损坏(比如传输中断),FFmpeg 可能静默退出,用
ffprobe -v error -show_entries format=duration -of default=nw=1 input.mp4预检是否可解析
PHP输出视频卡顿、拖动失效
用 readfile() 直接吐视频文件,浏览器会卡死、无法拖动、反复加载——这不是 PHP 性能问题,是 HTTP 协议层面缺失关键支持。
- 必须响应
Accept-Ranges: bytes头,否则浏览器不发起分片请求 - 遇到
Range请求头时,不能返回完整文件,得用fopen(..., 'rb')+fseek()定位并只输出对应字节段 - 返回状态码必须是
206 Partial Content,且带Content-Range字段,格式如bytes 0-1023/1234567 - 真正安全的做法是:PHP 只鉴权,然后发
X-Accel-Redirect(Nginx)或X-Sendfile(Apache),让 Web 服务器原生处理 Range 请求
用户传来的文件名导致命令注入
拼接 ffmpeg 命令时直接插进 $_POST['output_name'],等于给攻击者开了个 shell 入口。一个分号就能删库跑路。
- 绝对禁止字符串拼接命令,尤其涉及用户输入的任何字段(文件名、分辨率、码率参数)
- 优先用
php-ffmpeg/php-ffmpeg库,它内部用proc_open()传递参数,天然规避 shell 解析 - 若必须调用命令行,每个参数都过
escapeshellarg(),包括输入路径、输出路径、甚至-vf后的滤镜表达式 - 输出路径必须限定在白名单目录内,比如
/var/www/storage/videos/,禁止 ../ 路径穿越
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











