仅用src属性会导致90%兼容性问题;真正落地需<source>多格式兜底+精确type与codecs声明+服务端Content-Type严格匹配+iOS首源强制H.264。

video/audio 的 src 属性本身不处理格式兼容
直接给 <video> 或 <audio> 写 src 属性,等于把解码兼容性全押给浏览器“猜”——它不会解析文件头,只按 MIME 类型匹配。Chrome 可能碰巧播 MP4,但 Safari(尤其 iOS)会静默跳过,canplay 事件不触发,duration 返回 NaN,控制台也不报错。
<source> 必须带 type + codecs,且顺序决定 fallback 路径
浏览器不是选“画质最好”的源,而是按顺序试播第一个能解码的 <source>。一旦失败(HTTP 404、MIME 不匹配、编码不支持),就继续下一个;但只要有一个成功,后续全部跳过。
-
type必须精确:写type="video/mp4"不够,得加codecs,例如type="video/mp4; codecs="avc1.42E01E, mp4a.40.2" - iOS Safari 强制要求首个可解码源是 H.264+AAC 的 MP4,否则可能静音、禁止自动播放,甚至抛
NotAllowedError - WebM 放最前适配 Chrome/Firefox,MP4 放最后兜底 Safari/Edge —— 但 iOS 完全不发 WebM 请求,写了也白写
- 服务器返回的
Content-Type响应头必须和type值严格一致,比如video/webm对应Content-Type: video/webm,返回application/octet-stream就失败
src 和 source 混用时外层 src 被完全忽略
这是调试中最容易误判的点:哪怕你写了 <video src="fallback.mp4"><source src="demo.webm" type="video/webm"></video>,浏览器也**不会**在 demo.webm 失败后回退到 fallback.mp4。外层 src 在有 <source> 时被彻底丢弃。
- 想实现 JS fallback,只能监听
error事件,再手动赋值video.src = "fallback.mp4"并调用video.load() - 不要依赖
preload="auto":iOS 会忽略,且浪费用户流量 - 本地开发用
file://协议必失败,必须走http://或https://(哪怕localhost:8080) - GitHub Pages 默认不加 CORS 响应头,跨域视频请求会被静默拦截
音频和视频的 type 值不能简写,MIME 必须标准
常见错误是把 type="audio/mpeg" 写成 type="audio/mp3",或把 type="video/mp4" 当作万能钥匙。浏览器只认 IANA 注册的标准 MIME 类型。
立即学习“前端免费学习笔记(深入)”;
- MP3 必须用
type="audio/mpeg"(不是mp3) - WAV 推荐
type="audio/wav",但注意 Safari 不支持 PCM 编码的 WAV - Ogg 音频用
type="audio/ogg",但 iOS 完全不支持,写了也无请求 - 字幕 VTT 文件必须用
<track kind="subtitles" srclang="zh" label="中文" src="captions/cn.vtt" default>,且服务器要返回text/vtt
真正落地的兼容不是靠“多塞几个格式”,而是靠 <source> 的 type + codecs 精确声明、服务端响应头严格匹配、以及对 iOS 首源强制 H.264 的硬性约束——漏掉任何一环,都可能在某个设备上变成黑屏或静音。



















