跑马灯水印本质是用FFmpeg drawtext滤镜通过x=w+t*100等时间表达式实现动态位置overlay;PHP-FFMpeg 1.4.0需用addFilter透传该滤镜,注意字体路径、编码、格式兼容性及调试命令输出。

跑马灯水印的本质是动态位置的 overlay
PHP-FFMpeg 1.4.0 本身不提供「跑马灯」(即从右向左匀速移动的文字水印)的封装方法,它只支持静态 addFilter 或 addWatermark。所谓跑马灯,必须靠 FFmpeg 原生命令实现——即用 drawtext 滤镜配合时间表达式 t 动态计算 x 坐标。PHP-FFMpeg 的 addFilter 是唯一能透传这类复杂滤镜的入口。
用 addFilter 注入 drawtext 实现左移跑马灯
关键在于构造正确的 FFmpeg 滤镜字符串,并确保字体路径可访问、编码兼容。以下是最小可行配置:
$video
->addFilter(
'drawtext=' .
'fontfile=/var/www/fonts/arial.ttf:' . // 必须是服务器绝对路径,且 PHP 进程有读取权限
'text=\'Hello World\':' . // 单引号需转义,文字内容建议 URL 编码避免空格/特殊字符问题
'fontsize=24:' .
'fontcolor=white@0.8:' .
'x=w+t*100:' . // 核心:x = 视频宽 + 时间×速度;t 单位为秒,100 表示每秒向左移动 100px
'y=h/2-12:' . // 垂直居中(假设 fontsize=24,则行高约 24px)
'shadowx=2:shadowy=2:shadowcolor=black@0.6'
)
->save('output.mp4');
-
x=w+t*100是跑马灯逻辑起点:视频最右侧(w)开始,随时间推移不断减小x值;若要从左进、右出,改用x=-tw+t*100(需估算文字宽度) - 字体文件必须真实存在且为 TrueType(.ttf)格式;Linux 下常见报错
Cannot load font file多因路径错误或 SELinux/权限拦截 - 中文需额外指定
text='$(echo -n "你好" | iconv -f utf-8 -t gbk)'或改用支持 UTF-8 的字体(如 NotoSansCJK),否则显示方块
避免常见崩溃点:时长、编码与透明度
直接套用上述滤镜可能导出失败,原因往往不在语法,而在上下文约束:
- 输入视频若为 H.265(HEVC)编码,某些 FFmpeg 版本对
drawtext支持不稳定,优先转为 H.264 再加水印:$video->setFormat(new \FFMpeg\Format\Video\X264()) - 跑马灯需全程可见,但默认只在视频时长内生效;若希望文字循环滚动,需用
mod(t\,10)控制周期,例如x=w+100*mod(t\,15)表示每 15 秒循环一次 -
@0.8是 alpha 通道写法,仅在使用支持透明度的像素格式(如yuv420p)时生效;若输出黑底或无透明效果,显式添加format=yuv420p到滤镜链末尾
调试时优先检查 FFmpeg 命令是否真被调用
PHP-FFMpeg 1.4.0 默认静默执行,出错不报具体 FFmpeg 错误。启用调试最有效的方式是捕获底层命令:
立即学习“PHP免费学习笔记(深入)”;
$ffmpeg = FFMpeg::create([
'ffmpeg.binaries' => '/usr/bin/ffmpeg',
'ffprobe.binaries' => '/usr/bin/ffprobe',
'timeout' => 3600,
'ffmpeg.threads' => 12,
]);
$ffmpeg->getFFMpegDriver()->getLogger()->pushHandler(new \Monolog\Handler\StreamHandler('php://stderr'));
这样终端会输出实际执行的完整 FFmpeg 命令,复制出来手动运行,能立刻定位是字体路径、表达式语法,还是 libfreetype 缺失等底层问题。
跑马灯看着简单,但每个变量(t、w、字体度量、帧率)都可能让文字卡顿、跳帧或突然消失;别依赖“试几次”,先确认 FFmpeg 命令本身能跑通,再交还给 PHP-FFMpeg 封装。



















