H5端音频无法自动续播是因浏览器策略限制,必须通过用户交互(如touchstart或按钮点击)触发play()才能成功;iOS微信和Android X5内核均要求播放需用户手势授权,复用audio实例、避免setTimeout延迟、监听error并兜底交互是关键。

H5端移动端音频无法自动续播,本质不是代码写错了,而是浏览器策略卡死——iOS微信、Android X5内核都要求“用户交互后才能继续播放”,哪怕你上一个音频刚结束,play() 调用依然会被拦截。
为什么 ended 后调 play() 总失败?
这不是 bug,是浏览器主动拦截:iOS Safari 和微信内置浏览器(X5)在非用户手势上下文中禁止带声音的播放行为。即使你监听了 @ended、更新了 src、等了 @canplay,只要没用户新一次点击或触摸,play() 就会抛出 NotAllowedError: play() can only be initiated by a user gesture。
- 常见错误现象:
innerAudioContext.play()无响应、控制台报错、音频静音或黑屏 - H5 端不能依赖“自动连播”逻辑,必须把“续播”当作一次新的播放请求来处理
- 不要在
@ended回调里直接play(),那只是徒劳 -
uni-app 的
autoplay属性在 H5 端几乎无效,尤其 iOS 微信环境
必须用 WeixinJSBridge 或 wx.ready 触发首次播放
微信 H5 下唯一可靠路径是借助微信 JS-SDK 的桥接能力,在 WeixinJSBridge 就绪后触发播放——这相当于告诉微信“这个播放是有上下文授权的”,绕过部分静音策略。
- 先通过后端生成正确签名的
wx.config,jsApiList可为空,但debug必须关掉 - 必须等待
weixin-js-sdk的ready回调(或监听WeixinJSBridgeReady事件)再创建 audio 实例 - 首次
play()必须放在这里,否则 iOS 微信 100% 拒绝 - 推荐使用社区版
jweixin-module,比直接引入官方 script 更兼容 uni-app 的模块系统
续播只能靠“伪用户交互”兜底
真正意义上的“自动续播”在当前浏览器策略下不存在。可行方案是模拟一次轻量级用户交互,让后续 play() 获得合法上下文。
- 在
@ended后,用document.body.addEventListener('touchstart', handler, { once: true })监听一次任意触摸,然后立即触发play() - 或者更稳妥地:显示一个半透明“继续播放”按钮(不遮挡内容),绑定
@click调用play(),用户点一下就恢复播放流 - 避免用
setTimeout延迟播放——延迟 ≠ 用户交互,照样被拦 - Android X5 内核偶尔允许快速连续
play(),但 iOS 绝对不行,别赌兼容性
音频实例要复用,不能反复 destroy() + createInnerAudioContext()
每次新建 innerAudioContext 都会丢失播放上下文,导致续播再次失效。必须复用同一个实例,只换 src、重置状态。
- 声明为组件 data 中的引用(如
audioCtx: null),onLoad或mounted初始化一次 -
@ended中只做:this.audioCtx.src = nextUrl→this.audioCtx.play()(配合前述 touchstart 或按钮) - 务必监听
@error并打印errCode,常见 1001/1002 表示播放被拒,不是资源问题 - 不要在
@ended里调destroy(),除非你确定不再续播
真正的难点不在代码怎么写,而在于接受“自动续播不可行”这个前提——所有稳定方案都围绕“如何制造一次合法的用户上下文”展开。iOS 微信环境下,哪怕只差一次 touchstart 监听,整个链路就会断掉。











