PHP需调用FFmpeg实现动态水印,用drawtext或overlay配合时间变量t控制位置、透明度、缩放、旋转等;须确保FFmpeg安装、权限正确,并通过escapeshellarg()防护命令注入。

PHP 本身不直接处理视频,加动态水印(即随时间变化、移动、缩放的水印)需调用 FFmpeg 命令行工具,通过 PHP 的 exec()、shell_exec() 或 proc_open() 执行 FFmpeg 命令实现。关键在于用 FFmpeg 的 drawtext(文字水印)或 overlay(图片水印)配合时间表达式(如 t 变量)来实现“动态”效果。
1. 确保系统已安装并可调用 FFmpeg
在 PHP 中执行前,先确认服务器已安装 FFmpeg 且 PHP 有执行权限:
- Linux/macOS:运行
which ffmpeg或ffmpeg -version检查路径和版本(建议 ≥ 4.0) - Windows:确保 ffmpeg.exe 在系统 PATH 中,或使用绝对路径(如
/var/www/ffmpeg/bin/ffmpeg) - PHP 需开启
exec相关函数(检查disable_functions配置) - Web 服务器用户(如 www-data、nginx)需对输入视频、输出目录及临时文件有读写权限
2. 动态文字水印(例如:从左到右滚动 + 透明度渐变)
利用 drawtext 的 x、y、alpha 支持时间变量 t 实现动态效果:
示例命令(PHP 中拼接后执行):
立即学习“PHP免费学习笔记(深入)”;
ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:fontsize=48:fontcolor=white@0.7:x=(t*100)%w:y=h-th-20:text='© MySite':enable='gte(t,1)'" -c:a copy output.mp4
-
x=(t*100)%w:每秒向右移动 100 像素,超出宽度时取模实现循环滚动 -
y=h-th-20:固定在底部上方 20 像素处(h是画面高,th是文字高) -
enable='gte(t,1)':从第 1 秒开始显示 -
fontfile必须是服务器上的绝对路径,且字体文件需有读取权限
3. 动态图片水印(例如:缩放+旋转+移动)
使用 overlay 滤镜链,结合 scale、rotate、setpts 等滤镜,并用 t 控制参数:
示例(水印图 logo.png 缩放随时间增大,同时绕中心旋转):
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1][0]scale2ref=w='if(lte(iw/ih,ow/oh),ow,ow*ih/iw)':h='if(lte(iw/ih,ow/oh),oh*iw/iw,oh)'[wm][vid]; [wm]rotate=t*PI/10:ow=rotw(PI/10):oh=roth(PI/10):c=none[rot]; [vid][rot]overlay=x='(W-w)/2+(t*50)%100':y='(H-h)/2':enable='gte(t,0.5)'" -c:a copy output.mp4
-
scale2ref将水印适配到视频尺寸比例 -
rotate=t*PI/10:每秒旋转 18 周(π/10 弧度 ≈ 18°) -
x='(W-w)/2+(t*50)%100':水平居中基础上叠加周期性左右微移 - 注意:
W/w/H/h是大写表示主视频宽高,小写表示水印宽高;rotw/roth是旋转后尺寸
4. PHP 安全执行与错误处理建议
避免命令注入,必须过滤输入路径和参数:
- 使用
escapeshellarg()包裹所有用户可控路径(如视频路径、字体路径) - 不要拼接用户输入的文字内容到
drawtext=text='...'中;如需动态文本,先生成临时文件再用textfile参数读取 - 捕获错误输出:
$output = shell_exec("ffmpeg -i ... 2>&1");并检查是否含error或failed - 设置超时(如
proc_open配合 stream_set_timeout)防止卡死 - 生产环境建议异步处理(如进队列),避免 Web 请求阻塞



















