关键在于前端声明crossorigin="anonymous"且服务端精确返回access-control-allow-origin、access-control-allow-headers: range及access-control-expose-headers: content-range,否则视频虽可播放,js无法读帧、截图或获取尺寸。

要在 HTML5 中安全加载跨域视频资源,关键不是单靠 crossorigin 属性“打开开关”,而是前端声明 + 服务端响应严格匹配。否则视频可能照常播放,但 JS 读帧、截图、取尺寸都会失败。
video 标签必须显式设 crossorigin="anonymous"
这是触发浏览器走 CORS 流程的第一步,不能省略或写错:
- 推荐写法(HTML 中直接声明):
<video controls crossorigin="anonymous" src="https://cdn.example.com/vid.mp4"></video> - 动态创建时,务必在设置
src前赋值:const v = document.createElement('video'); v.crossOrigin = 'anonymous'; v.src = url; - 拼写必须小写、完整:不是
crossOrigin、crossorigin="true"或空字符串;错误写法等同于没加
服务端必须返回合法的 CORS 响应头
前端加了属性只是“申请”,服务端才是决定能否读像素的一方。仅返回 Access-Control-Allow-Origin: * 不够,尤其对视频分片(如 MP4 的 Range 请求):
- 至少需返回:
Access-Control-Allow-Origin: https://your-site.com(或*,但搭配凭据时不可用) - 必须允许
Range请求头:Access-Control-Allow-Headers: Range - 必须暴露
Content-Range响应头:Access-Control-Expose-Headers: Content-Range - Nginx 示例配置段:
location ~ \.(mp4|webm|ogg)$ { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Headers' 'Range'; add_header 'Access-Control-Expose-Headers' 'Content-Range'; }
JS 操作前要等视频真正就绪
即使配置正确,过早调用 canvas 绘制也会失败——因为元数据或首帧尚未加载完成:
- 监听
loadedmetadata(获取videoWidth/videoHeight)或canplay(可绘制首帧)事件后再操作 - 截图或取主色时,先确保视频已 seek 到目标时间点:
video.currentTime = 2.5;,再等loadeddata触发 - 绘制后立即调
canvas.toDataURL()或ctx.getImageData(),若报 “tainted canvas”,说明前面某环未达标
哪些标签支持 crossorigin?别乱加
该属性只对特定媒体元素有效,加在其他标签上纯属无效:
- 支持的标签只有:
<img>、<script></script>、<link rel="stylesheet">、<video></video>、<audio></audio> -
<iframe></iframe>、<link rel="icon">、<div> 等加了 <code>crossorigin,浏览器直接忽略 - 常见误用:给 favicon 加该属性,既不触发 CORS,也不影响加载











