原生 audio/video 标签不支持音轨切换,需动态替换 src 并重载或使用 MSE 实现真多音轨;Plyr 等库可封装处理兼容性问题。

原生 <audio> 或 <video> 标签不支持音轨切换
直接写多个 <source> 或用 <track kind="audio"> 是无效的——浏览器根本不会识别这种写法,kind="audio" 不是合法值,textTracks API 也只管字幕,对音频轨道完全无感。你看到的“多音轨”按钮,背后要么是重新加载整个文件,要么是绕过原生逻辑的手动控制。
最常用且兼容性好的做法:动态替换 src 并重载
适用于简单场景(比如几首歌、几个配音版本),不需要共享画面或保持播放进度同步:
- 每个音轨对应一个独立音频文件(如
song-zh.mp3、song-en.mp3) - 点击按钮时先调
audio.pause(),再赋值audio.src = 'xxx.mp3' - 必须紧接着调
audio.load(),否则后续play()可能失败或静音 - 等
loadedmetadata事件触发后再play(),否则duration为NaN,移动端尤其敏感 - iOS Safari 要求
play()必须在用户手势回调内执行(比如onclick里),不能异步延迟
真·多音轨切换必须用 MediaSource Extensions(MSE)
想做到“画面不动、只换声音”,就得自己管理缓冲区。这不是可选项,是标准要求:
- 创建
MediaSource实例并绑定到<video>元素 - 为视频轨道和每条音频轨道分别调
addSourceBuffer(),例如:mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"')和mediaSource.addSourceBuffer('audio/mp4; codecs="mp4a.40.2"') - 所有音轨分片的时间戳(
tfdt)必须严格对齐,否则音画不同步 - 切换时暂停当前音频
SourceBuffer的appendBuffer(),启用目标轨道的追加逻辑,保持video.currentTime不变 - Android WebView 对并发
SourceBuffer支持不稳定,需降级 fallback
不想从零写 MSE?用 Plyr 这类封装库更实际
Plyr 内部自动处理 MSE 或降级为 src 切换,省掉大量边界判断:
立即学习“前端免费学习笔记(深入)”;
- 传入音轨信息要带
srclang和label属性,例如:<track kind="subtitles" srclang="zh" label="中文">—— 注意仍是kind="subtitles",Plyr 会把它当音频元数据用 - 它能读取
navigator.language自动匹配首选音轨 - 提供统一 UI 控件(下拉菜单),但需手动注入音轨列表,不是靠 HTML 解析
- 若用外挂音频文件(非 fMP4 分片),需自行做时间同步,Plyr 不负责解码对齐



















