audio标签不响主因是格式fallback未配对、MIME类型不匹配或autoplay被策略拦截;须用source多格式兜底并严格匹配type与Content-Type,且iOS需用户手势授权后才能播放。

现代浏览器里,audio 标签不响,90% 不是代码写错了,而是格式 fallback 没配对、MIME 类型没对上、或 autoplay 被策略拦死——光写 <audio src="a.mp3"></audio> 在 Safari 和旧版 Firefox 里基本等于摆设。
必须用 <source> 多格式兜底,且顺序不能错
只靠一个 src 属性,浏览器不会“猜”你给的是 MP3 还是 AAC 封装,更不会主动解包验证。它只按 type 值匹配 MIME 类型,匹配失败就跳过,静默不报错。
-
mp3必须放第一个:<source src="a.mp3" type="audio/mpeg">(注意不是audio/mp3) - 第二个可加
ogg(Vorbis 编码),但要确认服务器返回Content-Type: audio/ogg;Safari 会直接忽略它,所以不能依赖它兜底 - 短提示音可加
wav作最后 fallback:<source src="a.wav" type="audio/wav">,但别放前面——体积大、加载慢、移动端易卡 - Android Hybrid WebView(如华为/联想自带浏览器)只读第一个
<source>,顺序错就直接失败
autoplay + muted 必须同时存在,否则白写
Chrome 66+、Firefox 66+、Safari 13.1+ 全部强制要求:有声自动播放被禁,静音才可能播。单独写 autoplay 或只设 volume=0 都无效。
- 必须显式写
autoplay muted,缺一不可 -
muted是布尔属性,写上即生效;JS 中要恢复声音得手动设audio.muted = false - iOS Safari 还有额外限制:即使
muted,也必须等用户至少触发一次手势(如点击、触摸)后,后续的play()才能解除静音——这是硬性限制,绕不过 - 不要在
load或canplay回调里直接调play(),iOS 不认这种“非手动触发”的上下文
服务器 MIME 类型必须和 type 严格匹配
哪怕 <source> 写得再全,如果响应头里 Content-Type 是 text/plain 或空着,浏览器就当普通文本扔掉,连解码器都不调用。
立即学习“前端免费学习笔记(深入)”;
- Apache 用户,在
.htaccess或虚拟主机配置里加:AddType audio/mpeg .mp3、AddType audio/ogg .ogg、AddType audio/wav .wav - Nginx 用户,在
types块里补:audio/mpeg mp3;、audio/ogg ogg;、audio/wav wav; - 本地开发别双击 HTML 文件跑 ——
file://协议下 Chrome/Firefox 直接屏蔽音频加载;改用python3 -m http.server 8000 - 用 Network 面板确认每个音频请求的响应头,
Content-Type必须和type属性值完全一致
JS 播放必须捕获拒绝,不能只靠 canplay
用户点按钮后调 play(),不代表一定能响。现代浏览器会抛出不同错误,不处理就会静默失败。
- 必须用
audio.play().catch(e => { ... })捕获三类常见错误:NotAllowedError(自动播放被拒)、NotSupportedError(格式不支持)、AbortError(网络中断) - 监听
error事件可定位具体哪个<source>失败:audio.error?.code === 4表示所有源都不可用 - 别只靠
canplay判断就绪——它在元数据加载完就触发,音频体可能还没到;canplaythrough更可靠,但会明显延迟首次播放 - 设置播放位置(
currentTime)要分平台:iOS 等canplay后再设,Android 可直接设完就play()
真正落地时,最容易被忽略的是服务器 MIME 配置和 iOS 的手势授权链路——前者导致资源根本没加载,后者让所有 JS 播放逻辑形同虚设。这两处不查 Network 面板,问题永远在黑盒里。



















