必须为audio标签的source元素显式声明type属性,如MP3用type="audio/mpeg"、Opus编码Ogg用type="audio/ogg; codecs=opus",并确保服务端Content-Type响应头与之严格匹配,否则浏览器静默失败。

只写 <audio src="a.mp3"> 就想全平台播放,90% 情况下会静默失败——不是代码没生效,而是浏览器直接跳过解码,连错误都不抛。
为什么不写type就等于没写
浏览器不解析文件头,只按 type 属性做 MIME 匹配。省略 type 时,Chrome 可能碰巧加载 MP3,但 Safari(尤其 iOS)会直接忽略整个 <source>,导致 duration 为 NaN、控件灰显、canplay 事件不触发。
-
type="audio/mp3"是无效写法,必须用type="audio/mpeg" - Ogg 文件若用 Opus 编码,得写
type="audio/ogg; codecs=opus",仅audio/ogg在部分 Chrome 版本返回空字符串 - 验证是否真支持:控制台执行
Audio.canPlayType('audio/ogg; codecs="opus"'),返回"probably"才算稳
多格式fallback顺序怎么排才不白忙
浏览器按 DOM 顺序调用 canPlayType(),第一个返回 "probably" 或 "maybe" 的就立刻加载,后面全跳过。顺序错了,兜底方案形同虚设。
- 推荐顺序:
<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"> - MP3 放最后?错。它兼容性最广,应放首位或次位;WAV 体积大、移动端加载慢,仅适合短提示音,别当主力 fallback
- 删掉所有没声明
type的<source>——它可能绕过 MIME 检查强行试播,结果报MEDIA_ERR_DECODE却找不到根因
服务端没配对MIME,前端写成诗也没用
即使 <source> 写得再全,如果响应头 Content-Type 是 text/plain 或缺失,浏览器就当普通文本扔掉,连解码器都不调用。
立即学习“前端免费学习笔记(深入)”;
- 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请求,否则 iOS/Safari 无法分片加载,拖动失效、currentTime设置无效
JS播放时怎么捕获真实失败原因
用户点一下 play() 不等于真能响。现代浏览器会因格式不支持、网络中断、自动播放策略等原因拒绝,必须主动捕获。
- 永远用
audio.play().catch(e => console.warn('play rejected:', e))包裹调用,别信then()成功回调 -
MEDIA_ERR_SRC_NOT_SUPPORTED(code: 4)就是格式被判死刑,说明所有<source>都被canPlayType()拒绝了 - iOS Safari 要求元素在视口内、未被
display: none或opacity: 0遮挡,否则即使点过也静音 - 别在
DOMContentLoaded或window.onload里调play(),100% 失败;必须等用户真实点击/触摸后立即调用
最容易被忽略的点:本地开发别双击 HTML 文件跑 —— file:// 协议下 Chrome/Firefox 会屏蔽音频加载,必须起本地服务器(如 python3 -m http.server);还有,preload="auto" 在 2026 年已基本弃用,Lighthouse 标为性能风险,Safari 实际忽略它。



















