audio标签的type属性必须显式声明,不能依赖文件后缀;需确保MIME类型与实际编码匹配、服务端Content-Type正确、按目标机型排序fallback源,并通过首次用户手势解锁播放权限。

audio 标签的 type 属性必须显式写,不能靠后缀猜
很多开发者以为 .mp3 文件配 <source src="a.mp3"> 就能播,结果在 OPPO、vivo 自带浏览器或某些 Android Webview 里静音或报错。根本原因是浏览器不看后缀,只认 type 声明的 MIME 类型和实际编码是否匹配。
例如 Safari 要求 type="audio/mp4" 的文件,内部音频编码必须是 AAC-LC —— 即使文件后缀是 .m4a,如果里面是 HE-AAC 或 ALAC,照样不播。用 ffprobe a.m4a 确认 codec_name 是 aac,不是 libopus 或 alac。
- MP3 文件统一用
type="audio/mpeg" - AAC 容器(
.m4a/.mp4)必须配type="audio/mp4",且编码为 AAC-LC - OGG(Vorbis)用
type="audio/ogg",别写成audio/ogg; codecs=vorbis—— Safari 会直接跳过 - WAV 不建议放最后,它虽兼容但体积大;若前面所有
<source>因 MIME 不匹配被跳过,会误触发“不支持”提示
多格式 fallback 必须按浏览器偏好排序,不能随便列
Firefox 桌面版对 OGG 解码最稳,但 iOS Safari 几乎不认 OGG;Android Chrome 对 MP3 支持好,但某些旧 Webview(如 Android 6.x)解码 MP3 有偶发卡顿。所以 fallback 顺序不是“哪个先写就优先用”,而是按目标机型权重排。
- 面向国内安卓机(OPPO/vivo/华为):优先
.mp3,再.ogg,最后.wav(仅作兜底) - 纯 iOS 场景(如企业微信内嵌页):只用
.mp3或.m4a(AAC-LC),删掉 OGG 分支 - 混合场景(H5 社交页):用
Audio.canPlayType()动态选源,而非全量加载 - 别把 WebM(Opus)放在
<source>里 —— Safari 和大部分国产浏览器根本不识别audio/webm
服务器 Content-Type 错了,前端再怎么写都白搭
控制台报 DOMException: The element has no supported sources 或静音无响应,90% 是服务端没配对 MIME 类型。浏览器收到 text/plain 或空 Content-Type,直接拒绝解析音频流。
立即学习“前端免费学习笔记(深入)”;
-
.mp3→ 响应头必须含Content-Type: audio/mpeg -
.m4a/.mp4(音频)→Content-Type: audio/mp4,不是video/mp4 -
.ogg→Content-Type: audio/ogg - Nginx 配置示例:
types { audio/mpeg mp3; audio/mp4 m4a; audio/ogg ogg; } - 用浏览器 DevTools 的 Network 面板点开音频请求,确认响应头里的
Content-Type是否准确
自动播放失败不是代码问题,是权限未解锁
用户点了播放按钮却没声音?大概率不是音频路径错了,而是媒体上下文没被激活。iOS Safari 和多数安卓 WebView 要求「首次用户手势」才能解锁音频播放权限,这个权限是页面级的,解锁后后续所有 play() 都有效。
- 别在
DOMContentLoaded或load事件里调audio.play(),必失败 - 最简解锁方式:在第一个可点击元素(如「开始」按钮)的
click回调里,创建一个空Audio并立刻play().catch(() => {}),然后pause() - 微信或 QQ 内置浏览器有时需要额外触发一次
touchstart才算有效手势,可加个透明遮罩层捕获首次触摸 - 不要用
setTimeout或 Promise 异步调play()—— 已脱离手势上下文,浏览器直接拒绝



















