真正起作用的视频水印必须用Canvas实时绘制到每一帧像素中,同步video显示尺寸、动态重绘、右下角锚定定位、显式字体设置、globalAlpha控制透明度,并用requestAnimationFrame节流优化;它仅作视觉提示,无法替代服务端加密或DRM。

真正起作用的视频水印,必须把文字实时画进每一帧像素里,而不是用 CSS 叠加一层遮罩。Canvas 是目前唯一能在截图、录屏、全屏播放时都保持可见的前端方案。
同步尺寸与动态重绘
canvas 的宽高必须严格匹配 video 元素当前显示尺寸(video.clientWidth / clientHeight),不能用原始分辨率(video.videoWidth / videoHeight),否则缩放或横竖屏切换后水印会错位甚至跑出画面。
- 每次绘制前必须调用 ctx.clearRect(0, 0, canvas.width, canvas.height),否则残留上一帧内容,出现拖影
- drawImage(video, ...) 和 fillText() 必须在同一次绘制循环内完成,且文字不能只画一次——它要随每一帧刷新
- 监听 window.resize 和 video 的 resize 事件(如 iOS Safari 触发的 video 尺寸变化),及时更新 canvas 尺寸
文字定位与样式控制
右下角锚定是最稳妥的定位方式:坐标设为 canvas.width - 20 和 canvas.height - 20,配合 textAlign = 'right' 与 textBaseline = 'bottom',文字边缘精准贴合角落,旋转或全屏也不易溢出。
- 字体必须显式声明大小,例如 ctx.font = 'bold 24px sans-serif';不写字号会回退到极小默认值
- 透明度用 ctx.globalAlpha = 0.3 控制,范围建议 0.2–0.4;别用 CSS 的 opacity,那会让整块 canvas 变淡
- iOS Safari 对
textBaseline = 'alphabetic'渲染偏高,统一设为'bottom'或'middle'更可靠
性能优化与节流策略
高频重绘容易引发卡顿,尤其在低端设备或多标签页场景下。requestAnimationFrame 是比 setInterval 更准、更省资源的驱动方式。
立即学习“前端免费学习笔记(深入)”;
- 文字内容不变时,可加入简单节流逻辑:300ms 内跳过重复 fillText 调用,降低 CPU 开销
- 避免在 draw 函数中频繁创建对象或字符串拼接;水印文本、字体等可提前缓存
- 若需斜向平铺水印,务必用 ctx.save() → ctx.translate() → ctx.rotate() → 绘制 → ctx.restore(),防止坐标系永久偏移
兼容性与限制提醒
纯前端水印本质是视觉增强,不是加密保护。它无法阻止用户通过 DevTools 提取原始 video src、用录屏软件捕获画面,或下载未加水印的源文件。
- 所有绘制逻辑运行在浏览器内存中,canvas 输出仍是普通图像数据,可被截图工具直接复制
- 移动端全屏播放时,原生播放器 UI 可能遮挡非 canvas 方案(如伪元素、img 叠层),而 canvas 绘制的内容始终与视频帧同层
- 如需更强防泄密能力,必须结合服务端预处理(如 FFmpeg 嵌入)或 DRM 方案,前端 canvas 水印仅作辅助提示



















