收藏
回答

InnerAudioContext.onTimeUpdate再次调用不触发

框架类型 问题类型 API/组件名称 终端类型 微信版本 基础库版本
小程序 Bug innerAudioContext.onTimeUpdate 客户端 7.0.4 2.7.3

- 当前 Bug 的表现(可附上截图)

InnerAudioContext播放完以后再次播放,onTimeUpdate生命周期不会再次触发,但是onPlay,onEnd都能正常触发


- 预期表现

每次audio组件重新播放都能触发onTimeUpdate

- 复现路径


- 提供一个最简复现 Demo


InnerAudioContext.onTimeUpdate再次调用不触发

最后一次编辑于  2019-07-04
回答关注问题邀请回答
收藏

11 个回答

  • 燚
    2019-07-03

    onTimeUpdate是播放进度更新,重新播放为什么不再触发?

    2019-07-03
    有用 1
    回复 18
    • 麦叻
      麦叻
      2019-07-04

      对 就是这个问题

      2019-07-04
      回复
    • 燚
      2019-07-04回复麦叻

      这边没重现不触发的case,你的设备信息是?

      2019-07-04
      回复
    • 麦叻
      麦叻
      2019-07-04回复

      这段代码片段 你导入看看Console 第二次播放不是也没触发吗

      2019-07-04
      回复
    • DuDuDu
      DuDuDu
      2019-07-04

      我这边也有这样的问题,不触发,求官方关注!

      2019-07-04
      2
      回复
    • 我贼瘦😶
      我贼瘦😶
      2019-07-18
      音频低于5秒,第一次点击播放可触发,第二次就不会触发。且ios上正常
      2019-07-18
      3
      回复
    查看更多(13)
  • Pumpkin Head
    Pumpkin Head
    2020-01-10

    最近也碰到这个问题。发现如果不去读取innerAudioContext.paused这个变量,它不会主动更新。解决问题的思路就是在调用play()方法之后再主动读取一次paused变量。可以写一个settimeout函数。

    this.data.innerAudioContext.seek(0)
    this.data.innerAudioContext.play()
    setTimeout(() => {
      console.log(this.data.innerAudioContext.paused)
    }, 100)
    
    2020-01-10
    有用 11
    回复 13
    • Qiu贤
      Qiu贤
      2020-02-27
      这个方法试过是可以的,我设的间隔是500
      2020-02-27
      1
      回复
    • 🐟 🐈
      🐟 🐈
      2020-05-24
      虽然不知道为什么 但是确实有用 为什么wx的bug每一个都能存在大半年
      2020-05-24
      1
      回复
    • 小胖
      小胖
      2020-07-21
      居然加setTimeout就莫名其妙可以了,不明觉厉
      2020-07-21
      回复
    • 大冰
      大冰
      2020-08-05
      我擦窗户,都一年了。 竟然有用。怎么试出来的我respect了
      2020-08-05
      回复
    • 老冰棍
      老冰棍
      2020-08-11
      厉害。一年了,这种方法可以。
      2020-08-11
      回复
    查看更多(8)
  • 朱文涛
    朱文涛
    2020-11-26

    总结得出以下结论:

    发生原因:由于音频加载导致 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中更加准确。

    2020-11-26
    有用 3
    回复
  • 温磊
    温磊
    2020-02-16

    经过反复测试,onTimeUpdate不触发确实是和onWaiting有关

    但不是注释掉onWaiting就正常了(上边大兄弟提供的方案),是音频只要不触发onWaiting,onTimeUpdate就是正常的

    而当拖动进度或者播放完毕后重新播放,都会触发onWaiting,然后onTimeUpdate就挂了

    2020-02-16
    有用 3
    回复 2
  • 左强
    左强
    2019-08-15

    在onEnded里面写 innerAudioContext.seek(0)即可解决


    2019-08-15
    有用 3
    回复 9
    • Andrew
      Andrew
      2019-09-05
      并不能解决,真机上还是获取不到
      2019-09-05
      回复
    • 杨森
      杨森
      2019-09-05回复Andrew
      对的,并不能解决
      2019-09-05
      回复
    • Andrew
      Andrew
      2019-09-05回复杨森
      现在有啥解决办法吗
      2019-09-05
      回复
    • 杨森
      杨森
      2019-09-05回复Andrew
      还没有,而且现在我还有一个问题是,onTimeUpdate还没有监听完,onEnded就触发了
      2019-09-05
      回复
    • 杨森
      杨森
      2019-09-06回复Andrew
      你解决了吗?
      2019-09-06
      回复
    查看更多(4)
  • Vaskka
    Vaskka
    2020-04-05

    完美解决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标志位
          })
      }
    })
    
    2020-04-05
    有用 2
    回复 3
    • 所谓曾经,已面目全非。所谓未来,不过冠冕堂皇
      所谓曾经,已面目全非。所谓未来,不过冠冕堂皇
      2020-05-07
      亲测有用,但是要定制化音频播放,不止这一个坑,真的是服气
      2020-05-07
      回复
    • 觀·自在
      觀·自在
      2020-08-18
      ios不管用
      2020-08-18
      回复
    • 觀·自在
      觀·自在
      2020-08-18
      楼主的方法,ios 确实不能播放了!参考后的解决方法是把pauses稍微挪一下
      2020-08-18
      1
      回复
  • uh...
    uh...
    2019-11-26

    我也遇到同样的问题 真心觉得小程序做的贼垃圾

    2019-11-26
    有用 1
    回复 1
    • 小精灵òᆺó
      小精灵òᆺó
      2019-12-11
      我也 遇到了同样的问题,请问最后是怎么解决的?
      2019-12-11
      回复
  • kk
    kk
    2020-12-25


    解决方案https://blog.csdn.net/Vaskka/article/details/105326977

    2020-12-25
    有用
    回复
  • 小海螺
    小海螺
    2020-02-26
    1. 遇到同样的问题,照上面的方法处理后还是不行。
    2. 曲线救国,onPlay中,延时0.3s(onTimeUpdate好像是0.25s回调一次) ,判断onTimeUpdate是否执行,不执行就setInterval 循环处理,但是效果不太完美。
    3. 最终 每次播放完后,如果再次播放就重新加载一次音频文件,解决问题。
    2020-02-26
    有用
    回复
  • 书文
    书文
    2019-12-25

    华为nova 2s 测试可跟随循环播放进行循环触发,但在开发工具上在开始第二次播放后便停止触发------同求解决办法,尚未在iphone真机测试,不知目前是否仅是开发工具上如此


    目前解决的大致思路是 

    猜测:开发工具中仅在新建InnerAudio实例时触发“一轮”onTimeUpdate直至一轮播放结束


    大体解决思路: "互相传球"——新建两个InnerAudio实例,互相在对方onEnded时新建对方实例,同时在对方实例中销毁自己(注意innerAudio.loop不能设置为true,实践证明这样无法触发onEnded!------此时一想,莫非开发工具中onTimeUpdate的触发和onEnded的触发存在某种未知联系?)


    具体一点点:

    通过在Page({})下分别新建两个InnerAudio实例,实例中分别在onEnded时新建另一各实例,而同时另一个实例中销毁前一个audio实例.....从而实现“互相传球”


    主要代码如下(具体功能可无视):

      toAC_0: function () {

        console.log('target_0')

        let _this = this

        if (_this.audioContext_1.play) {//如果第二个audio实例存在,则销毁

          _this.audioContext_1.destroy()

          _this.audioContext_1 = null

        }

        _this.audioContext_0 = new Object()//因为在_this.toAC_1中_this.audioContext_0已经被赋值null(原因略)

        _this.audioContext_0 = wx.createInnerAudioContext()

        _this.audioContext_0.src = 'cloud://superteam-hzq0j.7375-superteam-hzq0j-1300417025/app/login/bgm.mp3'

        _this.audioContext_0.autoplay = true

        //_this.audioContext_0.loop = true

        _this.audioContext_0.onEnded(() => {

          console.log('onEnded_0!')

          _this.toAC_1()

        })

        _this.audioContext_0.onTimeUpdate(() => {

          console.log('已触发onTimeUpdate_0!')

          console.log('onTimeUpdate-duration_0: ', _this.audioContext_0.duration)

          let deg_0 = (360 * _this.audioContext_0.currentTime / _this.audioContext_0.duration + 45)

          let deg = deg_0 <= 180 ? deg_0 : (deg_0 - 360)

          let bgc = [deg, 128, 128, 128, 8, 245, 8]

          console.log(bgc[0])

          _this.setData({

            bgc: bgc

          })

        })

        _this.audioContext_0.onError(err => {

          console.log('audioOnErr: (上次是音源有问题导致无法循环!可供参考)', err)

        })

      },

      toAC_1: function () {

        console.log('target_1')

        let _this = this

        if (_this.audioContext_0.play) {//如果第一个audio实例存在,则销毁

          _this.audioContext_0.destroy()

          _this.audioContext_0 = null

        }

        _this.audioContext_1 = new Object()//因为在_this.toAC_0中_this.audioContext_1已经被赋值null(原因略)

        _this.audioContext_1 = wx.createInnerAudioContext()

        _this.audioContext_1.src = 'cloud://superteam-hzq0j.7375-superteam-hzq0j-1300417025/app/login/bgm.mp3'

        _this.audioContext_1.autoplay = true

        //_this.audioContext_1.loop = true

        _this.audioContext_1.onEnded(() => {

          console.log('onEnded_1!')

          _this.toAC_0()

        })

        _this.audioContext_1.onTimeUpdate(() => {

          console.log('已触发onTimeUpdate_1!')

          console.log('onTimeUpdate-duration_1: ', _this.audioContext_1.duration)

          let deg_0 = (360 * _this.audioContext_1.currentTime / _this.audioContext_1.duration + 45)

          let deg = deg_0 <= 180 ? deg_0 : (deg_0 - 360)

          let bgc = [deg, 128, 128, 128, 8, 245, 8]

          console.log(bgc[0])

          _this.setData({

            bgc: bgc

          })

        })

        _this.audioContext_1.onError(err => {

          console.log('audioOnErr: (上次是音源有问题导致无法循环!可供参考)', err)

        })

      },

      addBgMusic: function () {

        let _this = this

        _this.bgmSrc = 'cloud://superteam-hzq0j.7375-superteam-hzq0j-1300417025/app/login/bgm.mp3'

        _this.audioContext_0 = new Object()

        _this.audioContext_1 = new Object()

        /**

         * 此处通过

         * let bgMusicaudioContext_0 = _this.audioContext_0

         * 无法形成指向getApp().globalData.bgMusic.audioContext_0d的指针效果?

         */

        if (_this.audioContext_0.play || _this.audioContext_1.play){//如果已经创建bgMusic,则直接播放(避免重复创建)

          if (_this.audioContext_0.play){

            _this.audioContext_0.play()

          }

          else{

            _this.audioContext_1.play

          }

        }

        else{

          _this.toAC_0(_this)

        }

      },

      removeBgMusic: function(){

        /*

        //对于微信小程序社区所讨论innerAudioaudioContext_0.destroy()的不确定性

        //此处采用先stop,再destroy

        //确保不会意外的无法停止播放

        */

        let _this = this

        if (_this.audioContext_0 || _this.audioContext_1) {//多这一层if为了看起来“局部整体化”

          /**

          * 经测试,destroy并未真正销毁innerAudioaudioContext_0

          */

          if (_this.audioContext_0) {//加这一层为了避免直接访问_this.audioContext_0.play出错

            if (_this.audioContext_0.play){

              _this.audioContext_0.destroy()

              _this.audioContext_0 = null

            }

          }

          if (_this.audioContext_1) {//加这一层为了避免直接访问_this.audioContext_1.play出错

            if (_this.audioContext_1.play){

              _this.audioContext_0.destroy()

              _this.audioContext_0 = null

            }

          }

        }

      },


    现已经在开发工具中和真机 华为 nova 2s真机中测试可无限循环触发onTimeUpdate(参看console.log内容可知)


    小白的学习之路,如有可改进之处,请指教!谢谢!



    2019-12-25
    有用
    回复 2

正在加载...

登录 后发表内容