只写 <audio src="a.mp3"> 必然在 Firefox 或 Safari 上静音/不播;真正兼容的方案必须同时满足三件事——<source> 多格式声明 + type 属性严格匹配 + preload="metadata" 控制加载粒度。

直接给结论:只写 <audio src="a.mp3"> 必然在 Firefox 或 Safari 上静音/不播;真正兼容的方案必须同时满足三件事——<source> 多格式声明 + type 属性严格匹配 + preload="metadata" 控制加载粒度。
为什么加了 controls 还没播放按钮?
不是代码写错了,是浏览器根本没加载到音频资源。常见原因:
-
src路径用的是file://协议(双击 HTML 打开),Chrome/Firefox/Safari 全部静默拒绝,Network 面板里连请求都没有 -
<source>标签漏了type属性,Safari 直接跳过该源,最终无可用音源 - 写了
<audio>但没闭合标签(比如写成<audio>没写</audio>),Safari 会忽略整个元素 - 音频文件名含中文或空格,
src="背景音乐.mp3"在 Safari 和部分 Chrome 版本下 404
排查方式:打开 Network 面板,看音频请求是否返回 200,且响应头 Content-Type 是 audio/mpeg、audio/ogg 等合法类型。
多格式 fallback 怎么写才真有效?
浏览器按 <source> DOM 顺序尝试,**第一个 type 能解码的就用**,不是靠后缀名判断。所以顺序和 type 值都错不得:
立即学习“前端免费学习笔记(深入)”;
- MP3 放最前:
<source src="bg.mp3" type="audio/mpeg">—— iOS/macOS Safari 必须有它,别写audio/mp3(无效 MIME) - OGG 补位:
<source src="bg.ogg" type="audio/ogg">—— Firefox/Linux 常依赖,编码用libvorbis,别用 Opus 封进 OGG(老版本不认) - WAV 仅作兜底:
<source src="beep.wav" type="audio/wav">—— 文件大、加载慢,只适合短提示音,别放 MP3 前面
别信 canPlayType() 返回 "probably" 就能播——它只是推测,静态 fallback 更可靠。
autoplay + muted 为什么还是不响?
写了 autoplay muted 不等于“一打开就响”,现代浏览器(Chrome ≥70、Firefox ≥66、Safari ≥12.1)仍要求用户手势触发:
- iOS Safari 完全无视
autoplay,哪怕muted也得等click或touchstart后立刻调audio.play() - 别在
load或canplay回调里自动play(),iOS 不认这种“非手动上下文” -
preload="auto"在移动端基本被忽略,Safari 直接降级为metadata,Lighthouse 也会标为性能风险 - 实测有效的最小路径:监听按钮
click→ 立即audio.play().catch(e => console.warn(e))→ 捕获NotAllowedError(未交互)、NotSupportedError(格式不支持)
真正容易被忽略的是:preload="metadata" 不仅影响首屏体验,更是离线环境下的硬性前提——它让控件能立即渲染(duration 可读),又避免因文件缺失导致整个 <audio> 元素失效。



















