实测音频格式支持必须调用 canPlayType(),Modernizr.audio 仅表示元素识别,Modernizr.canplaytype 仅表示方法存在;结果仅 ''、'maybe'、'probably' 三种,且 'probably' 不保证可播,最终需监听 error 事件验证。

用 canPlayType() 实测格式支持,别信 Modernizr 返回的 video 或 audio
Modernizr 的 Modernizr.audio 只表示 <audio> 元素被识别,不代表能播 MP3;Modernizr.canplaytype 仅说明方法存在,不告诉你 canPlayType('audio/mpeg') 返回什么。真正兼容性必须自己调用。
实操建议:
- 创建临时元素:
const a = new Audio()(比document.createElement('audio')更轻量) - 对每种格式调用:
a.canPlayType('audio/mpeg')、a.canPlayType('audio/ogg')、a.canPlayType('audio/mp4; codecs="aac"') - 结果只有三种:
''(不支持)、'maybe'(可能支持,但解码器未加载或编码不明确)、'probably'(大概率可播) - Firefox 对
audio/mpeg常返回''或'maybe',即使 MP3 能播——需 fallback 到实际加载后监听error事件验证
type 属性写错就等于没写:必须用 audio/mpeg,不是 audio/mp3
浏览器靠 type 值匹配内置解码器,不是靠文件后缀。写错 MIME 类型会导致 Safari、iOS WebView 直接跳过该 <source>,静默失败,控制台无报错。
常见错误与修正:
立即学习“前端免费学习笔记(深入)”;
-
type="audio/mp3"→ 错,标准是audio/mpeg -
type="audio/ogg"正确,但注意:它只保证 Ogg 容器 + Vorbis 编码(不是 Opus),可用ffprobe file.ogg确认 Audio: vorbis -
type="audio/wav"要小心:Chrome 拒绝 IEEE Float 编码的 WAV,Firefox 支持但体积大;适合短提示音,不推荐主音频 - 没写
type属性 → Chrome 可能碰巧加载,Safari 必定跳过
服务器响应头 Content-Type 不匹配,<source> 就是摆设
就算 <source src="a.mp3" type="audio/mpeg"> 写得再准,如果服务器返回的响应头是 Content-Type: text/plain 或空着,浏览器连解码器都不会调用,直接当普通文本丢弃。
检查与修复步骤:
- 打开 DevTools → Network → 点击音频请求 → 查看 Response Headers 中的
Content-Type - 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 会屏蔽音频加载
iOS Safari 和 Android WebView 的真实限制:preload 和用户手势不能省
iOS Safari 对音频加载极其保守:preload="auto" 被忽略,autoplay 即使配了 muted 也常失败,除非页面已获得用户手势授权(比如用户点过任意区域)。
关键实操点:
-
preload必须设为"metadata":只读时长、采样率,不下载音频体,兼顾首帧速度与流量 -
play()必须包裹在用户事件回调里:button.addEventListener('click', () => audio.play()),不能放在load、canplay或定时器中 - 静音自动播放要双重确认:
muted属性存在 且audio.volume === 0,JS 后续改过volume会触发策略重检 - Android 4.4 WebView 支持
<audio>但canPlayType('audio/mpeg')返回空字符串,只能靠 fallback + error 事件兜底
最易被忽略的一点:canPlayType 返回 'probably' 不代表一定能播——它只说明浏览器“认为自己能”,但实际解码可能因系统级编解码器缺失、权限限制或内存不足而失败。最终验证必须落到 error 事件和 audio.error?.code(code === 4 表示所有 source 均不可用)。



















