GJ 站长论坛・社区规则,请知晓

HTML 的 `<source>` 在 video/audio 中怎么用?

juming
juming 初级会员超兽战士
发布于 2026-10-09 20:54 ·5 浏览 ·0 回复

结论:<source> 是 <video>/<audio> 的「格式候选清单」,浏览器按文档顺序从上往下挑,选第一个 type 能解码且 src 能加载的源;它本身是空元素,不写 </source>,也不承载任何降级文案。

<source> 在 video/audio 里的作用是什么?

它的唯一职责是给父级媒体元素提供备用源地址,实现格式回退。父元素自己不写 src,而是把多个 <source> 作为子元素列出来,浏览器执行「资源选择算法」:逐个检查 <source>,跳过 type 明显不支持的,对剩下的按顺序尝试加载,成功一个就停止。

这意味着一件事:顺序即优先级。你把 mp4 放第一位,浏览器就会优先请求 mp4,后面的 WebM 只有在 mp4 失败时才会被考虑。想让带宽小的用户优先拿 AV1/WebM,就得把它写到前面。

结论:<source> 不解决兼容性,它只是给浏览器提供「选择权」,真正决定能不能播的是 type 里声明的 MIME 类型和 codecs 参数。

<source> 的代码怎么写才标准?

最小可用写法如下,注意 <source> 没有闭合标签,降级文案放在所有 <source> 之后:

<video controls width="640" poster="cover.jpg" preload="metadata">
  <source src="movie.webm" type="video/webm; codecs=vp9,opus">
  <source src="movie.mp4"  type="video/mp4; codecs=avc1.42E01E,mp4a.40.2">
  你的浏览器不支持 HTML5 视频,<a href="movie.mp4">点此下载</a>。
</video>
  • src:媒体地址,支持相对路径,也支持 #t=10,20 这种媒体片段,表示只播 10~20 秒。
  • type:MIME 类型,分号后可以带 codecs,值用双引号包住,大小写不敏感。
  • preload、controls、poster、muted 都是 <video> 自己的属性,写在 <source> 上无效。

结论:codecs 参数能把「容器对但编码不对」的情况提前拦掉,比如同是 mp4,H.265 在部分 Chrome 上就播不了。

为什么 type 属性强烈建议写?

不写 type,浏览器就必须真的去发请求、下载头部、嗅探容器,才能判断能不能播;多个候选源就会产生多次无效请求。写上 type 后,浏览器可以先在本地用 canPlayType() 判断,返回 "probably" 或 "maybe" 才去请求,返回空字符串直接跳过。

自测一下当前环境支持什么,控制台一行就够:

document.createElement('video').canPlayType('video/mp4; codecs="avc1.42E01E"')
// Chrome/Edge/Safari 返回 "probably",不支持的编码返回 ""

结论:type 是性能优化手段,不是可选装饰,多源场景下省掉的是实打实的无效流量。

用 JS 动态切换清晰度或格式,为什么改了 src 没反应?

因为源选择算法只在特定时刻运行一次。直接改 source.src 或往 <video> 里 append 新 <source>,浏览器不会重新选择。正确做法是改完之后显式调用父元素的 load():

const video = document.querySelector('video');
video.querySelector('source').src = 'movie-1080p.mp4';
video.load();          // 必须调用,否则不生效
video.play();

如果只是单一源,更简单的做法是直接给 <video src="..."> 赋值再调 load(),而不是维护 <source> 列表。

结论:切换源 = 改属性 + load(),缺一不可。

加载失败怎么拿到错误?

监听 <video>/<audio> 自身的 error 事件,再读 video.error.code。code === 4(MEDIA_ERR_SRC_NOT_SUPPORTED)代表所有候选源都不可用或不支持。

video.addEventListener('error', () => {
  if (video.error?.code === 4) showFallback();
});

注意 <source> 上的 error 事件在各浏览器行为不一致,不要依赖它做逐源失败统计。

<source> 和 <track>、<picture> 里的 source 区别在哪?

同一个标签名,三种用途,别混淆:

场景关键属性作用
<video>/<audio>src、type格式回退
<picture>srcset、media、sizes响应式图片
字幕用 <track>,不是 <source>字幕/章节

结论:字幕、章节、描述一律走 <track kind="subtitles" srclang="zh" src="zh.vtt">,<source> 不承担这个职责。

常见误区

❌ 写 <source src="a.mp4"></source> 或把「浏览器不支持」文案塞进 <source> 里 → 正确:<source> 是空元素,降级内容写在所有 <source> 之后、</video> 之前。
❌ 多个 <source> 只写 src 不写 type → 正确:每个源都补上 type="video/mp4; codecs=...",让浏览器提前跳过不支持项。
❌ 把 preload="none" 写在 <source> 上做懒加载 → 正确:preload 是 <video> 属性;真正的滚动懒加载用 IntersectionObserver 在进入视口后再注入 <source> 并 load()。
❌ 用 JS 改完 source.src 直接 play() → 正确:先调 video.load() 重置源选择,再 play()。
❌ 在 <source> 上监听 error 判断哪个格式失败 → 正确:监听 <video> 的 error,读 video.error.code === 4。
❌ 用 <source> 挂中文字幕 → 正确:用 <track kind="subtitles" srclang="zh" src="zh.vtt" default>。

一句话收尾:<source> 管的是「候选与回退」,按优先级排列、每个都写清 type,改源时记得 load(),字幕和降级文案各有各的位置。

版权声明:本文来自 GJ站长论坛《HTML 的 `<source>` 在 video/audio 中怎么用?》
原文链接:https://www.gj0.com/thread-1254.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~