浏览器只认第一个能解码成功的,非“选最优”而是“选首个可用”;mp4(h.264)必须排第一,webm次之,type须精确声明编码如video/mp4; codecs="avc1.42e01e, mp4a.40.2",且服务端content-type必须严格匹配。

浏览器只认第一个能解码成功的 <source></source>,不是挑“最好”的,而是挑“第一个能用的”——顺序写错、type 写宽泛、服务端 Content-Type 不匹配,都会让降级链直接断裂。
video/source 的顺序必须是 MP4(H.264) → WebM(VP9) → 其他
这不是偏好问题,而是兼容性事实:iOS Safari(包括所有 WebKit WebView)强制要求第一个可播放的 <source></source> 是 H.264 编码的 MP4,否则可能静音、禁止自动播放,甚至抛 NotAllowedError。WebM 放第一位?Safari 直接跳过,且不触发 fallback,整个 <video></video> 可能卡在 loading 状态。
- MP4 必须用 H.264 Baseline 或 Main Profile + AAC-LC,FFmpeg 导出时加
-profile:v baseline -level 3.0 -c:a aac - WebM 推荐用
type="video/webm",不带codecs参数更稳妥;VP9 的 codec 字符串(如vp09.00.10.08)大小写、点号、版本号稍有偏差,Safari 就返回空字符串 - Ogg(Theora) 已基本淘汰,现代项目可省略;AV1 MP4(
type="video/mp4; codecs="av01.0.05M.08"")仅 Chrome/Firefox 支持,必须放在最后,且 Safari 16+ 才识别
type 属性必须精确,不能只写 MIME 类型
type 不是装饰,是浏览器跳过不支持格式的唯一依据。写成 type="video/mp4" 看似省事,实则危险:浏览器无法判断编码是否支持,会发一次请求再解码失败,浪费带宽、延长首帧时间,还可能卡住。
- 正确写法:
type="video/mp4; codecs="avc1.42E01E, mp4a.40.2""(H.264 Baseline + AAC-LC) - 错误写法:
type="video/mpeg"(对应 .mpeg 文件)、type="mp4"(缺video/前缀)、type="video/mp4; codecs="h264""(标准写法是avc1) - 服务器响应头
Content-Type必须和type值严格一致,比如.webm文件返回text/plain,Safari 会静默跳过
别信文件后缀,要验证实际编码和 HTTP 响应
一个叫 vid.mp4 的文件,可能是 AV1 编码;一个 vid.webm 文件,服务器可能返回 application/octet-stream。这些都会导致 <source></source> 被忽略,而 DevTools Network 面板里只看到一个请求、没报错,容易误判为“降级生效”。
- 用
ffprobe vid.mp4检查真实编码:Stream #0:0: Video: h264 (Baseline)才算合规 - 用
curl -I https://example.com/vid.mp4确认响应头:Content-Type: video/mp4 - 在 Safari 私密模式下,
canPlayType()可能返回空字符串,但不代表真不支持——必须让浏览器实际加载第一条<source></source>,监听stalled或error事件二次验证
兜底文字和 JS error 监听不能少
<source></source> 自动回退很可靠,但网络中断、文件损坏、解码失败等极端情况仍会发生。纯靠 HTML 结构,用户可能面对黑屏或 loading 圈转半天。
- 所有
<source></source>后、前,必须写简明降级提示,如:<p>您的浏览器不支持视频播放</p>,兼顾屏幕阅读器与老设备 - 绑定
error事件:当所有<source></source>都失败时,可提示用户、上报错误或加载 GIF 备用图 - 避免动态插入
<source></source>:JS 创建的<source></source>可能绕过浏览器原生探测逻辑,优先用静态 HTML
最易被忽略的其实是服务端配置——CDN 或 Nginx 没透传 Accept 请求头,后端就无法根据 Accept: image/avif,image/webp 返回对应格式,导致 type="image/avif" 的 <source></source> 静默失效。降级不是写几行 HTML 就完事,它是一条从编码、打包、HTTP 响应到前端声明的完整链路。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











