必须用<source>多格式兜底并正确设置type属性,服务器返回准确Content-Type,JS播放需捕获Promise拒绝和error事件,三者缺一不可。

只写 <audio src="a.mp3">,在 Safari、Firefox 或 iOS 上大概率静音、卡住或完全不响——这不是代码写错了,是浏览器根本没尝试解码。
必须用 <source> 多格式兜底,不能只靠一个 src
浏览器不会“猜”你给的 MP3 文件能不能播,它只按 type 值匹配 MIME 类型。省略 type 或写错(比如 type="audio/mp3"),Safari 就直接跳过该 <source>,连错误都不报。
-
<source src="a.mp3" type="audio/mpeg">是正确写法;audio/mp3是错的 - 至少提供两个
<source>:MP3 放第一位(兼容最广),OGG(Vorbis 编码)放第二位 - WAV 不建议作 fallback:文件大、Chrome 对 IEEE Float 编码的 WAV 直接拒绝
- OPUS 可作为第三选项:
type="audio/opus",Chrome/Firefox 已支持,体积比 MP3 小 30%~50%
服务器必须返回正确的 Content-Type 响应头
即使 <source> 写得再全,如果响应头里 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 会屏蔽音频加载;用python3 -m http.server 8000启服务 - 检查 Network 面板,确认每个音频请求的响应头
Content-Type准确对应后缀和编码
JS 播放必须捕获 Promise 拒绝,不能只靠 play()
用户点击后调用 play() 不等于一定能响。现代浏览器对自动播放拦截极严,且错误类型各异,不捕获就等于放弃诊断。
立即学习“前端免费学习笔记(深入)”;
- 必须用
audio.play().catch(e => { ... })捕获三类关键错误:NotAllowedError(手势缺失)、NotSupportedError(格式不支持)、AbortError(网络中断) - 监听
error事件可定位具体失败源:audio.error?.code === 4表示所有<source>均不可用 - 不要依赖
canplay判断就绪——它只等元数据,音频体可能还没到;canplaythrough更可靠,但延迟明显 - iOS Safari 要求元素在视口内、未被
display: none或opacity: 0遮挡,否则即使点过也静音
真正能落地的兼容加载,不是拼对标签,而是把 <source> 顺序、服务器 MIME 配置、JS 错误捕获这三层都拧紧。漏掉任何一层,都可能在某个设备上彻底无声——而且不报错,只沉默。



















