Safari和旧Android上单个src失败主因是type MIME类型不匹配或缺失,需确保type值与服务器响应头严格一致,并用本地HTTP服务替代file://协议。

为什么单个 src 属性在 Safari 和旧 Android 上大概率失败
浏览器不会解包 MP3 或 OGG 文件去猜编码,它只按 type 值做 MIME 类型匹配。省略 type 时,Chrome 可能碰巧加载成功,但 iOS Safari 会直接跳过该 <source>,导致 canplay 不触发、duration 为 NaN,控制台还静默无报错。
<source> 的 type 值必须写对,且与服务器响应头严格一致
常见错误包括:type="audio/mp3"(错,应为 audio/mpeg)、type="audio/ogg" 指向 Opus 编码文件(Safari 不支持,得用 Vorbis);更隐蔽的问题是服务器没配 MIME 类型——哪怕 HTML 写全了,响应头是 Content-Type: text/plain,浏览器就当文本扔掉,连解码器都不调。
- Apache 用户:在
.htaccess加AddType audio/mpeg .mp3、AddType audio/ogg .ogg - Nginx 用户:在
types块里补audio/mpeg mp3;、audio/ogg ogg; - 本地开发别双击 HTML:用
python3 -m http.server 8000启服务,否则file://协议下 Chrome/Firefox 直接屏蔽音频加载
多格式顺序和选型不能只靠“MP3 + OGG”
MP3 + OGG 覆盖大部分桌面端,但漏掉两个关键场景:iOS Safari 对 audio/ogg 支持极不稳定,实测 audio/wav 反而更稳(尤其短提示音);某些企业内网禁用 MP3 解码,只允许 WAV 或 OPUS(audio/opus 在 Chrome/Firefox 已支持,体积比 MP3 小 30%~50%)。
- 顺序决定 fallback 路径:把兼容性最广的放第一位(如 MP3),WAV 放最后(体积大、加载慢,仅作兜底)
- 别依赖
canPlayType()动态判断——返回"probably"不等于“一定能播”,静态声明更可靠 - Ogg 文件必须确认是 Vorbis 编码:
ffprobe a.ogg输出里要有Audio: vorbis
JS 触发 play() 必须捕获拒绝,且区分平台设置播放时机
用户点击后调用 play() 不等于一定能响。iOS WebKit 要求必须等 canplay 才能设 currentTime,而低版本 Android WebView 压根不抛 canplay,但 play 事件相对可靠。
立即学习“前端免费学习笔记(深入)”;
- 必须用
audio.play().catch(e => console.warn('play rejected:', e))捕获NotAllowedError(自动播放被拒)、NotSupportedError(格式不支持)、AbortError(网络中断) - 监听
error事件可定位具体哪个<source>失败:audio.error?.code === 4表示所有源均不可用 - iOS 要求元素在视口内、未被
display: none或opacity: 0遮挡,否则即使点过也静音
真正卡住人的不是写不出代码,而是 Network 面板里看不到请求、控制台没报错、readyState 停在 0 —— 这些时候,先查 Content-Type 响应头和 type 声明是否对得上,再看是否还在用 file:// 协议本地双击打开。



















