audio标签不播放,先查src路径和content-type:network面板确认请求返回200且content-type为audio/mpeg等合法类型;file://协议下chrome/safari禁用play(),须启本地服务;ios需用户手势触发play()并显式设置muted。

audio 标签不播,先查 src 路径和 Content-Type
浏览器静默失败最常见原因不是代码写错,而是资源根本没加载成功。打开 Network 面板,确认 src 请求返回 200,且响应头 Content-Type 是 audio/mpeg、audio/ogg 或 audio/wav —— 写成 audio/mp3 或漏掉 type 声明,Safari 就直接跳过该 <source></source>。
本地开发用 file:// 协议时,Chrome 和 Safari 会彻底禁用 play(),哪怕用户点了按钮也报 DOMException: play() failed because the user didn't interact with the document first。必须起本地服务,比如 python3 -m http.server。
多格式 fallback 必须按顺序写死 <source></source>,别信 canPlayType()
canPlayType() 返回 "probably" 不等于“一定能播”,它只表示 MIME 类型匹配,不校验编码细节(如 MP3 的 VBR 变比特率在 Firefox 中就可能失败)。静态声明更可靠:
-
<source src="sound.mp3" type="audio/mpeg"></source>—— 放最前,兼容性最广 -
<source src="sound.ogg" type="audio/ogg"></source>—— Firefox/Chrome 稳,Safari 完全不认 -
<source src="sound.wav" type="audio/wav"></source>—— 仅作兜底,文件大、加载慢,但 iOS Safari 对短音效支持反而比 OGG 稳
OPUS(audio/opus)可选:Chrome/Firefox 已支持,体积比 MP3 小 30%~50%,适合网络受限场景,但 Safari 仍不支持。
autoplay + muted 组合不是万能钥匙,iOS 还要用户手势授权
Chrome ≥84 允许静音自动播放,但前提是:muted 属性存在(写 muted="" 或 muted 都行,但 muted="false" 是无效的),且 JS 没后续改 audio.volume = 1。
iOS Safari 更严格:即使写了 autoplay muted,若页面没经历过任何用户手势(点击、触摸、键盘输入),play() 仍会静默失败。常见坑:
- 在
DOMContentLoaded或load事件里调play()→ iOS 必挂 - 用
setTimeout延迟 100ms 再播 → 依然不算“用户触发” - 监听
document.addEventListener('click', ...)后再播,是目前最稳的兜底方式
微信 WebView 还额外需要 WeixinJSBridgeReady 事件,否则连 touchstart 都不触发。
JS 播放必须捕获 Promise 拒绝,不能只靠 canplay 判断就绪
canplay 事件在元数据加载完就触发(比如时长、采样率),音频主体可能还没下载完,此时调 play() 仍可能卡住或报错。真正安全的做法是:
- 用
audio.play().catch(e => { ... })捕获三类关键错误:NotAllowedError(无手势)、NotSupportedError(所有<source></source>格式都不支持)、AbortError(网络中断) - 监听
error事件,检查audio.error?.code === 4,表示全部<source></source>均不可用 - 避免在
loadedmetadata后立刻play(),iOS 上大概率失败;等canplaythrough更稳妥(但注意它不保证 100% 缓存完成)
最后一点容易被忽略:如果音频中途被 JS 修改了 src,loop 属性状态不会自动重置,必须手动写 audio.loop = true 才生效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











