vue 移动端:语音播放--原生audio(类似百度翻译的语音播放)

996 阅读1分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

可下载进行测试的音频网站

→点击可查看---可下载的音频网站

1.效果图

在这里插入图片描述

上图效果的代码请查看博文→点击可查看(写成了父子组件形式)

我目前写的主要展示的是单个语音的播放,如下图所示,我参考的文章地址是 → 点击可查看

效果图

多个语音的播放顺序问题,可查看文章→点击可查看

2.一些audio相关的代码知识

// 重新加载
this.audio.load();
 
// 判断是否正在播放 返回布尔值
this.audio.paused
 
// 暂停
this.audio.pause();
this.audio = new Audio();
this.audio.src = mp3;
let playPromise; 
playPromise = this.audio.play();
if (playPromise) {
        playPromise.then(() => {
            // 音频加载成功
            // 音频的播放需要耗时
          that.tiemr = setInterval(() => {
            second--;
            if (second <= 0) {
              that.audio.pause()
              clearInterval(that.tiemr);
            }
          }, 1000);
        }).catch((e) => {
          // 音频加载失败
          console.error(e);
        });
      }

3.上图效果代码展示--vue项目

<template>
	<div>
	    ...
		<div v-if="this.noCompleteAnswerList.code==='1' || this.noCompleteAnswerList.code==='2' || this.noCompleteAnswerList.code==='3'" class="questionName" @click="startPlayOrPause">
		    <audio ref="audio"
		      :src="urlAudio"
		      :preload="audio.preload"
		      @play="onPlay"
		      @error="onError"
		      @waiting="onWaiting"
		      @pause="onPause"
		      @timeupdate="onTimeupdate"
		      @loadedmetadata="onLoadedmetadata">
		    </audio>
		      <div class="imgLaba">
		        <img src="@/assets/image/laba1.png" alt="" v-if="isShowImgAudio">
		        <img src="@/assets/image/laba2.gif" alt="" v-else >
		      </div>
		  </div>
		  <span class="questionName">{{this.noCompleteAnswerList.thisQueIndex}}、{{noCompleteAnswerList.title}}</span>
		</div>
		...
	</div>
</template>
<script>
...
export default {
  data () {
    return {
      ...
      isShowImgAudio: true, // 进入题型时展示的是静态喇叭
      // 播放语音播报
      audio: {
        currentTime: 0,
        maxTime: 0,
        playing: true, // 是否自动播放
        muted: false, // 是否静音
        speed: '',
        waiting: true,
        preload: 'auto'
      },
      sliderTime: 0,
      volume: 100,
      speeds: this.theSpeeds,
      controlList: {
        // 不显示下载
        noDownload: false,
        // 不显示静音
        noMuted: false,
        // 不显示音量条
        noVolume: false,
        // 不显示进度条
        noProcess: false,
        // 只能播放一个
        onlyOnePlaying: false,
        // 不要快进按钮
        noSpeed: false
      },
      urlAudio: '',
      ...
	}
  },
  methods: {
    // 当音频暂停
    onPause () {
      this.audio.playing = false
    },
    // 当发生错误, 就出现loading状态
    onError () {
      this.audio.waiting = true
    },
    // 当音频开始等待
    onWaiting (res) {
      // console.log(res)
    },
    // 开始播放
    startPlay () {
      this.$refs.audio.play()
    },
    // 暂停
    pausePlay () {
      this.$refs.audio.pause()
    },
    // 触发喇叭的时候
    startPlayOrPause () {
      // 判断是否正在播放
      if (this.$refs.audio.paused) {
        // 播放
        this.$refs.audio.play()
        this.isShowImgAudio = false
        // console.log(1)
      } else {
        // 暂停\重播
        this.$refs.audio.currentTime = 0 // 重新播放
        this.$refs.audio.play()
        // this.isShowImgAudio = true // 暂停
        // this.$refs.audio.pause()
        // console.log(2)
      }
    },
    // 调取接口--获取audio的url音频地址
    getUrlAudio () {
      return new Promise(resolve => {
        const params = { paperLogOid: this.noCompleteAnswerList.tbPaperLogoid }
        this.api.voiceQuestions(params).then(res => {
          // console.log('111111111111', res)
          if (res.code === 200) {
            this.urlAudio = res.data
            resolve()
          }
        })
      })
    },
    // 当音频开始播放
    onPlay (res) {
      this.audio.playing = true
      this.audio.loading = false

      if (!this.controlList.onlyOnePlaying) {
        return
      }
      const target = res.target
      const audios = document.getElementsByTagName('audio');
      [...audios].forEach((item) => {
        if (item !== target) {
          item.pause()
        }
      })
    },
    // 当timeupdate事件大概每秒一次,用来更新音频流的当前播放时间
    onTimeupdate (res) {
      this.audio.currentTime = res.target.currentTime
      this.sliderTime = parseInt(this.audio.currentTime / this.audio.maxTime * 100)
      if (res.target.currentTime === res.target.duration) { // 当播放时长与总当前时长 相等时喇叭的图片展示为静止图片
        this.isShowImgAudio = true
      }
    },
    // 当加载语音流元数据完成后,会触发该事件的回调函数
    // 语音元数据主要是语音的长度之类的数据
    onLoadedmetadata (res) {
      this.audio.waiting = false
      this.audio.maxTime = parseInt(res.target.duration)
      // this.audio.maxTime = parseInt( this.$refs.audio.duration);
      // console.log('总时间', this.$refs.audio.duration)
      this.$emit('loading-true', 11)
    },
  }
  ...
}
</script>