5月28日 00:03

如何用FFmpeg给视频加水印?

drawtext 添加文本水印

drawtext 是 FFmpeg 内置的文本绘制过滤器,适合添加版权声明、时间戳等文字水印。它依赖 FreeType 库渲染字体,需要系统预装字体文件。

基本用法

bash
ffmpeg -i input.mp4 -filter_complex "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='Copyright 2026':x=10:y=10:fontsize=28:fontcolor=white@0.8" -c:v libx264 -c:a copy output.mp4

核心参数

参数说明示例
fontfile字体文件绝对路径(必填)/usr/share/fonts/.../DejaVuSans.ttf
text显示文本,支持时间变量'版权所有''%{localtime\:%H\:%M\:%S}'
x / y水印左上角坐标(像素)x=10:y=10
fontsize字体大小28
fontcolor颜色 + 透明度white@0.8 表示白色 80% 不透明
box是否添加背景框1 开启,配合 boxcolorboxborderw

居中对齐:用表达式 x=(w-text_w)/2:y=(h-text_h)/2 让水印自动居中,其中 w/h 是视频宽高,text_w/text_h 是文本尺寸。

半透明背景框

bash
drawtext=fontfile=...:text='Watermark':x=10:y=10:fontsize=24:fontcolor=white:box=1:boxcolor=black@0.5:boxborderw=5

overlay 添加图片水印

overlay 过滤器将一张图片叠加到视频流上,适合 Logo、二维码等图形水印。水印图片建议用 PNG 格式,保留 Alpha 通道以实现透明效果。

基本用法

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

overlay=10:10 表示水印左上角放在视频 (10,10) 像素处。

四角定位速查

overlay 的坐标参数支持变量表达式,main_w/main_h 是视频宽高,overlay_w/overlay_h 是水印宽高:

位置overlay 参数
左上角(带 10px 边距)overlay=10:10
右上角overlay=main_w-overlay_w-10:10
右下角overlay=main_w-overlay_w-10:main_h-overlay_h-10
左下角overlay=10:main_h-overlay_h-10
正中央overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2

缩放水印尺寸:先对水印做 scale,再 overlay:

bash
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]scale=120:60[wm];[0:v][wm]overlay=10:10" output.mp4

带透明度的 overlay:如果 PNG 自带 Alpha 通道,overlay 会自动识别;如果需要额外调整透明度,用 format=auto 并配合 alpha 参数:

bash
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]format=rgba,colorchannelmixer=aa=0.5[wm];[0:v][wm]overlay=10:10" output.mp4

colorchannelmixer=aa=0.5 将水印整体透明度设为 50%。

文本 + 图片混合水印

实际项目中经常需要同时叠加 Logo 和文字。在 filter_complex 中用逗号链式串联多个过滤器:

bash
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]scale=80:40[wm]; [0:v][wm]overlay=10:10[base]; [base]drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:text='Copyright 2026':x=100:y=10:fontsize=20:fontcolor=white@0.7" -c:v libx264 -c:a copy output.mp4

注意过滤器链的顺序:先 overlay 图片,再 drawtext 文字。中间用 [base] 标签传递中间结果。

水印位置偏移或不对

最常见的原因是坐标写死成了绝对像素值,而视频分辨率发生了变化。解决办法是用 main_wmain_hoverlay_woverlay_h 这些动态变量计算相对位置。

如果水印压根没出现,先排查:

  1. 字体文件路径是否正确——用 fc-list | grep DejaVu 确认系统字体
  2. PNG 是否有 Alpha 通道——用 ffprobe logo.png 查看 pix_fmt 是否为 rgba
  3. filter_complex 语法是否正确——引号嵌套容易出错,建议先加 -t 5 只处理前 5 秒快速验证
bash
ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=10:10" -t 5 test_output.mp4

处理速度太慢怎么办

水印叠加是逐帧操作,1080p 视频单线程处理大约每秒 30-50 帧(取决于硬件)。提速方向:

  • 多线程-threads 4 启用并行编码
  • 硬件加速:Intel 集显用 -hwaccel qsv,NVIDIA 用 -hwaccel cuda,AMD 用 -hwaccel vaapi
  • CRF 调整-crf 23 是默认值,提高到 28 可以降低编码耗时(画质略降)
  • GPU overlay:部分平台支持 overlay_qsvoverlay_cuda,将叠加操作也放到 GPU 上
bash
# NVIDIA GPU 加速示例 ffmpeg -hwaccel cuda -i input.mp4 -i logo.png -filter_complex "overlay=10:10" -c:v h264_nvenc -c:a copy output.mp4

字体渲染报错找不到字体

drawtext 依赖 FreeType 库。安装方式:

bash
# Ubuntu/Debian apt-get install libfreetype6-dev # macOS brew install freetype # CentOS/RHEL yum install freetype-devel

安装后用 fc-list 列出系统可用字体,找到完整路径填入 fontfile 参数。如果仍然报错,检查 FFmpeg 编译时是否启用了 --enable-libfreetype,用 ffmpeg -filters | grep drawtext 确认过滤器可用。

平铺水印防止裁剪盗用

单点水印容易被裁剪掉。平铺(tile)水印覆盖整个画面,大幅提高防盗能力:

bash
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]scale=60:30[wm]; [0:v][wm]overlay=x='mod(t*50\,main_w)':y='mod(t*30\,main_h)':eof_action=repeat" -c:v libx264 -c:a copy output.mp4

这个命令让水印位置随时间动态移动(t*50t*30),配合 mod 取模实现循环平铺效果,防止裁剪去水印。

关键要点总结

  • 文本水印用 drawtext,图片水印用 overlay,混合使用时注意过滤器链的标签传递顺序
  • 坐标务必用 main_w/main_h/overlay_w/overlay_h 动态变量,不要写死像素值
  • 调试时加 -t 5 只处理前几秒,快速验证效果后再全量处理
  • PNG 水印保留 Alpha 通道才能实现透明效果
  • 性能优化优先级:GPU 加速 > 多线程 > CRF 调整
标签:FFmpeg