PHP视频处理必须先在Linux系统级安装FFmpeg二进制,确保www-data或nginx用户可执行;需启用proc_open、shell_exec等函数,配置Nginx上传与超时参数,并设置专用可写临时目录。

PHP视频处理依赖必须手动编译FFmpeg
Linux服务器默认不带FFmpeg,exec('ffmpeg -version') 会直接失败,不是权限问题,是根本没装。PHP调用视频处理命令(如转码、截图、提取音频)前,必须先在系统级安装FFmpeg二进制,并确保PHP运行用户(www-data 或 nginx)能执行它。
常见错误现象:sh: 1: ffmpeg: not found 或 Permission denied;即使 which ffmpeg 返回路径,PHP里仍报错,大概率是SELinux或文件执行权限未放开。
- Ubuntu/Debian:用官方PPA安装较新版本(避免源里老旧的3.x):
sudo apt install software-properties-common && sudo add-apt-repository ppa:savoury1/ffmpeg4 && sudo apt update && sudo apt install ffmpeg - CentOS/RHEL/AlmaLinux:启用EPEL后安装:
sudo dnf install epel-release && sudo dnf install ffmpeg(注意RHEL 8+默认禁用PowerTools,需额外启用) - 验证是否可用:
sudo -u www-data ffmpeg -version(Debian系)或sudo -u nginx ffmpeg -version(RHEL系),必须返回版本号才表示PHP进程能调用 - 若仍报权限拒绝,检查FFmpeg二进制是否被SELinux拦截(RHEL系):
sudo setsebool -P httpd_can_network_connect 1,并确认/usr/bin/ffmpeg有+x权限
PHP.ini必须显式启用proc_open和shell_exec
绝大多数视频处理库(如PHP-FFMpeg、laravel-ffmpeg)底层靠proc_open()启动子进程。但很多生产环境PHP配置默认禁用这些函数,ini_get('disable_functions') 会显示它们被列在黑名单里——这不是安全建议,是硬性限制。
典型报错:proc_open() has been disabled for security reasons;即使你写了shell_exec('ffmpeg -i ...'),也会静默返回空字符串,无任何错误提示。
立即学习“PHP免费学习笔记(深入)”;
- 编辑
/etc/php/*/cli/php.ini和/etc/php/*/fpm/php.ini(两个都要改,CLI用于调试,FPM用于Web请求) - 搜索
disable_functions,删掉proc_open,shell_exec,exec,passthru(保留system等更危险的即可) - 重启PHP-FPM:
sudo systemctl restart php*-fpm(注意版本号,如php8.2-fpm) - 验证:
php -r "echo ini_get('disable_functions');"输出应不含上述函数名
Nginx配置要放宽上传与超时限制
视频文件动辄几十MB甚至GB级,Nginx默认client_max_body_size 是1MB,fastcgi_read_timeout 默认60秒——上传一个500MB MP4或转码10分钟,必然中断。
现象包括:上传进度条卡在99%、502 Bad Gateway、POST Content-Length exceeds limit 错误日志。
- 在
http{}块或server{}块顶部加:client_max_body_size 2G;(根据业务上限设,别写0) - 在
location ~ \.php$块内加:fastcgi_read_timeout 300;(单位秒,转码类操作建议≥300) - 如果用
upload_progress或分片上传,还需配fastcgi_buffering off;防止缓冲区阻塞大文件流 - 改完后
sudo nginx -t && sudo systemctl reload nginx,别只restart
视频临时目录必须由PHP进程可写且独立于Web根
PHP-FFMpeg等库默认把转码中间文件(如帧截图、临时TS切片)写到/tmp,但该目录可能被noexec挂载,或空间不足,更严重的是——如果Web根目录(如/var/www/html)下某个子目录被设为临时输出路径,攻击者可能通过构造恶意文件名触发任意文件读取或覆盖。
典型问题:mkdir(): Permission denied 或 Unable to create directory /tmp/ffmpeg-xxxx;线上偶尔失败,本地复现不了,大概率是/tmp满或挂载参数冲突。
- 创建专用目录:
sudo mkdir -p /var/tmp/php-video - 赋权:
sudo chown www-data:www-data /var/tmp/php-video(Debian)或sudo chown nginx:nginx /var/tmp/php-video(RHEL) - 在PHP代码中显式指定:
$ffmpeg = FFMpeg::create(['ffmpeg.binaries' => '/usr/bin/ffmpeg', 'ffprobe.binaries' => '/usr/bin/ffprobe', 'temporary_files_directory' => '/var/tmp/php-video']); - 补充:
/var/tmp比/tmp更持久,且通常不挂noexec,适合长期存放中间产物
sudo -u www-data ffmpeg -version这一步——很多人只测root或自己账号能跑,却忘了PHP worker进程是以Web服务用户身份运行的。



















