如何用FFmpeg给视频加水印?
drawtext 添加文本水印
drawtext 是 FFmpeg 内置的文本绘制过滤器,适合添加版权声明、时间戳等文字水印。它依赖 FreeType 库渲染字体,需要系统预装字体文件。
基本用法:
bashffmpeg -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 开启,配合 boxcolor 和 boxborderw |
居中对齐:用表达式 x=(w-text_w)/2:y=(h-text_h)/2 让水印自动居中,其中 w/h 是视频宽高,text_w/text_h 是文本尺寸。
半透明背景框:
bashdrawtext=fontfile=...:text='Watermark':x=10:y=10:fontsize=24:fontcolor=white:box=1:boxcolor=black@0.5:boxborderw=5
overlay 添加图片水印
overlay 过滤器将一张图片叠加到视频流上,适合 Logo、二维码等图形水印。水印图片建议用 PNG 格式,保留 Alpha 通道以实现透明效果。
基本用法:
bashffmpeg -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:
bashffmpeg -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 参数:
bashffmpeg -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 中用逗号链式串联多个过滤器:
bashffmpeg -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_w、main_h、overlay_w、overlay_h 这些动态变量计算相对位置。
如果水印压根没出现,先排查:
- 字体文件路径是否正确——用
fc-list | grep DejaVu确认系统字体 - PNG 是否有 Alpha 通道——用
ffprobe logo.png查看pix_fmt是否为rgba - filter_complex 语法是否正确——引号嵌套容易出错,建议先加
-t 5只处理前 5 秒快速验证
bashffmpeg -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_qsv或overlay_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)水印覆盖整个画面,大幅提高防盗能力:
bashffmpeg -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*50 和 t*30),配合 mod 取模实现循环平铺效果,防止裁剪去水印。
关键要点总结
- 文本水印用
drawtext,图片水印用overlay,混合使用时注意过滤器链的标签传递顺序 - 坐标务必用
main_w/main_h/overlay_w/overlay_h动态变量,不要写死像素值 - 调试时加
-t 5只处理前几秒,快速验证效果后再全量处理 - PNG 水印保留 Alpha 通道才能实现透明效果
- 性能优化优先级:GPU 加速 > 多线程 > CRF 调整