FFmpeg倾斜水印位置控制与独立模板平铺
FFmpeg 倾斜水印位置控制与独立模板平铺实战指南
在 FFmpeg 中,直接对文字使用 angle 或 expression_evaluation 选项极易触发 Option not found 错误。最稳妥、最高效的倾斜水印方案是:先生成带透明通道的独立倾斜水印 PNG 模板,再将该模板精准定位或平铺叠加到目标图片上。
一、 倾斜水印的位置控制(单水印定位)
1. 核心控制原理
控制倾斜水印的位置分为两步:
- 透明画布内绘制: 在
drawtext滤镜中使用x='(w-text_w)/2'与y='(h-text_h)/2'让文字在透明画布中心旋转。 - 叠加层贴回原图: 通过
overlay滤镜的x与y参数,将旋转后的透明水印贴到原图的指定位置。
2. 常用位置命令模板
右下角倾斜水印(留 50 像素边距)
ffmpeg -i b1.png -filter_complex "[0:v]format=rgba,split[bg][fg];[fg]lutrgb=r=0:g=0:b=0:a=0,drawtext=fontfile='simhei.ttf':text='baidaoya.com':fontsize=50:fontcolor=white@0.4:x='(w-text_w)/2':y='(h-text_h)/2',rotate=30*PI/180:c=none:ow=rotw(30*PI/180):oh=roth(30*PI/180)[text];[bg][text]overlay=x=main_w-overlay_w-50:y=main_h-overlay_h-50" B_bottom_right.png
左上角倾斜水印(留 50 像素边距)
ffmpeg -i b1.png -filter_complex "[0:v]format=rgba,split[bg][fg];[fg]lutrgb=r=0:g=0:b=0:a=0,drawtext=fontfile='simhei.ttf':text='baidaoya.com':fontsize=50:fontcolor=white@0.4:x='(w-text_w)/2':y='(h-text_h)/2',rotate=30*PI/180:c=none:ow=rotw(30*PI/180):oh=roth(30*PI/180)[text];[bg][text]overlay=x=50:y=50" B_top_left.png
垂直偏上(高度 25% 处,水平居中)
ffmpeg -i b1.png -filter_complex "[0:v]format=rgba,split[bg][fg];[fg]lutrgb=r=0:g=0:b=0:a=0,drawtext=fontfile='simhei.ttf':text='baidaoya.com':fontsize=50:fontcolor=white@0.4:x='(w-text_w)/2':y='(h-text_h)/2',rotate=30*PI/180:c=none:ow=rotw(30*PI/180):oh=roth(30*PI/180)[text];[bg][text]overlay=x='(main_w-overlay_w)/2':y='main_h*0.25-overlay_h/2'" B_top.png
二、 独立水印模板与平铺叠加避坑要点
采用“生成独立透明 PNG 水印模板”再叠加的方式,后续处理批量图片时无需重复计算文字渲染与旋转,处理速度大幅提升。
1. 关键避坑规则
- 防止透明区域变黑/变绿:
rotate滤镜需显式指定填充颜色c=black@0,并在输出端强制使用-pix_fmt rgba与format=rgba传递 Alpha 通道。 tile滤镜的帧数依赖:tile=layout=5x5必须捕获 25 帧 图像才能填满网格。若输入为单帧 PNG,必须通过-stream_loop -1结合fps=25,loop=loop=24:size=1补齐 25 帧,否则会导致黑屏或仅显示单个水印。- 水印尺寸与平铺密度关系: 单张水印尺寸决定平铺密度。如果水印画布过大(如 500px+),平铺后画面仅能露出 2~3 个水印;若要密集满屏,建议将水印尺寸控制在 150px ~ 250px 左右。
三、 独立模板平铺实战工作流(两步法)
第一步:生成尺寸恰当的“纯透明倾斜水印模板”
创建小画布(如 250x150),将文字居中绘制并顺时针旋转 30 度(30*PI/180),white@0.4是透明度,导出为 RGBA 透明 PNG:
ffmpeg -f lavfi -i color=c=black@0:s=250x150:d=1,format=rgba -vf "drawtext=fontfile='simhei.ttf':text='baidaoya.com':fontsize=30:fontcolor=white@0.4:x='(w-text_w)/2':y='(h-text_h)/2',rotate=30*PI/180:c=black@0:ow=rotw(30*PI/180):oh=roth(30*PI/180),format=rgba" -vframes 1 -pix_fmt rgba ss4.png
关键参数解析:
s=250x150:控制单张水印的基本尺寸与间距,尺寸越小,后续平铺越密集。rotate=...:c=black@0:指定旋转填充色为全透明黑色,防止产生黑色或绿色背景框。-pix_fmt rgba:强制输出包含 Alpha 透明通道的文件。
第二步:将水印模板平铺满任意目标图片
利用 -stream_loop 与 loop 滤镜在滤镜链内部生成 25 帧连续图像,交由 tile=layout=5x5 拼成全屏网格大图并覆盖叠加:
ffmpeg -i b1.png -stream_loop -1 -i ss4.png -filter_complex "[1:v]format=rgba,fps=25,loop=loop=24:size=1,tile=layout=5x5,format=rgba[wm];[0:v][wm]overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':shortest=1" bs10.png
关键参数解析:
-stream_loop -1 -i ss4.png:将单张 PNG 水印转化为无限循环流。fps=25,loop=loop=24:size=1:在滤镜链内部准确生成 25 帧连续水印画面。tile=layout=5x5,format=rgba:将 25 帧水印拼成 5x5 网格,并保持 RGBA 透明格式。overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':shortest=1:居中叠加至原图,并在原图处理完毕时终止。
四、 CMD 批量平铺水印脚本
生成一次 ss4.png 水印模板后,可使用 Windows CMD 批处理脚本一键为当前目录下的所有图片添加平铺水印:
for %i in (*.png *.jpg) do ffmpeg -i "%i" -stream_loop -1 -i ss4.png -filter_complex "[1:v]format=rgba,fps=25,loop=loop=24:size=1,tile=layout=5x5,format=rgba[wm];[0:v][wm]overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':shortest=1" "wm_%i"
📝 最终可用命令,直接把sy-bd2.png水印图片铺到B1.png上(两个都行)
命令 1(原版加参数):
ffmpeg -i B1.png -stream_loop -1 -i sy-bd2.png -filter_complex "[1:v]format=rgba,fps=25,loop=loop=24:size=1,tile=layout=5x5,format=rgba[wm];[0:v][wm]overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':shortest=1" bs22.png命令 2(精简版):
ffmpeg -i B1.png -stream_loop -1 -i sy-bd2.png -filter_complex "[1:v]loop=loop=24:size=1:start=0,tile=5x5[wm]; [0:v][wm]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -frames:v 1 -update 1 bs21.png这两个命令得到的效果完全一样,都能成功铺上水印。-update 后可以忽略报错,它们的区别只在于:
| 第一个命令(你之前的) | 第二个命令(我建议的) | |
|---|---|---|
| 水印效果 | ✅ 完全一样 | ✅ 完全一样 |
| 滤镜参数 | 多了 format=rgba、fps=25、shortest=1 | 更精简 |
| 输出参数 | 没有 -frames:v 1,靠 shortest=1 结束 | 明确加 -frames:v 1 |
| 报错警告 | 会报 image2 序列警告(但能生成) | 不报错 |