type属性必须严格匹配服务器content-type响应头,否则浏览器静默跳过;type决定加载顺序与fallback行为,需按兼容性排序并配合media实现分辨率分流,验证需通过network面板确认请求与响应头一致性。

type属性不写或写错,浏览器直接跳过整个
浏览器不是靠文件后缀(比如 .mp4)判断格式,而是严格比对 type 值和服务器返回的 Content-Type 响应头。哪怕只差一个字符——比如把 audio/mpeg 写成 audio/mp3,Safari 就可能静默跳过该 <source></source>,转而试下一个;如果全都不匹配,视频区域就空白,控制台也不报错。
常见错误现象:
-
type="video/mp4"写成type="mp4"或type="video/.mp4" - WebM 文件用了
type="video/webm",但实际编码是 AV1 + Opus,部分 Chrome 版本要求显式写type="video/webm; codecs="av01.0.05M.08, opus"" - 本地开发用
file://协议时,type被完全忽略,所有<source></source>失效——必须起 HTTP 服务(如python -m http.server)才能验证
type决定加载顺序和 fallback 行为
浏览器按 <source></source> 出现顺序逐个尝试,一旦遇到 type 匹配且资源可解码的,就立即加载并停止后续检查。这意味着:type 不仅是“声明”,更是加载策略的开关。
实操建议:
- 把兼容性最广的格式放最前:iOS/Safari 只认
video/mp4(H.264 + AAC),所以<source src="vid.mp4" type="video/mp4"></source>应排第一 - WebM 推荐用 VP9 + Opus,写成
type="video/webm; codecs="vp9, opus"",但注意 iOS 全系不支持 WebM,它永远不会被选中 - 不要给多个
<source></source>设置相同type和media,行为未定义,多数浏览器取第一个
type配合media实现设备级分辨率分流
media 属性只影响初始匹配是否参与筛选,不控制播放中切换。真正起作用的是 type + media 的组合是否让某个 <source></source> 在首次加载时被选中。
例如:
<video controls><source src="vid-480.mp4" type="video/mp4" media="(max-width: 767px)"><source src="vid-1080.mp4" type="video/mp4" media="(min-width: 768px)"></source></source></video>
这里两个 <source></source> 的 type 相同,但 media 互斥,确保小屏设备只加载低清版。但要注意:
-
media查询在页面渲染时计算一次,窗口 resize 不会触发重新选择源 - 如果用户从桌面切到移动端(或反之),已加载的视频不会自动切换分辨率
- 想实现播放中动态切换,必须用 JS 驱动的播放器(如
hls.js),<source></source>无法胜任
验证type是否生效的唯一可靠方式
打开 DevTools → Network 标签页,播放视频,观察实际发出的请求 URL 和响应头中的 Content-Type 是否与你写的 type 一致。这是唯一能确认浏览器是否“看到并接受了”该 <source></source> 的方法。
容易被忽略的点:
-
<source></source>上设置width/height无效——这些属性只对父级<video></video>生效 - 路径 404 或跨域失败时,浏览器不会报错,也不会显示
<video></video>内的 fallback 文本,只会留一个空控件 -
<source></source>必须是<video></video>的直接子元素,嵌套在<div> 里会导致 <code>DOMException: The element has no supported sources











