iOS Safari等浏览器中audio标签静默失效,必须用显式声明type="audio/mpeg"等正确MIME类型,配服务器Content-Type响应头,且首次播放需用户手势触发并加catch处理。

只写 <audio src="a.mp3"></audio> 在 iOS Safari、微信 iOS WebView、旧版 Firefox 和部分 Android WebView 中必然静默失效——不是报错,是连请求都不发、duration 为 NaN、控件不显示、canplay 事件永不触发。
必须用 <source></source> 显式声明多格式 + 正确 type
浏览器不会“猜”你 MP3 文件是不是 MPEG 编码,它只按 type 值匹配 MIME 类型。漏掉 type 或写错(比如 type="audio/mp3"),Safari 就直接跳过该源。
-
<source src="a.mp3" type="audio/mpeg"></source>:MP3 放第一位,兼容性最广;避免 VBR 编码(用ffprobe a.mp3确认是 CBR) -
<source src="a.ogg" type="audio/ogg"></source>:仅限 Vorbis 编码(ffprobe a.ogg输出含Audio: vorbis),Firefox/Chrome 稳定,Safari 完全不支持,所以不能放第一位 -
<source src="a.opus" type="audio/opus"></source>:Chrome/Firefox 已原生支持,体积比 MP3 小 30%~50%,但 Safari 仍不支持,可选 - 别加
.wav作 fallback:Chrome 对 IEEE Float 编码的 WAV 直接拒绝;若必须用,仅限短提示音,且确认是 PCM 编码
服务器响应头 Content-Type 必须严格匹配
即使 HTML 写对了,如果服务器返回的 Content-Type 是 text/plain 或为空,浏览器就当普通文本扔掉,连解码器都不调用。
- Apache:在
.htaccess或虚拟主机配置中加AddType audio/mpeg .mp3、AddType audio/ogg .ogg - Nginx:在
types块里补audio/mpeg mp3;、audio/ogg ogg; - 本地开发别双击 HTML:
file://协议下 Chrome/Firefox 会屏蔽音频加载;必须起 HTTP 服务,例如python3 -m http.server 8000 - 验证方式:打开 Network 面板,确认音频请求返回 200,且 Response Headers 中
Content-Type精确等于audio/mpeg等
自动播放必须满足三条件:muted + 用户手势 + JS 补偿
写了 autoplay muted 不代表真能响。iOS Safari 和微信 iOS WebView 要求用户至少触发一次 click 或 touchstart,否则 play() 返回被 reject 的 Promise,控制台报 DOMException: play() failed because the user didn't interact with the document first。
立即学习“前端免费学习笔记(深入)”;
- 不要在
DOMContentLoaded或 Vue 的mounted中调play(),100% 被拒 - 首次播放必须由用户事件同步触发,不能包在
setTimeout或Promise.then里 - 推荐做法:给一个按钮绑定
click,点击时先执行new Audio().play().catch(() => {})唤醒媒体上下文,后续音频才能自由播 - 所有
play()调用必须带.catch(e => console.warn('play blocked:', e)),常见错误码:NotAllowedError(策略拦截)、NotSupportedError(格式不支持)、AbortError(网络中断)
控件显示和预加载设置容易被忽略
不写 controls,浏览器默认隐藏所有播放界面;写了 controls="false" 是典型陷阱——浏览器把它当真值处理,控件反而意外出现且无法通过 JS 关闭。
-
controls=""或controls(空属性)才有效;controls="false"无效且误导 -
preload推荐设为"metadata":只读取时长、采样率等元数据,不下载音频体,兼顾首播速度与流量控制 -
preload="auto"在移动端常被忽略,部分 Android WebView 直接降级为metadata - iOS 还额外要求跨域音频响应头含
Access-Control-Allow-Origin: *,否则拒绝解码(连错误都不抛)



















