4. 文字与时间戳:drawtext滤镜基础、字体与颜色设置、动态时间戳水印、滚动字幕效果

做视频处理,加文字是最常见的需求之一。不管是给视频打水印、加字幕,还是显示时间戳,FFmpeg 的 drawtext 滤镜都是绕不开的工具。说实话,这个滤镜功能非常强大,但参数也多,刚接触时容易懵。今天我就带你把它彻底搞明白。

核心要点:drawtext 滤镜基于 libfreetype 库,支持 TrueType 字体、自定义颜色、位置、透明度,还能读取系统时间或文本文件。掌握它,你就能在视频上做各种文字特效。

4.1 drawtext 滤镜基础用法

先看一个最简单的例子。给视频加上 "Hello World":

ffmpeg -i input.mp4 -vf "drawtext=text='Hello World':fontsize=48:fontcolor=white:x=100:y=100" output.mp4

这个命令做了几件事:

  • text:要显示的文字内容
  • fontsize:字号,单位是像素
  • fontcolor:字体颜色,支持颜色名称或十六进制
  • x / y:文字左上角坐标

嗯,这里要注意——坐标原点在视频左上角,x 向右为正,y 向下为正。我刚开始用的时候总搞反,以为 y 是向上,结果文字跑到了画面外面。

4.2 字体与颜色设置

系统默认字体通常不够好看。我个人习惯指定一个中文字体,比如微软雅黑或思源黑体。

ffmpeg -i input.mp4 -vf "drawtext=text='你好世界':fontfile=/usr/share/fonts/truetype/wqy/wqy-microhei.ttc:fontsize=48:fontcolor=red" output.mp4

字体文件路径 这个参数很关键。Windows 上路径要加双引号,Linux 上注意权限。我在项目中遇到过一个问题:字体路径写对了,但 FFmpeg 编译时没开启 freetype 支持,结果报错。所以先确认一下:

ffmpeg -filters | grep drawtext

如果没输出,说明你的 FFmpeg 没编译 drawtext 滤镜,需要重新编译或换一个版本。

颜色设置 支持多种格式:

格式 示例 说明
颜色名称 white, red, yellow 仅限基本颜色
十六进制 RGB 0xFF0000 红绿蓝各 8 位
十六进制 RGBA 0xFF000080 最后两位是透明度
@ 语法 white@0.5 颜色名 + 透明度

举个例子,半透明的红色水印:

ffmpeg -i input.mp4 -vf "drawtext=text='水印':fontcolor=red@0.5:fontsize=36" output.mp4

小技巧:用 @ 语法控制透明度最方便。0 完全透明,1 完全不透明。我一般用 0.3~0.6 之间,既能看到文字又不遮挡画面。

4.3 动态时间戳水印

给视频加上实时时间戳,这是很多监控视频、录屏教程的刚需。drawtext 支持读取系统时间变量:

ffmpeg -i input.mp4 -vf "drawtext=text='%{localtime}':fontsize=24:fontcolor=white:x=w-tw-10:y=10" output.mp4

这里有几个新东西:

  • %{localtime}:本地时间变量,自动显示当前时间
  • w-tw-10:x 坐标 = 视频宽度 - 文字宽度 - 10 像素,实现右对齐
  • y=10:距离顶部 10 像素

你还可以自定义时间格式:

ffmpeg -i input.mp4 -vf "drawtext=text='%{localtime\:%Y-%m-%d %H\\:%M\\:%S}':fontsize=24:fontcolor=white" output.mp4

注意这里的时间格式转义——冒号要用反斜杠转义,因为 FFmpeg 的滤镜参数里冒号有特殊含义。我曾经在这上面卡了半小时,后来才发现是转义问题。

更高级的用法:显示视频播放进度

ffmpeg -i input.mp4 -vf "drawtext=text='%{pts\:hms}':fontsize=24:fontcolor=yellow" output.mp4

%{pts:hms} 会显示当前帧的时间戳,格式是 时:分:秒。这个在做视频预览或校对时特别有用。

注意:时间戳变量只在滤镜处理时更新,不是实时时钟。如果你需要显示真实世界时间,用 %{localtime};如果需要显示视频内部时间,用 %{pts}。两者不要搞混。

4.4 滚动字幕效果

滚动字幕,也叫跑马灯,常见于新闻底部或片尾致谢。实现原理很简单:让文字的 x 或 y 坐标随时间变化。

水平滚动(从右向左)

ffmpeg -i input.mp4 -vf "drawtext=text='滚动字幕效果':fontsize=36:fontcolor=white:x=w-mod(t*100\,w+tw):y=h-th-20" output.mp4

拆解一下这个表达式:

  • mod(t*100, w+tw):t 是当前时间(秒),乘以 100 控制速度,mod 取模保证循环
  • w+tw:视频宽度 + 文字宽度,确保文字完全移出画面后再重新出现
  • y=h-th-20:距离底部 20 像素

垂直滚动(从下往上)

ffmpeg -i input.mp4 -vf "drawtext=text='片尾致谢':fontsize=48:fontcolor=white:x=(w-tw)/2:y=h-mod(t*50\,h+th)" output.mp4

这个效果常用于片尾字幕。文字从底部出现,向上滚动,循环播放。

速度控制:t 后面的乘数越大,滚动越快。我一般用 50~150 之间,太快看不清,太慢显得拖沓。你可以根据视频时长和文字长度调整。

4.5 综合实战:带时间戳的滚动新闻条

把前面学的结合起来,做一个底部新闻条,左边显示时间,右边滚动新闻文字:

ffmpeg -i input.mp4 -vf \
"drawtext=text='%{localtime\:%H\\:%M\\:%S}':fontsize=28:fontcolor=white:x=20:y=h-50, \
 drawtext=text='今日新闻摘要':fontsize=28:fontcolor=yellow:x=w-mod(t*80\,w+tw):y=h-50" \
output.mp4

这里用了两个 drawtext 实例,用逗号分隔。第一个显示时间,固定在左下角;第二个显示新闻文字,从右向左滚动。

我在项目中做过一个类似的方案,给直播流实时叠加滚动公告。需要注意一点:文字长度变化时,滚动节奏要调整。如果文字太长,速度要加快,否则还没滚完就循环了。

4.6 知识体系总览

下面这张图帮你理清 drawtext 的核心脉络:

drawtext 滤镜知识体系 drawtext 滤镜 基础参数 text / fontfile / fontsize fontcolor / x / y alpha / shadow 时间变量 %{localtime} / %{pts} %{localtime\:format} %{pts\:hms} 表达式计算 mod(t*speed, w+tw) w-tw-10 / h-th-20 sin(t) / if(条件) 静态水印 时间戳水印 滚动字幕

4.7 常见问题与避坑

最后分享几个我踩过的坑:

  • 字体路径错误:Windows 路径用双反斜杠或正斜杠,比如 C:/Windows/Fonts/msyh.ttc
  • 特殊字符转义:冒号、百分号、花括号在滤镜参数里都有特殊含义,需要用反斜杠转义
  • 多行文本:用 \n 换行,但要注意某些字体不支持换行,建议用两个 drawtext 实例
  • 性能问题:drawtext 是 CPU 密集操作,高清视频上多个文字实例会明显降低编码速度。我一般先用低分辨率测试,确认效果后再跑全分辨率

重要提醒:drawtext 的表达式计算是逐帧执行的。如果你在表达式里用了复杂的数学函数(比如 sin、cos、pow),每帧都会重新计算,对性能影响很大。能用简单加减乘除解决的,就别用复杂函数。

好了,drawtext 的核心用法就这些。从静态文字到动态时间戳,再到滚动字幕,你都能用这几个参数组合出来。多动手试试,参数调多了自然就熟练了。