HTML5视频水印需用canvas实时绘制:监听播放事件,通过requestAnimationFrame每帧drawImage视频帧并fillText添加文字,同步canvas尺寸至video.clientWidth/clientHeight,设globalAlpha=0.3防干扰,注意iOS字体渲染与性能优化。

用 canvas 实时绘制文字水印到视频画面上
HTML5 本身不支持直接给 添加文字水印,必须借助 canvas 捕获帧并叠加。核心思路是监听 timeupdate 或用 requestAnimationFrame 定期将视频当前帧绘制到 canvas,再用 fillText() 写文字。
- 水印文字需在每次重绘时手动绘制,不能只画一次
- 推荐用
requestAnimationFrame而非setInterval,避免帧率抖动和丢帧 - 注意 canvas 尺寸必须与视频显示尺寸一致(不是原始分辨率),否则水印错位;可用
video.videoWidth/video.videoHeight获取原始尺寸,但绘制时应按video.clientWidth/video.clientHeight缩放计算坐标 - 文字透明度靠
ctx.globalAlpha控制,建议设为0.2–0.4,太浓影响观看,太淡易被裁掉
避免水印被右键保存或录屏绕过的关键限制
纯前端水印本质是“视觉欺骗”,无法阻止用户截图、录屏或通过 DevTools 提取原始视频流。所有叠加逻辑都在浏览器内存中运行,canvas 输出的仍是可复制图像。
- 禁用右键菜单(
oncontextmenu="return false")只能防误触,不影响开发者工具或系统级录屏 - 不要依赖
controlsList="nodownload"阻止下载——它仅隐藏下载按钮,资源 URL 仍可在 Network 面板找到 - 真正防泄漏需服务端配合:如 HLS 分片加密、动态 token 鉴权、或使用 DRM(Widevine/PlayReady),但这些与前端水印无关
- 若只需防普通用户“顺手截屏”,文字水印+低透明度+倾斜排布(用
ctx.rotate())能显著提升识别成本
移动端 Safari 上文字模糊或不显示的修复方法
iOS Safari 对 canvas 文字渲染有特殊限制:当 canvas 未显式设置 width/height 属性(而非仅 CSS 设置),或字体加载未完成时,fillText() 可能失效或糊成一团。
- 务必用 JS 设置
canvas.width和canvas.height(像素值),不能只靠 CSS 缩放 - 避免使用未声明的字体名,优先用系统安全字体如
'-apple-system, BlinkMacSystemFont, sans-serif' - 若需自定义字体,用
@font-face加载后,调用document.fonts.load()确保就绪再开始绘制 - 部分 iOS 版本对
globalAlpha+fillText组合有渲染 bug,可改用带阴影的文字:ctx.shadowColor = 'rgba(0,0,0,0.5)'; ctx.shadowBlur = 4;
性能敏感场景下减少重绘开销的优化点
高频调用 drawImage() + fillText() 在低端设备或高分辨率视频上容易掉帧,尤其当视频宽高超过 1280×720。
立即学习“前端免费学习笔记(深入)”;
- 不必每帧都画水印:可降频至每 200–300ms 绘制一次(用
performance.now()记录上次绘制时间) - 水印区域小且固定时,可预先画好一张含水印的透明 PNG,用
ctx.drawImage(watermarkImg, x, y)贴图,比实时文字快 3–5 倍 - 关闭抗锯齿:
ctx.imageSmoothingEnabled = false,对文字影响不大,但提升 canvas 绘制速度 - 如果视频暂停,停止
requestAnimationFrame循环;播放时再恢复,避免后台空转耗电
实际项目里最容易被忽略的是 canvas 尺寸同步时机——很多同学在页面加载完就设死 canvas 大小,却没监听 video 的 loadedmetadata 和窗口 resize,导致水印在视频刚加载或横竖屏切换时严重偏移。











