首页 > 编程语言 >小程序音频播放复杂流程的经验和思考

小程序音频播放复杂流程的经验和思考

时间:2023-04-22 13:12:30浏览次数:40  
标签:音频 audioInfos innerIdx item currWordItem 播放 data 流程

最近两周在写一个新的小程序项目,托福词汇真经。这个小程序的难点是音频播放流程比较复杂

之前我在雅思听力小程序里实现过雅思词汇真经的功能

前期讨论的结果是基于原有的功能开发

开发过程中碰到了一些问题,这里记录一下,同时梳理一下这里音频播放的逻辑,后面如果再增加新功能,可以快速处理

闲话少叙
这里讨论的页面是: wordsZhenjing.js
四种模式介绍

这个页面的音频播放最开始只有两个模式:1.循环听 2.听写
后来增加了在线拼写模式,这次又增加了测试模式。但是这两种模式的详情页都是新的页面,逻辑不在这里,这里不讨论
循环听VS听写 最开始使用 isListen 这个布尔值变量区分,但是后来增加了拼写和测试模式,所以现在使用modeIndex变量区分(0:测试; 1:循环听; 2:听写; 3:拼写) 。
所以isListen是否可以去掉呢? xml里面使用了这个变量,先留着吧

旧的模式介绍
听写模式: 只播放单词。播放完毕去对答案

循环听模式:播放单词,例句, 同替,过去式,过去分词。这个单词的相关信息播放完,继续播放下一个单词的例句,同替,过去式...
一组全部播放完毕,根据不同设置,可以重头播放这一组,也可以播放下一组

旧的关键逻辑
Q:循环听模式是怎么顺序播放 单词,例句,同替,单词,例句,同替...... 如此循环的呢?
A: 每个单词的例句, 同替,过去式格式化成数组 formAudios, 追加字段audioInfos, 增加一个innerIdx 字段,用于在单词的 audioInfos 数组里面顺序播放音频

/**
   * 格式化音频
   */
  formAudios(list) {
    list.forEach((item) => {
      let audioInfos = typeof (item.near) != 'undefined' ? Array.from(item.near) : []

      if (item.past) {
        audioInfos.push(...item.past)
      }

      if (item.participle) {
        audioInfos.push(...item.participle)
      }

      if (item.template && item.template.url.length > 0) {

        let tempItem = {
          tag: 'template',
          url: item.template.url,
          text: item.template.en
        }
        audioInfos.unshift(tempItem)
      }

      let wordItem = {
        tag: 'word',
        url: item.url,
        text: item.text
      }
      audioInfos.unshift(wordItem)
      item.audioInfos = audioInfos
    // console.log('检查----',audioInfos)
    })
  },

接口返回的数据格式:

输出结果:

播放逻辑:


// 1洗脑听单词,下一个音频判断逻辑
function listenToNext() {

  if (this.hasPlayGroupUrl) {
    this.hasPlayGroupUrl = false
    this.inLogic_xiNaoNext()
    this.listen2NextWord()
  } else {
    let currWordItem = this.data.currWordItem
    
    if(!currWordItem.text){ //判断是否是拓展
      this.expandStart()
      return 
    }

    // 根据innerIdx 判断是否播放到这一组的边缘
    if (this.data.innerIdx < 0) {
      console.log('item??--',this.data.currWordItem)
      if(this.data.currWordItem){ //听写同替到头,切换洗脑听,重复播放间隔音bugFix
        this.playMainUrl()
        this.setData({
          innerIdx: 0
        })
      }
    }
    else if (this.data.innerIdx < currWordItem.audioInfos.length - 1) {
      if (this.isPlayInnerGapAudio) {
        this.isPlayInnerGapAudio = false
        this.playIntervalUrl()
      } else {
        this.isPlayInnerGapAudio = true
        this.data.innerIdx++

        // 如果下一个是同替才播, 其他都不播, 下标++ todo:抽取优化
        if(this.data.dictateSynonym && this.data.modeIndex == 2){
          let nextInfor = currWordItem.audioInfos[this.data.innerIdx]
          if(nextInfor.tag == '同替'){
            this.initAudio()
            let codeUrl = encodeURI(currWordItem.audioInfos[this.data.innerIdx].url)
            this.backgroundAudioManager.src = codeUrl
            this.backgroundAudioManager.playbackRate = parseFloat(this.data.speed)
            this.backgroundAudioManager.play()
            this.setData({
              innerIdx: this.data.innerIdx
            })
          }else {
            this.setData({
              innerIdx: this.data.innerIdx
            })
            this.isPlayInnerGapAudio = false
            this.playIntervalUrl()
          }
        }else {
          this.initAudio()
          let codeUrl = encodeURI(currWordItem.audioInfos[this.data.innerIdx].url)
          this.backgroundAudioManager.src = codeUrl
          this.backgroundAudioManager.playbackRate = parseFloat(this.data.speed)
          this.backgroundAudioManager.play()
          this.setData({
            innerIdx: this.data.innerIdx
          })
        }

      }
    } else {
      if (this.isPlayInterval) {
        this.repetitionCount--
        if (this.repetitionCount <= 0) { //bugFix:播放两遍拓展
          // 播放间隔音
          // 当前没有同替,不播放间隔音
          if(currWordItem.near){
            this.listenPlayInterval()
            this.hasPlayGroupUrl = true
          } else {
            this.hasPlayGroupUrl = false
            this.inLogic_xiNaoNext()
            this.listen2NextWord()
          }

          // 如果到头了,让下标++
          if(this.data.wordIndex == this.data.wordArr.length - 1){
            
            let idx = this.data.wordIndex
            this.setData({
              wordIndex: idx++
            })
          }
        } else if (this.repetitionCount > 0) {

          this.listen2NextWord()
          this.setData({
            innerIdx: -1
          })
        }else {
          this.inLogic_xiNaoNext()
            this.listen2NextWord()
            this.setData({
                innerIdx: -1
            })
        }
      }
    }
  }
}

这次新增的需求:
【需求1】循环听模式,单词听完了,如果有拓展,播放拓展
【需求2】听写模式,如果有同替,可以听写同替

【需求1】
Q: 如何实现?
A:一组音频播放完,检查当前currWordItem是否是拓展,是拓展就播放拓展。是否是拓展的判断如下:

if(!currWordItem.text){ //判断是否是拓展
   this.expandStart()
   return 
}

用字段为空这么判断可能不太优雅,先这样吧

【需求2】
Q: 如何实现?
A: 增加字段 dictateSynonym, 在toNext函数里面判断 如果是dictateSynonym的情况,也调用dictateSynonym:


function toNext() {
  if (util.noRepeatTap(this, 100)) {
    return
  }
  if (this.data.isPlay) {

    if (this.data.isListen) {
      console.log('check idx->',this.data.wordIndex)
      this.listenToNext()
      return
    }

    // 听写同替模式
    if(this.data.dictateSynonym){
      this.listenToNext()
      return
    }

    if (this.isPlayInterval) {
      this.repetitionCount--
      if (this.repetitionCount == 0) {
        this.data.wordIndex++
        this.repetitionCount = parseInt(this.data.repetition)
      }
    }

    // 播放完成
    if (this.data.wordIndex >= this.data.wordArr.length) {
      this.setData({
        isEnd: true,
        isPlay: false,
      })
      this.playChange(this.data.isPlay)
      this.audioFinish()
    } else {
      this.data.currWordItem = this.data.wordArr[this.data.wordIndex]
      if (this.isPlayInterval) {
        var intervalCount = parseInt(this.data.interval)
        this.isPlayInterval = false
        var intervalAudioUrl = ""
        console.log('listen count->',intervalCount)
        switch (intervalCount) {
          case 1:
            intervalAudioUrl = intervalAudio1
            break;
          case 2:
            intervalAudioUrl = intervalAudio2
            break;
          case 3:
            intervalAudioUrl = intervalAudio3
            break;
          case 4:
            intervalAudioUrl = intervalAudio4
            break;
          case 5:
            intervalAudioUrl = intervalAudio5
            break;
          case 7:
            intervalAudioUrl = intervalAudio7
            break;
          case 10:
            intervalAudioUrl = intervalAudio10
            break;
          default:
            intervalAudioUrl = intervalAudio1
            break;
        }
        this.initAudio()
        this.backgroundAudioManager.playbackRate = 1.0
        this.backgroundAudioManager.src = intervalAudioUrl
        this.backgroundAudioManager.play()
      } else {
        console.log(this.data.currWordItem.url)
        this.playMainUrl()
        this.setData({
          currWordItem: this.data.currWordItem,
          wordIndex: this.data.wordIndex,
          percent: (this.data.wordIndex + 1) / this.data.wordArr.length * 100,
        })
      }
    }
  }
}

遇到的问题:
增加播放拓展的逻辑-前进后退-自动播放完切换下一个音频
svSupListen.js listenToNext 一百行逻辑
同步弹窗选中的跟保存的记录

标签:音频,audioInfos,innerIdx,item,currWordItem,播放,data,流程
From: https://www.cnblogs.com/tufei7/p/17342730.html

相关文章

  • 入门案例认证流程图讲解、思路分析
    入门案例认证流程图讲解 概念速查:Authenticcation接口:它的实现类,表示当前访问系统的用户,封装了用户相关信息。AuthenticcationManager接口:定义了认证Authenticcation的方法UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。......
  • SpringSecurity完整流程、如何查看具体的过滤器
    SpringSecurity完整流程SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。这里我们可以看看入门案例中的过滤器。 图中只展示了核心过滤器,其它的非核心过滤器并没有在图中展示。UsernamePasswordAuthenticationFilter:负责处理我们再登录页面填写了......
  • 前后端分离项目登录校验流程、分析需要修改的地方
    前后端分离项目登录校验流程、分析需要修改的地方登录校验流程 原理初探想要知道如何实现自己的登录流程就必须要先知道入门案例中的SpringSecurity的流程。前后端分离项目登录校验流程、分析需要修改的地方......
  • QT中在使用QMediaPlaylist类的insertMedia函数插入新播放文件后,出现播放顺序错误的分
    我下面的这段代码的意图是:当前的播放队列中插入一个播放文件到队首,使其为下一个播放文件。但是并没有达到我的预期。于是在代码中加入一段调试程序,将当前的播放文件的序号打印出来。 调试之后的结果如下:发现无论向播放队列中插入几次,当前的播放序列都是1。如果想要在播放......
  • AI大数据可视化EasyCVR视频融合平台的部署操作流程详解
    EasyCVR视频融合平台基于云边端一体化架构,具有强大的数据接入、处理及分发能力,平台支持海量视频汇聚管理,能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频直播、云端录像、云存储、检索回看、智能告警、平台级联、服务器集群、云台控制与语音对讲、......
  • 《简化iOS APP上架流程,App Uploader助你搞定!》
    转载;http://kxdang.com/topic/appuploader/questions.htmlAppuploader常见错误及解决方法  问题解决秘籍遇到问题,第一个请登录苹果开发者官网检查一遍账号是否有权限,是否被停用,是否过期,是否有协议需要同意,并且在右上角切换账号后检查所有关联的账号是否工作正常,apple......
  • 《简化iOS APP上架流程,App Uploader助你搞定!》
    转载;http://kxdang.com/topic/appuploader/questions.htmlAppuploader常见错误及解决方法  问题解决秘籍遇到问题,第一个请登录苹果开发者官网检查一遍账号是否有权限,是否被停用,是否过期,是否有协议需要同意,并且在右上角切换账号后检查所有关联的账号是否工作正常,apple......
  • 【四二学堂】基于UiBot RPA开发入门---流程判断
    流程块一:dimaa=1Returna流程块二:TracePrint"a的值等于1时执行的模块"流程块三:TracePrint"a的值不等于1时执行的模块"......
  • AI大数据可视化EasyCVR视频融合平台的部署操作流程详解
    EasyCVR视频融合平台基于云边端一体化架构,具有强大的数据接入、处理及分发能力,平台支持海量视频汇聚管理,能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频直播、云端录像、云存储、检索回看、智能告警、平台级联、服务器集群、云台控制与语音对讲、......
  • Scrum of Scrums(SOS)大规模敏捷研发管理流程
    ​ScrumofScrums是轻量化的规模化敏捷管理模式,Leangoo领歌可以完美支持ScrumofScrums多团队敏捷管理。ScrumofScrums的场景ScrumofScrums是指多个敏捷团队共同开发一个大型产品、项目或解决方案。Leangoo提供了多团队场景下的产品路线图规划、需求管理、缺陷管理、分多......