将video渲染到canvas需确保视频就绪、分辨率匹配、帧率稳定及跨域合规:监听loadedmetadata/canplay事件,用video.videoWidth/Height设canvas尺寸,requestAnimationFrame逐帧绘制,并配置crossorigin与服务端CORS响应。

确保视频已就绪再绘制
视频还没加载完就调 drawImage,大概率得到黑帧或空白。必须等浏览器确认视频元数据可用、帧可读取:
- 监听 loadedmetadata 事件:获取视频原始宽高(
video.videoWidth/video.videoHeight) - 更稳妥的是等 canplay 或 loadeddata,表示首帧已解码完成
- 如果是摄像头流(
getUserMedia),需等srcObject绑定后触发play事件再开始绘制
画布尺寸要匹配视频真实分辨率
用 video.clientWidth 或 CSS 设置的宽高去设 canvas,容易因缩放导致拉伸、模糊或裁切。正确做法是:
- 优先采用
video.videoWidth和video.videoHeight设置 canvas 的width和height属性(注意:这是 DOM 属性,不是 CSS 样式) - 若需适配容器尺寸,手动计算缩放比:
const scale = Math.min(containerWidth / video.videoWidth, containerHeight / video.videoHeight),再传入drawImage的目标区域参数 - 避免只改 CSS 宽高——那只是拉伸画布显示,不提升像素精度
用 requestAnimationFrame 稳定逐帧捕获
不要用 setInterval 定时调用 drawImage,它与屏幕刷新不同步,易丢帧或卡顿:
- 用
requestAnimationFrame循环绘制,自然贴合浏览器刷新节奏 - 在回调函数里先检查
video.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA,确保当前帧有效 - 如需控制帧率(比如只要每秒 15 帧),可加时间戳判断,跳过部分调用
跨域视频必须配好 CORS
从 CDN 或其他域名加载的视频,若服务端没返回 Access-Control-Allow-Origin 头,canvas 会被污染,后续 toDataURL 或 getImageData 就会失败:
-
<video crossorigin="anonymous">是前端必要设置 - 但仅加这个不够——服务端必须实际响应带
Access-Control-Allow-Origin: *(或指定域名) - 污染后无法恢复,只能换源或服务端修复


















