收藏
回答

基础库2.32.3:WebAudioContext解码音频后播放,生产播放不完整,体验版正常?

测试机型:iOS13、iOS13 pro;

微信版本:8.0.38;

基础库:体验/开发环境测试了2.32.2、2.32.3,线上环境不确定,应该是2.32.2吧

实现方式:使用 wx.createWebAudioContext()进行播放,将arrayBuffer的音频通过audioContext.decodeAudioData解码后,创建BufferSourceNode进行播放;

现象:在本地调试、预览、体验版上测试都没问题,可以正常播放音频,只有线上版本的音频播放不完整,会出现播放中断现象(只播放前一段,后半段大概率无声音)。iOS上出现概率很大,Android机暂未复现。

并且测试或者体验版打开调试时,生产环境小程序也可出现控制台的情况下,音频都播放正常,未出现不完整情况,关闭调试后重启小程序,线上版本播放出现不完整。

有大佬知道遇到过这个问题嘛?线上控制台调出来就不复现了,关控制台后复现概率好大,崩溃。。

根据线上版本的页面交互看,source.onended回调是在实际音频播放时长后触发,并不是在音频中断的时候就触发,所以推测实际上播放器应该还一直在工作,只不过没有声音(例如三秒的音频只播放了一秒,后两秒没声音,但onended在三秒后触发)

贴出播放相关的部分代码参考:

this.playStatus = 1;
//微信小程序需要用WebAudioContext来播放base64数据(innerAudioContext不支持)
// #ifdef MP-WEIXIN
//先暂停,防止其他使用audioContext的组件有正在播放的音频产生冲突
this.audioContext.state !== 'suspended' && this.audioContext.suspend()
try {
    //需要去掉换行这些符号,不然base64ToArrayBuffer会报错
    const base64 = this.content.nodevoid.replace(/[\r\n]/g, "")
    let arrayBuffer = uni.base64ToArrayBuffer(base64)
    this.audioContext.decodeAudioData(arrayBuffer, buffer => {
        console.log('robot decodeAudioData:', buffer)
        const duration = buffer.duration
        try {
            this.source = this.audioContext.createBufferSource()
            console.log('robot create bufferSource :', this.source)
            //音频播放器被暂停时,当前场景有其他的音频播放,为防止声音重叠设置的暂停
            this.audioContext.onstatechange = () => {
                console.log('robot onstatechange:', this.audioContext.state, this.playStatus)
                if (this.audioContext.state === 'suspended' && this.playStatus === 1) {
                    this.source.stop()
                }
            }
            this.source.buffer = buffer
            this.source.connect(this.audioContext.destination)
            //回调播放结束事件,自动播放时用(有几率触发不了,原因没查到,先做个处理)
            this.source.onended = () => {
                console.log('robot play ended')
                this._playEnd()
            }
            console.log('robot connect destination :', this.audioContext.destination)
            this.audioContext.state === 'suspended' && this.audioContext.resume()
            this.source.start(0)
            console.log('robot play start ', this.source)
            //定时器为了应对偶先不触发onended的情况,duration向上取整,时间稍微多一点点,防止有播放不完全的情况
            this.endTimer = setTimeout(() => {
                console.log('robot play ended(timeout)')
                this._playEnd()
            }, Math.ceil(duration) * 1000)
        } catch (e) {
            console.error('robot play catch error ', e)
        }
    }, err => {
        console.error('robot decodeAudioData fail', err)
    })
} catch (e) {
    console.warn('robot play error:', e)
}
// #endif

_playEnd() {
    this.playStatus = 0
    if(this.endTimer) {
        clearTimeout(this.endTimer)
        this.endTimer = 0
    }
    this.$emit('play-ended')
}

补充:

后来意外的找到微信客户端为8.0.29和8.0.30版本,测试了下线上的音频播放是没问题的,推测可能是高版本的播放问题,因为目前测试的微信都是8.0.38,都有问题,所以暂时没更多对比,不好推测问题出在哪。

最后一次编辑于  2023-06-25
回答关注问题邀请回答
收藏

2 个回答

  • ben
    ben
    2023-07-30

    我遇到过类似的,只在ios上复现,但每次有略有差别,左后将代码行顺序调整了一下,莫名其妙的就好了,而且非常稳定,不知道什么原因

    2023-07-30
    有用
    回复 1
    • Strive
      Strive
      08-11
      怎么调整的
      08-11
      回复
  • Buon Giorno 🐈🐕
    Buon Giorno 🐈🐕
    2023-06-25

    莫名其妙的改好问题了,由于播放是在子组件中实现,之前是子组件中自己通过createWebAudioContext创建音频上下文进行播放,后来因为要控制多个子组件的音频播放冲突问题,于是改成在父组件中createWebAudioContext后将音频上下文对象传给子组件,大家公用一个,结果播放不完整的问题就修复了,我目前还没想明白原因。。。

    2023-06-25
    有用
    回复
登录 后发表内容