顺序播放需监听ended事件手动切换,首次播放须用户手势触发,用HTML预定义audio元素更可靠,iOS需静音启动链。

顺序播放必须用 JavaScript 监听 ended 事件
原生 <audio></audio> 标签不支持内置播放列表,autoplay 和 loop 都无法实现“播完 A 自动播 B”。唯一可靠路径是监听当前音频的 ended 事件,在回调里手动加载并播放下一个。
常见错误现象:调用 play() 报错 DOMException: play() failed because the user didn't interact with the document first;或切换后卡住、从中间开始播、音量/静音状态丢失。
- 首次播放必须由用户手势(如
click、touchstart)触发,不能放在DOMContentLoaded或定时器中 - 每次切换前必须调用
load(),否则部分浏览器复用旧解码器状态,导致异常 - 务必重置
currentTime = 0,否则可能从上一次播放位置继续 - 如果用了
muted或volume控制,切换时需同步设置到新元素
多个 <audio></audio> 元素比 new Audio() 更稳
用 HTML 提前声明多个 <audio></audio> 元素(带 controls 或隐藏),比运行时用 new Audio(src) 实例化更可靠。前者可预加载元数据、支持 preload="metadata"、更容易绑定事件和调试。
new Audio() 在移动端尤其脆弱:iOS Safari 可能拒绝无用户交互后的首次 play(),即使加了 muted;且无法通过 DevTools 直观查看加载状态。
- HTML 中写好全部音频元素,例如:
<audio id="track1" src="a.mp3"></audio><audio id="track2" src="b.mp3"></audio> - 用数组统一管理:
const playlist = [document.getElementById('track1'), document.getElementById('track2')] - 避免在
ended回调里动态new Audio()并play(),容易触发静音策略拦截
格式兼容与预加载要分开处理
<source></source> 多格式回退只解决“能不能播”,不解决“播得顺不顺”。顺序播放对加载时序敏感,preload="metadata" 不会预加载音频主体,真预加载得靠 fetch + createObjectURL,但成本高、内存占用大,一般没必要。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
更务实的做法是:确保每个 <audio></audio> 元素都带 preload="metadata",并在用户点击播放第一个时,提前对后续几个调用 load()(非阻塞,浏览器自行调度)。
- 每个
<audio></audio>必须包含<source></source>组合,推荐顺序:<source src="x.mp3" type="audio/mpeg"><source src="x.ogg" type="audio/ogg"></source></source> -
type值必须是标准 MIME 类型,"audio/mp3"是无效的 - 不要依赖
autoplay启动整个列表——它只对第一个有效,且大概率被拦截
移动端 iOS Safari 的静音链必须打通
iOS Safari 对音频控制最严格:即使有用户点击,若该 <audio></audio> 元素此前从未成功 play() 过,仍可能拒绝后续调用。解决方案是“静音启动链”:首个播放强制 muted=true,成功后再取消静音并播放后续。
这个细节极易被忽略——你可能在 Chrome 里一切正常,一到 iPhone 就卡在第二首。
- 第一个音频设
muted属性,并确保首次play()成功后再执行audio.muted = false - 后续音频也显式设置
muted = false,不要假设继承上一个的状态 - 别省略
canplay或canplaythrough监听——短音频可等canplay再play(),长音频建议等canplaythrough避免中断
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










