- 当前 Bug 的表现(可附上截图)
InnerAudioContext播放完以后再次播放,onTimeUpdate生命周期不会再次触发,但是onPlay,onEnd都能正常触发
- 预期表现
每次audio组件重新播放都能触发onTimeUpdate
- 复现路径
- 提供一个最简复现 Demo
InnerAudioContext.onTimeUpdate再次调用不触发
框架类型 | 问题类型 | API/组件名称 | 终端类型 | 微信版本 | 基础库版本 |
---|---|---|---|---|---|
小程序 | Bug | innerAudioContext.onTimeUpdate | 客户端 | 7.0.4 | 2.7.3 |
onTimeUpdate是播放进度更新,重新播放为什么不再触发?
对 就是这个问题
这边没重现不触发的case,你的设备信息是?
这段代码片段 你导入看看Console 第二次播放不是也没触发吗
我这边也有这样的问题,不触发,求官方关注!
总结得出以下结论:
发生原因:由于音频加载导致 onUpdateTime 失效,(比如调用 seek的时候,触发了音频自动加载)
总结:(受楼上启发)由于使用 innerAudioContext.paused(比如:打印) 可以将onUpdateTime生效,所以只需要判断在什么情况下使用innerAudioContext.paused,由于每次音频加载完毕都会触发onCanPlay,所以加在此回调中即可
解决方案:innerAudioContext.onCanPlay(()=>{ console.log(innerAudioContext.paused) })
其它:楼上说在seek后加setTimeout(() => { console.log(innerAudioContext.paused) },100),也可以解决,由于seek后音频加载时间不固定,100毫秒内如果没有加载完毕,仍然无法触发onUpdateTime,所以加在onCanPlay中更加准确。
最近也碰到这个问题。发现如果不去读取innerAudioContext.paused这个变量,它不会主动更新。解决问题的思路就是在调用play()方法之后再主动读取一次paused变量。可以写一个settimeout函数。
this.data.innerAudioContext.seek(0) this.data.innerAudioContext.play() setTimeout(() => { console.log(this.data.innerAudioContext.paused) }, 100)
遇到同样的问题,目前已解决,分两部分详述:
一、分析问题
我的场景是用户录制语音完成后,自动播放一遍,用户可以点“重听”按钮再次播放。
我使用 InnerAudioContext 来实现播放语音的需求,录制语音完成后的自动播放是将 InnerAudioContext.src 赋值为录制完成后得到的 tempFilePath,并设置自动播放(InnerAudioContext.autoplay = true),可以正常播放,且 onTimeUpdate 回调正常。
第一遍播放完毕后,点击“重听”按钮时,我使用 InnerAudioContext.play(),倒是可以正常播放,但 onTimeUpdate 100%不会被触发(我需要用 onTimeUpdate 来更新进度条)。
发现这个问题下很多人已经指出,只要触发了 innerAudioContext.onWaiting,innerAudioContext.onTimeUpdate 就会失效,我实测了一下,果然如此:运行 InnerAudioContext.play() 后,就会触发 onWaiting,因为需要重新载入音频文件,所以一定会触发等待载入(实测即使只有 1 秒钟的音频,用 .play() 播放时也会先触发 onWaiting)。
而只要触发了 onWaiting 之后,onTimeUpdate 就失效了。但在这之后如果暂停一次再继续播放,onTimeUpdate 就能恢复正常。(微信团队真是懒政至极,这种 Bug 存在三年了,既不修复也不回复,真的好意思每个月继续领工资吗?😠)
二、解决问题
有人给的方案是用 setTimeout,原理就是运行 .play() 之后,等待一段时间让音频载入,然后运行一次暂停,然后再继续播放,就可使得 onTimeUpdate 正常运行。
但延时这个方案太丑陋了,长了影响体验,短了音频没载入完依然无效,永远不可能设置一个完美的延时长度。
对我这个场景而言(不需要拖动进度条),更理想的方式是点“重听”时,重新给 InnerAudioContext.src 赋值,并设置 InnerAudioContext.autoplay = true,它会等待音频载入完之后自动开始播放,不触发 innerAudioContext.onWaiting,所以 onTimeUpdate 也就能正常运行。
而如果你的场景需要支持用户手动调整进度(需要调用 innerAudioContext.seek),也别用延时的方案,在 innerAudioContext.onCanplay 里(代表这时已经载入完音频了),调用一次 .pause(),再调用一次 .play() 即可。
完美解决onTimeUpdate在触发onWaiting回调后失效的问题:
目前在IDE和xiaomi9 Wechat-7.0.13上表现较好,iphone未测试。
只需要在onWaiting()触发时,调用pause(),在音频准备好的时候也就是onCanplay()触发时再调用play()即可。
// 音频由于网络等原因等待中的回调 this.audioCtx.onWaiting(() => { that.audioCtx.pause() // 等待网络的时候音频暂停 that.setData({ waitFlag: true // 标明是onWaiting触发的暂停 }) }) // 音频准备就绪的回调 this.audioCtx.onCanplay(() => { if (that.data.waitFlag) { // 如果是onWaiting触发的暂停,就立即播放 that.audioCtx.play() // play()方法看上去能重新触发onTimeUpdate()回调 that.setData({ waitFlag: false // 取消相应的flag标志位 }) } })
innerAudioContext.onWaiting(() => {
this.setData({
waitFlag: true
})
})
// 监听音频进入可以播放状态的事件。但不保证后面可以流畅播放
innerAudioContext.onCanplay(() => {
if (this.data.waitFlag) {
innerAudioContext.pause()
innerAudioContext.play()
this.setData({
waitFlag: false
})
}
})
在onEnded里面写 innerAudioContext.seek(0)即可解决
我也遇到同样的问题 真心觉得小程序做的贼垃圾
加个seek(0) 貌似可以触发再次onTimeUpdate
2023-10-26 依旧没有解决这个bug 微信真好
setInterval(()=>{ let duration = innerAudioContext.duration let currentTime = innerAudioContext.currentTime console.log("时长: ", duration) console.log("当前播放时间: ", currentTime) }, 200)
用定时器吧,实测可行