audio标签src必须为有效静态路径,动态拼接易404;多source按顺序fallback,mp3放最前;play()需用户手势触发并捕获promise错误;移动端推荐preload="none"。

audio 标签的 src 属性必须是绝对或相对有效路径,不能是 blob URL 以外的 JS 生成地址
浏览器对 <audio></audio> 的加载策略很直接:只认静态可解析的 src 值。如果你用 URL.createObjectURL(blob) 动态赋值,它能播;但若拼接字符串如 "./audio/" + id + ".mp3" 却没提前存在对应文件,Chrome 和 Safari 会静默失败(network tab 显示 404,但不抛错),Firefox 可能触发 onerror。常见错误是后端返回音频临时链接带过期参数,前端没做预检就塞进 src。
- 上线前用 curl 或 fetch 检查所有
src地址是否真实返回200和Content-Type: audio/mpeg等正确类型 - 避免在
src里写未编码的中文或空格路径,如"./音频/测试.mp3"→ 改为"./%E9%9F%B3%E9%A2%91/%E6%B5%8B%E8%AF%95.mp3"或服务端重定向 - 移动端 iOS Safari 不支持直接播放
autoplay,哪怕加了muted,必须由用户手势(click/touchend)触发play()
多个 source 标签不是“自动选最优”,而是按顺序 fallback
<audio></audio> 内部的 <source></source> 是线性尝试机制:浏览器从上到下依次请求 src,遇到第一个能 canPlayType() 返回非 "" 且 HTTP 状态正常(2xx/3xx)的,就停在此处加载。它不会比较码率、采样率或容器格式优劣。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 把最通用格式放最前:优先
type="audio/mpeg"(MP3),再audio/ogg(Firefox 兼容),最后audio/wav(体积大,仅作兜底) - 不要写
type="audio/mp3"—— 正确 MIME 是audio/mpeg,否则 Safari 直接跳过该<source></source> - 可以用
canPlayType()预判:例如audio.canPlayType('audio/webm; codecs="opus"')在 Chrome 返回"probably",但在 Safari 返回"",说明 WebM+Opus 不可用
play() 返回 Promise,失败时 catch 而不是靠 onerror
现代浏览器调用 play() 后会返回 Promise,成功则 resolve,失败(如被策略阻止、资源加载异常、解码失败)则 reject。很多人仍习惯监听 onerror 或 onstalled,但这俩只覆盖部分底层错误,对“autoplay 被拦截”这类策略限制完全不触发。
- 必须用
audio.play().catch(e => { console.warn("play failed:", e.name) }),常见e.name有"NotAllowedError"(无用户交互)、"NotSupportedError"(格式不支持)、"AbortError"(加载中断) - 在用户手势回调里调用
play(),比如按钮onclick或touchstart,但注意:iOS Safari 要求事件必须是touchend才算有效手势上下文 - 不要在
loadedmetadata后立刻play(),此时可能还没建立播放上下文,尤其在 iframe 或后台标签页中
preload="none" 是移动端省流量的关键,但会延迟首次播放响应
默认 preload="metadata" 会在页面加载时预取音频头信息(时长、采样率等),但对移动网络来说,这可能提前下载几 MB 数据却最终没人点播。而 preload="none" 完全惰性,直到调用 play() 才发起请求 —— 这正是多数 H5 活动页需要的。
- iOS Safari 对
preload="auto"会强制忽略,始终表现如"metadata";Android Chrome 则真会预加载全部内容,慎用 - 如果业务要求“点击即播”,可在用户 hover 或 focus 按钮时,提前创建
Audio实例并设置src,利用浏览器缓存,但别调load()或play() - 服务端开启
Accept-Ranges: bytes和合适的Cache-Control,能让preload="metadata"只取前几百字节,降低开销
play() Promise 错误捕获——这两个点一旦出问题,整个播放流程就卡死,且控制台几乎不报错。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










