PHP 8.5 无法安全可靠地一行调用 FFmpeg 加水印,必须使用 shell_exec() 配合 escapeshellarg() 转义路径、指定编码器、添加 -y 参数,并确保环境权限与文件有效性。

PHP 8.5 无法直接一行调用 FFmpeg 加水印
PHP 本身不内置视频处理能力,exec() 或 shell_exec() 是唯一可行路径,但“一行代码”隐含了安全、路径、转义、错误处理等被忽略的硬伤。PHP 8.5 和 FFmpeg 是两个独立进程,中间没有魔法胶水。
实际能跑通的最小可靠调用(带基础防护)
必须确保:ffmpeg 在系统 PATH 中、输入文件存在、输出目录可写、水印图格式兼容(推荐 PNG)、PHP 进程有执行 shell 权限(如未禁用 disable_functions)。
- 用
escapeshellarg()包裹所有外部输入(尤其是文件路径),否则空格、单引号、中文路径必炸 - 水印位置建议用
overlay=10:10(左上角),避免用main_w-overlay_w-10等动态表达式——PHP 字符串拼接时容易漏转义 - 强制指定编码参数,例如
-c:v libx264 -c:a aac,否则某些源视频会因编码器不匹配静默失败 - 加上
-y跳过确认,否则命令卡住
shell_exec('ffmpeg -i ' . escapeshellarg($input) . ' -i ' . escapeshellarg($watermark) . ' -filter_complex "overlay=10:10" -c:v libx264 -c:a aac -y ' . escapeshellarg($output));
常见失败现象和对应检查点
命令返回空、输出文件为 0 字节、PHP 报错 Warning: shell_exec(): Unable to execute...,大概率是以下之一:
-
ffmpeg命令找不到:运行which ffmpeg确认路径,必要时改用绝对路径(如/usr/bin/ffmpeg) - 权限问题:Web 服务器用户(如
www-data)无权读取输入文件或写入输出目录 - 水印图损坏或尺寸过大:FFmpeg 对 PNG 透明通道敏感,用
identify -format "%wx%h %r" watermark.png检查是否识别为DirectClass sRGB - PHP 禁用了执行函数:检查
phpinfo()中disable_functions是否包含exec,shell_exec,system
比“一行代码”更值得花时间的事
真实项目里,你很快会遇到:水印要居中、要缩放、要淡入、要随分辨率自适应、要并发防夯死、要记录失败日志。这时候硬塞在一行里的命令会变成维护地狱。
立即学习“PHP免费学习笔记(深入)”;
真正省事的做法是封装成小函数,加超时控制(proc_open + stream_set_timeout),捕获 stderr 输出,并把 overlay 参数拆成变量传入。FFmpeg 命令本身已经够复杂了,别让 PHP 层再增加歧义空间。



















