php执行ffmpeg前须确认三件事:一、php进程有权限且系统已安装ffmpeg并位于path中;二、web服务器未禁用exec等函数;三、ffmpeg编译支持overlay等水印所需滤镜。

PHP执行FFmpeg命令前必须确认的三件事
exec()、shell_exec() 或 proc_open() 能调用 FFmpeg,但实际失败多数不是代码问题。先检查:
- 确保 PHP 进程有权限执行外部二进制 —— 在 CLI 下运行
php -r "echo shell_exec('which ffmpeg');",返回空说明系统没装或不在$PATH中
- Web 服务器(如 Apache/Nginx)运行的 PHP 通常被禁用部分函数,检查
disable_functions是否含exec、shell_exec、system
- FFmpeg 需支持水印功能(即编译时带
libass和libfreetype),运行ffmpeg -filters | grep overlay应能看到overlay滤镜
最简可行的批量加图水印脚本(Linux/macOS)
核心是循环拼接命令,而非依赖第三方库。假设水印图是 logo.png,放在视频同级目录,输出到 output/:
foreach (glob("*.mp4") as $video) {
$output = "output/" . pathinfo($video, PATHINFO_FILENAME) . "_watermarked.mp4";
$cmd = sprintf(
'ffmpeg -i %s -i logo.png -filter_complex "overlay=10:10" -c:a copy %s 2>&1',
escapeshellarg($video),
escapeshellarg($output)
);
$result = shell_exec($cmd);
if (strpos($result, 'Error') !== false || !file_exists($output)) {
error_log("Failed on {$video}: {$result}");
}
}
注意:
- 必须用
escapeshellarg()包裹路径,否则含空格或特殊字符的文件名直接报错
-
-c:a copy表示音频流不重编码,省时间;若需同步音画,加-vsync vfr防卡顿
-
overlay=10:10是左上角偏移,单位是像素;右下角常用overlay=W-w-10:H-h-10(W/H 是视频宽高,w/h 是水印宽高)
加文字水印时字体路径和编码最容易翻车
drawtext 滤镜依赖系统字体,Web 环境常无图形界面,fontfile 必须写绝对路径,且字体文件需 PHP 进程可读:
- Linux 下可用
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf(先fc-list确认存在)
- 字符串含中文必须指定
fontcolor=white@0.8:box=1:boxcolor=black@0.5并加text='中文',但更稳的是用 UTF-8 编码的字符串 +reload=1防缓存
- 错误示例:
drawtext=text=测试→ 报Unable to parse option value "测试";正确写法:drawtext=fontfile=/path/to/simhei.ttf:text='测试':x=10:y=10
并发多任务别硬套 for 循环
单进程顺序处理 100 个视频可能卡死或超时。真实批量场景建议:
- 用
proc_open()控制并发数(例如最多同时跑 3 个ffmpeg进程),避免内存炸掉
- 把待处理列表写入队列(如 Redis 或简单文本文件),用守护进程分片消费
- 日志必须单独记录每个视频的
ffmpeg完整命令和 stderr 输出,否则出错根本没法定位是参数错还是磁盘满
水印位置计算、字体加载、并发控制这三块,现场调试时 80% 的问题都集中在这儿,而不是语法本身。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











