ffmpeg命令找不到需先确认系统级安装并写全路径调用;PHP禁用exec等函数、权限不足、SELinux/AppArmor限制、未用proc_open捕获stderr进度、同步转码超时及输出目录暴露均为常见故障点。

ffmpeg 命令找不到?先确认系统级安装和 PATH
PHP 本身不带视频编解码能力,ffmpeg 必须作为独立命令行工具存在。如果执行 exec('ffmpeg -version') 返回空或报错 sh: ffmpeg: command not found,说明它根本没装进系统,不是 PHP 配置问题。
- Ubuntu/Debian:运行
sudo apt update && sudo apt install ffmpeg,装完立刻验证ffmpeg -version - CentOS/RHEL/AlmaLinux:用
sudo dnf install epel-release && sudo dnf install ffmpeg(注意 EPEL 源需先启用) - 别信“软链接到 /usr/local/bin”这种手动操作——Web 进程(如 www-data)的 PATH 往往不含该路径,
which ffmpeg输出的绝对路径(如/usr/bin/ffmpeg)才可靠 - PHP 脚本里调用时,**必须写全路径**,例如
exec('/usr/bin/ffmpeg -i input.mp4 output.mp4'),否则容易在 Web 环境下失效
PHP 执行函数被禁用了?检查 disable_functions 和用户权限
exec()、shell_exec()、proc_open() 这类函数在共享主机或安全加固环境中常被禁用。现象是函数返回空、null 或静默失败,phpinfo() 里搜 disable_functions 就能一眼看到。
- 编辑
php.ini,找到disable_functions行,删掉exec,shell_exec,system,passthru,proc_open(若存在) - 重启 PHP-FPM:
sudo systemctl restart php*-fpm(版本号按实际填,如php8.2-fpm) - 确保 PHP-FPM worker 进程用户(如
www-data)对输入文件可读、输出目录可写;用ls -l /path/to/input.mp4和ls -ld /path/to/output/dir/检查权限 - SELinux(RHEL系)或 AppArmor(Ubuntu)可能拦截 exec,临时测试可先
sudo setenforce 0或sudo aa-disable,确认是否为策略限制
为什么用 proc_open() 而不是 exec()?进度和错误流必须分开捕获
exec() 是黑盒式调用:命令跑完才吐全部输出,中间卡住、超时、Nginx 断连都无感知。而视频转码动辄几十秒,用户需要进度条或实时日志诊断,proc_open() 是唯一靠谱选择。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
-
proc_open()的$descriptorspec至少要定义三路:stdin(["pipe","r"])、stdout(["pipe","w"])、stderr(["pipe","w"]) - 转码过程中的进度信息(如
frame=1234 fps=25 q=28.0 size=12345kB time=00:00:45.23 bitrate=2245.6kbits/s)默认走 stderr,必须单独读取才能解析时间/帧率 - 不要忽略
proc_get_status($process)['running']判断,避免脚本假死;配合stream_set_blocking($pipes[1], false)实现非阻塞读取 - 示例关键片段:
$process = proc_open('/usr/bin/ffmpeg -y -i input.mp4 -c:v libx264 output.mp4', $descriptorspec, $pipes)
Web 下同步转码很危险:超时、内存溢出、并发崩溃全在这儿
用户上传一个 500MB 视频,PHP 脚本直接调 proc_open() 并等待结束——这是生产环境最常见崩盘起点。Nginx 默认 60 秒超时,PHP max_execution_time 通常设为 30,Apache 也有类似限制。
立即学习“PHP免费学习笔记(深入)”;
- 真实项目必须拆成「接收 → 入队 → 后台处理 → 回调通知」四步,用 Redis 队列或 RabbitMQ 托底
- Web 请求只负责存文件、写任务记录、返回任务 ID;转码由独立的 CLI 脚本(如
php artisan video:process)在后台持续拉取执行 - 输出目录不能放在 Web 可访问路径下(如
/var/www/html/uploads/),否则生成的 MP4 可能被直接下载,也易被恶意覆盖;建议用/var/video/output/+ Nginx alias 或 X-Accel-Redirect 控制访问 - 哪怕只是测试,也要加
set_time_limit(0)和ignore_user_abort(true),否则用户刷新页面就中断进程


















