可通过Canvas结合WebRTC和face-api.js实现实时人脸遮罩装饰:获取视频流→逐帧绘制到canvas→检测关键点→动态绘制随脸移动的装饰图形。

可以通过 Canvas 结合 WebRTC 和 face-api.js(或类似轻量人脸检测库)实现实时视频帧捕捉与人脸遮罩装饰。核心在于:获取视频流 → 每帧绘制到 canvas → 检测人脸关键点 → 绘制装饰图形(如口罩、眼镜、猫耳)并随人脸动态跟随。
1. 获取并显示实时视频流
使用 navigator.mediaDevices.getUserMedia 获取摄像头视频流,绑定到 <video> 元素,并设置 playsinline autoplay muted 以适配移动端:
- 确保 video 元素设置了固定宽高(如
width="640" height="480"),避免缩放导致坐标错位 - 将 video 的
crossOrigin="anonymous"属性设为匿名,防止后续 canvas 绘制时因跨域被污染(尤其在 HTTPS 页面加载 HTTP 视频源时) - 隐藏 video 标签本身(
display: none),仅用它作为图像源,所有渲染走 canvas
2. 定期捕获帧并送入人脸检测
用 requestAnimationFrame 替代 setInterval,保证帧率稳定(通常 30–60fps):
- 在动画循环中调用
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)把当前视频帧绘制到离屏 canvas(或主 canvas) - 对绘制后的 canvas 执行
ctx.getImageData(0, 0, width, height)获取像素数据,传给检测模型(如 face-api.js 的detectSingleFace或detectAllFaces) - 为性能考虑,可降采样处理(如只检测 320×240 分辨率的帧),再将结果坐标按比例映射回原始 canvas 尺寸
3. 基于关键点动态绘制遮罩装饰
检测返回的人脸对象通常包含 landmarks(68 或 5 点关键点),据此计算装饰物的位置、旋转和缩放:
立即学习“前端免费学习笔记(深入)”;
- 例如画“口罩”:取鼻底点(noseBottom)、左/右嘴角(mouthLeft/mouthRight),计算宽度与倾斜角,用
ctx.save()+ctx.translate()+ctx.rotate()+ctx.drawImage()绘制贴合的 PNG 图片 - 画“眼镜”:用左右眼中心点确定中心位置,两眼间距决定宽度,眼眶朝向微调旋转角度
- 所有装饰建议预加载为
Image对象,避免每帧重复创建;使用ctx.globalCompositeOperation = 'source-over'保持正常叠加
4. 优化与兼容性注意点
实际部署中常见瓶颈不在绘图,而在检测速度和内存管理:
- face-api.js 默认使用 Tiny Face Detector(快但精度略低),适合实时场景;避免在低端安卓机启用 SSD Mobilenet(太重)
- 检测结果缓存 2–3 帧,用插值平滑关键点跳变(如加权平均上一帧位置),减少抖动
- iOS Safari 需特别注意:必须在用户手势触发后(如点击按钮)才能调用
getUserMedia,且部分旧版本不支持 OffscreenCanvas,应降级使用主线程 canvas - 导出装饰后视频?需用
MediaRecorder录制 canvas 的captureStream()输出流,而非直接录 video 元素
不复杂但容易忽略:所有 canvas 绘制前务必检查 video 是否已加载元数据(监听 loadedmetadata 事件),否则第一帧可能为空白;装饰图片推荐用透明背景 PNG,尺寸按设计稿 2x 导出适配高清屏。



















