21、添加水印:使用overlay滤镜叠加图片水印、文字水印、时间水印

水印这东西,说白了就是给视频打上专属标记。不管是保护版权,还是品牌露出,甚至只是加个拍摄时间,都离不开它。我在做视频后期处理时,几乎每个项目都会遇到这个需求。

FFmpeg 的 overlay 滤镜,就是干这个的。它能把一张图、一段文字,甚至动态的时间戳,叠加到视频画面上。今天我就带你把它玩透。

21.1 图片水印:最基础的叠加

图片水印是最常见的。比如给视频加上 Logo。

先看一个最简单的命令:

ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=10:10" output.mp4

这个命令把 logo.png 放在视频的左上角,距离左边和上边各 10 像素。

但实际项目中,我们往往需要更灵活的位置。比如右下角:

ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=main_w-overlay_w-10:main_h-overlay_h-10" output.mp4

这里用到了几个内置变量:

  • main_w:主视频宽度
  • main_h:主视频高度
  • overlay_w:水印图片宽度
  • overlay_h:水印图片高度

嗯,这里要注意:如果你想让水印居中,可以这样写:

overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2

我曾经在做一个批量处理项目时,客户要求水印位置必须精确到像素。当时我直接用硬编码坐标,结果不同分辨率视频全乱了。后来改用变量计算,一劳永逸。

我的习惯: 所有水印位置都用相对坐标,别写死。这样换视频分辨率时不用改命令。

21.2 文字水印:用 drawtext 滤镜

文字水印需要用到另一个滤镜——drawtext。它依赖 libfreetype 库,编译 FFmpeg 时记得带上。

基本用法:

ffmpeg -i input.mp4 -vf "drawtext=text='蓝海资料':fontcolor=white:fontsize=24:x=10:y=10" output.mp4

这会在左上角显示白色文字「蓝海资料」。

但文字水印的坑不少。我列几个常见参数:

参数 说明 示例
text 文字内容 text='Hello'
fontfile 字体文件路径 fontfile=/usr/share/fonts/msyh.ttf
fontcolor 字体颜色 fontcolor=white@0.5
fontsize 字号 fontsize=36
box 是否加背景框 box=1:boxcolor=black@0.3
shadowx/shadowy 文字阴影偏移 shadowx=2:shadowy=2

我个人习惯给文字加个半透明背景框,这样在任何画面下都能看清:

ffmpeg -i input.mp4 -vf "drawtext=text='蓝海资料':fontcolor=white:fontsize=28:box=1:boxcolor=black@0.4:x=10:y=10" output.mp4
我曾经踩过的坑: 在 Windows 上使用 drawtext,字体路径必须用双反斜杠或者正斜杠。比如 fontfile=C:/Windows/Fonts/msyh.ttf,别用单反斜杠。

21.3 时间水印:动态显示当前时间

时间水印在监控视频、录屏回放中特别常用。drawtext 支持时间变量,可以实时显示视频的当前时间戳。

核心用法:

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

%{localtime} 会显示系统本地时间。但注意,这个时间是 FFmpeg 开始处理时的时间,不是视频本身的录制时间。

如果想显示视频的时间进度(从 0 开始),用 %{pts}

ffmpeg -i input.mp4 -vf "drawtext=text='%{pts\:hms}':fontsize=20:fontcolor=white:x=10:y=h-th-10" output.mp4

%{pts:hms} 会把时间戳格式化成 HH:MM:SS 格式。比如视频播放到 1 分 30 秒时,显示 00:01:30

你想想看,如果做课程录制,加上时间水印,学员回看时就知道具体时间点,多方便。

更复杂的用法,比如自定义时间格式:

ffmpeg -i input.mp4 -vf "drawtext=text='%{localtime\:%Y-%m-%d %H\\:%M\\:%S}':fontsize=18:fontcolor=yellow:x=10:y=10" output.mp4

这里用 \\: 转义冒号,因为 FFmpeg 的文本解析中冒号有特殊含义。

21.4 组合使用:图片+文字+时间一起上

实际项目中,往往需要同时叠加多个水印。比如左上角放 Logo,右下角显示时间,底部再跑一行滚动字幕。

用 filter_complex 可以串联多个滤镜:

ffmpeg -i input.mp4 -i logo.png -filter_complex \
"[0:v][1:v]overlay=10:10[bg]; \
 [bg]drawtext=text='蓝海资料':fontcolor=white:fontsize=20:x=10:y=50[bg2]; \
 [bg2]drawtext=text='%{localtime}':fontcolor=yellow:fontsize=16:x=w-tw-10:y=10" \
output.mp4

这里用 [bg][bg2] 作为中间标签,把处理结果一步步传递下去。说白了就是流水线作业。

核心思路: 每个滤镜处理完,输出一个带标签的流,下一个滤镜用这个标签作为输入。这样就能无限叠加。

21.5 知识体系图

下面这张图,帮你理清 overlay 水印的核心逻辑:

overlay 水印叠加核心流程 输入视频流 选择水印类型 图片 | 文字 | 时间 位置计算 相对坐标/变量 overlay/drawtext 是否组合多个水印? 是 → 继续叠加 | 否 → 输出 输出最终视频 核心原则:先选类型 → 算位置 → 执行滤镜 → 判断是否继续叠加

21.6 避坑指南与实用技巧

做水印叠加,有几个坑我不得不提:

  • 字体找不到: 用 drawtext 时,如果字体路径不对,FFmpeg 会报错。建议先用 fc-list 查看系统可用字体。
  • 性能问题: 叠加多个水印会消耗更多 CPU。如果只是加一个静态图片水印,用 -vf-filter_complex 更轻量。
  • 透明背景: 图片水印最好用 PNG 格式,支持透明通道。JPG 会有白色背景,很难看。
  • 时间水印的时区: %{localtime} 用的是系统时区。如果视频是在不同时区录制的,记得先设置 TZ 环境变量。
我的小技巧: 调试水印位置时,先用一张小尺寸视频快速测试,别直接处理大文件。等位置调好了,再上全分辨率。这样省时间。

好了,水印叠加的内容就这些。从图片到文字,再到动态时间,你都能用 overlay 和 drawtext 搞定。下次遇到加 Logo 或者打时间戳的需求,直接上命令就行。

公众号:蓝海资料掘金营,微信deep3321