浏览器不解析文件头猜编码,只按type匹配;省略type时Chrome或可碰巧播MP3,但Safari(尤其iOS)直接跳过source,导致duration为NaN、canplay不触发、控件灰显。

为什么只写 src 属性大概率播不出来
浏览器不会解包音频文件去猜编码,它只认 type 声明。省略 type 时,Chrome 可能碰巧加载 MP3,但 Safari(尤其 iOS)直接跳过整个 <source>,导致 duration 为 NaN、canplay 不触发、控制条灰掉。
常见静默失败现象:
- <source src="a.mp3"> → iOS Safari 控制台无报错,但没声音、没加载进度
- 多个 <source> 都没写 type → 浏览器逐个发 404 请求,直到超时才放弃
- 每个
<source>必须带type,MP3 写type="audio/mpeg",不是audio/mp3 - OGG 必须精确到编码:
type="audio/ogg; codecs=opus",仅写audio/ogg在 Chrome 中可能返回空字符串 - 验证方式:控制台执行
Audio.canPlayType('audio/ogg; codecs="opus"'),返回"probably"才算稳
<source> 的顺序怎么排才不白写
浏览器按 DOM 顺序调用 canPlayType(),一旦返回 "probably" 或 "maybe" 就立刻加载,不再往后看。顺序错了,兼容性方案等于没写。
- 推荐 fallback 顺序:
<source src="a.opus" type="audio/ogg; codecs=opus">→<source src="a.m4a" type="audio/mp4; codecs=aac">→<source src="a.mp3" type="audio/mpeg"> - 别把
.wav放第一位:16-bit PCM 文件体积大,Firefox 虽能解码,但用户得等完整下载才出声 - Safari 17.5 不认
audio/ogg,哪怕你写的是.opus文件,也必须声明codecs=opus,否则跳过 - 删掉没声明
type的<source>:它可能绕过 MIME 检查直接试播,结果报MEDIA_ERR_DECODE却找不到原因
服务端配置不到位,前端写成诗也没用
90% 的“静音”“卡 loading”“拖不动进度条”,问题不在 HTML,而在 Nginx/Apache 没配对 MIME、Range 请求或 CORS。
- Nginx 必须显式加
add_type audio/ogg .opus;、add_type audio/mp4 .m4a;、add_type audio/mpeg .mp3; - 响应头
Content-Type必须和type值完全一致,比如audio/ogg; codecs=opus对应Content-Type: audio/ogg,不能是application/octet-stream - 跨域音频必须带
Access-Control-Allow-Origin: *,否则 Safari 直接拒绝解码,连错误都不抛 - 必须支持
Range请求,否则 Safari/iOS 无法分片加载,拖动失效、currentTime设置无效
JS 播放时怎么捕获真实失败原因
用户点一下 play() 不等于真能响。现代浏览器会因格式不支持、网络中断、自动播放策略等原因拒绝,必须主动捕获。
立即学习“前端免费学习笔记(深入)”;
- 用
audio.play().catch(e => { })捕获三类关键错误:NotAllowedError(自动播放被拒)、NotSupportedError(格式不支持)、AbortError(网络中断) - 监听
error事件可定位具体哪个<source>失败:audio.addEventListener('error', () => console.log(audio.error?.code)),code === 4表示所有源都不可用 - 别依赖
canplay判断就绪——它在元数据加载完就触发,音频体可能还没到;canplaythrough更可靠,但延迟明显,适合非首帧敏感场景 - 设置播放位置要分平台:iOS 必须等
canplay后再设currentTime,Android 可以先设再play()
真正卡住的往往不是写法,而是服务端 Content-Type 和 Range 支持没对上,或者 type 声明漏了 codecs= 这一段。这些地方一错,整个多格式链就断在第一环。



















