安卓 WebView 会跳过后续 <source> 标签,因其仅识别第一个 src 且严格校验 type 与响应头 Content-Type 的完全匹配(大小写敏感、编码精确),失败时静默不触发事件,唯一可靠兜底是直接使用 <video src="..."> 并辅以 JS 探测降级。

为什么安卓 WebView 会跳过后续 <source> 标签
部分安卓 WebView(尤其 Android 4.4–6.x 系统内置浏览器、旧版 Samsung Internet)根本不会触发 canplay 或 loadeddata,也不按顺序尝试 <source>;它只认第一个 src,且对 type 属性极不敏感——哪怕你写了 type="video/mp4",只要响应头 Content-Type 不是精确匹配,就直接静默失败,不发后续请求。
<source> 的 type 必须和响应头完全一致
安卓 WebView 比桌面 Chrome 更严苛:它不“猜”,只比对。常见踩坑点包括:
-
type="video/mp4"但服务器返回Content-Type: video/MP4(大小写敏感)→ 跳过 -
type="audio/mpeg"写成audio/mp3→ 安卓直接忽略,iOS 也失败 - MP4 文件实际编码是 AV1,却配
type="video/mp4; codecs="avc1.42E01E, mp4a.40.2"→ 解码失败,不报错,也不试下一个 - 用
curl -I https://xxx.mp4验证响应头,确保是Content-Type: video/mp4
安卓上 fallback 到 src 属性是唯一可靠兜底
当 <source> 在低版本安卓中集体失效时,<video src="..."> 反而更稳——它绕过 type 匹配逻辑,直接发起请求。实操建议:
- 把兼容性最强的 MP4 放在
<video>的src属性里:<video src="clip-h264.mp4" controls> - 再叠一层
<source>供现代浏览器使用,顺序不变:<source src="clip.mp4" type="video/mp4"> - 不要让
src和<source>共存于同一<video>——规范要求互斥,但安卓 WebView 实现混乱,有的版本优先用src,有的忽略src只看<source>,所以统一用src+ 多<source>是最兼容写法
检测并动态降级的 JS 补丁必须加
纯 HTML 无法覆盖安卓 WebView 的行为差异,必须靠 JS 主动探测:
立即学习“前端免费学习笔记(深入)”;
- 监听
video.error事件,若触发且video.networkState === 3(NETWORK_NO_SOURCE),说明所有<source>都被跳过 - 检查
video.canPlayType("video/mp4")返回值:空字符串或""表示不支持,此时手动设video.src = "fallback.mp4"并调用video.load() - 避免在
DOMContentLoaded就调play(),低版本安卓需要等loadedmetadata后才能操作currentTime或play()
真正麻烦的不是格式本身,而是安卓 WebView 对 HTML 规范的碎片化实现——它不报错、不提示、不加载,只沉默。验证是否生效,唯一办法是真机连 DevTools 远程调试,看 Network 面板到底发了几个请求、哪个被 abort、哪个没触发任何事件。



















