php本身不处理视频转码,需调用ffmpeg等外部工具;关键在环境配置(path、权限、disable_functions)、路径处理(避免空格/中文、用escapeshellarg)、错误捕获(2>&1+$return_code)及跨平台差异(windows需.exe路径、mac受sip限制)。

ffmpeg)或集成扩展(如 ffmpeg-php,已废弃)来触发转码流程。真正差异不在 PHP 语法,而在命令执行环境、路径处理、权限模型和二进制依赖上。
Windows 下 exec() 调用 ffmpeg 失败的典型原因
不是 PHP 写错了,而是 exec() 找不到 ffmpeg.exe 或被系统策略拦住。
-
ffmpeg必须加.exe后缀,且路径不能含空格或中文——C:Program Filesfmpeginfmpeg.exe会失败,应改用短路径C:progra~1fmpeginfmpeg.exe或移到C:fmpegfmpeg.exe - PHP 进程默认以
SYSTEM或IIS_IUSRS身份运行,对C:根目录下某些路径无读取权限;建议把ffmpeg.exe放到项目目录下(如./bin/ffmpeg.exe),再用__DIR__ . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'ffmpeg.exe'拼路径 - Apache/Nginx 的 CGI/FastCGI 模式下,
exec()可能被disable_functions禁用,检查 php.ini 中是否含disable_functions = exec,passthru,shell_exec,system—— Windows 环境下常默认禁用这些函数
Mac 下 shell_exec() 路径与权限陷阱
Mac 的 shell_exec() 看似更自由,但实际受 SIP(System Integrity Protection)、Shell 环境变量隔离、以及 Homebrew 安装路径变动影响更大。
- Homebrew 安装的
ffmpeg默认在/opt/homebrew/bin/ffmpeg(Apple Silicon)或/usr/local/bin/ffmpeg(Intel),但 Web 服务器(如 Apache via MAMP)启动时不会加载用户 Shell 的$PATH,导致shell_exec('ffmpeg -version')返回空 —— 解决方法是显式写全路径:/opt/homebrew/bin/ffmpeg -i input.mov output.mp4 - PHP 进程若由
launchd(如 Valet)启动,其环境变量与终端不一致;可用var_dump($_SERVER['PATH'])查看实际可用路径 - macOS 12+ 对
/tmp目录有沙盒限制,ffmpeg若输出到/tmp/output.mp4可能报错Permission denied;应改用项目内临时目录:sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'ffmpeg_' . uniqid()
跨平台 exec 命令拼接必须绕开的坑
别直接拼字符串,尤其涉及文件路径、空格、特殊字符时,escapeshellarg() 是唯一安全出口。
- 错误写法:
exec("ffmpeg -i {$input} -c:v libx264 {$output}")—— 若$input是/path/to/my video.mov,空格会导致命令截断 - 正确写法:
exec(escapeshellcmd("ffmpeg -i " . escapeshellarg($input) . " -c:v libx264 " . escapeshellarg($output))) - Windows 下还需注意:
escapeshellarg()会把路径变成双引号包裹的"C:path oile.mp4",而ffmpeg.exe在某些旧版本中不认双引号路径 —— 此时可先用str_replace('\', '/', $path)统一为正斜杠,再escapeshellarg()
PHP 调用 ffmpeg 的日志与调试关键点
失败时不报错,是因为 exec() 默认不捕获 stderr。漏掉这步,等于盲操作。
- 始终加上
$output和$return_var参数:exec($cmd, $output, $return_var);$return_var !== 0表示 ffmpeg 执行出错 - 把 stderr 重定向到 stdout:
$cmd .= " 2>&1",否则$output里只有空行 - Windows 下若看到
'ffmpeg' is not recognized as an internal or external command,说明路径或环境变量没配对;Mac 下若看到No such file or directory,大概率是 SIP 阻断或路径未全写 - 建议记录完整命令和返回值:
error_log("FFMPEG CMD: {$cmd} | RETURN: {$return_var} | OUTPUT: " . implode(" ", $output), 3, "/tmp/ffmpeg.log")
ffmpeg 二进制。路径拼错、权限卡住、stderr 被吞——这三个点,占了 90% 的调试时间。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











