preload="metadata"仅触发一次HEAD或GET请求以获取响应头并解析moov box,不下载音视频帧;若服务端不支持Accept-Ranges或moov在文件末尾,则可能卡住、退化为全量下载或失败。

preload="metadata" 实际触发的 HTTP 请求类型
它不下载视频帧,只发一次 HEAD 或 GET 请求,目标是获取响应头(如 Content-Length、Accept-Ranges: bytes)并尝试读取容器头部(如 MP4 的 moov box)。服务端若忽略 HEAD(如某些 CDN),浏览器会降级为 GET;若返回 Accept-Ranges: none 或压根没这个头,就可能卡住或退化为下载前几 KB 甚至整个文件。
metadata 模式下真正拿到的数据内容
只解析出元数据字段,不包含任何音视频帧:
-
duration(时长)、videoWidth/videoHeight(分辨率) - 封面帧(如果
moov中含stco或stss指向关键帧,且该帧被包含在头部请求范围内) - 音轨/字幕轨道数量与基础属性(编码格式、语言标签等)
- 关键帧索引(用于拖动时快速定位,但仅当 moov 结构支持且已加载)
注意:这些值必须等 loadedmetadata 事件触发后才可用;video.readyState 初始仍为 HAVE_NOTHING,不能靠它判断。
为什么有时候 metadata 加载失败或变慢
两个硬性前提缺一不可,否则行为完全不可控:
立即学习“前端免费学习笔记(深入)”;
- 服务端必须返回
Accept-Ranges: bytes响应头,否则浏览器无法发起字节范围请求,只能硬下整个文件或前几 KB - MP4 文件必须用
ffmpeg -c copy -movflags +faststart重写,确保moovbox 在文件开头;否则浏览器得下载全部才能解析元数据,和preload="none"几乎没区别 - iOS Safari 会无视
preload设置,无论写什么,实际都按none处理——这点容易被漏掉
preload="metadata" 对流媒体(HLS/DASH)完全无效
当 src 指向 .m3u8 或通过 MediaSource 动态赋值时,preload="metadata" 不会触发任何分片请求。浏览器根本不解析 m3u8,也不提取首个 .ts 地址。所有加载逻辑由 JS 播放器(如 hls.js)接管,preload 属性被彻底绕过。
想优化首帧,得在 JS 层预热:提前 fetch m3u8、解析第一个 ts URL、手动 new Image().src 或 fetch() 预热 DNS/TCP/TLS,甚至利用缓存机制做资源预热(注意 CORS 限制)。



















