文章内容介绍 : 主要是使用 vue3 + TypeScript 实现 使用audio标签播放语音列表,并且能够在页面中实时展示当前语音播放的时长
相关知识点文档
链接: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/audio
链接: https://dayjs.fenxianglu.cn/category/plugin.html#duration

在这里插入图片描述

index.vue

<script lang="ts" setup>
import useAudio from './useAudio'

const audioRef = ref<HTMLAudioElement | null>(null) as Ref<HTMLAudioElement | null>
const audioSrcList = ['语音地址1' , '语音地址2' , '语音地址3' .....]

const {
  isPlay: isAudioPlay,
  currentAudioUrl,
  accumulatedCurrentTimeFormat,

  playNextAudio,
  loadAudioData,
  audioTimeUpdate,
  audioPlayClick,
} = useAudio(audioRef, audioSrcList)

</script>
<template>
<div>
	<audio-play v-if="isAudioPlay" class="audio-play" @click="audioPlayClick" />
	<audio-pause v-else class="audio-play" @click="audioPlayClick" />
	<audio
	ref="audioRef" 
	:src="currentAudioUrl" 
	@loadedmetadata="loadAudioData"
	@timeupdate="audioTimeUpdate" 
	@ended="playNextAudio"
	/>
</div>
</template>

逻辑处理 如下 : useAudio.ts

可以创建一个文件单独处理语音的内容 有利于逻辑解耦

import dayjs from 'dayjs'
import type { ComputedRef, Ref } from 'vue'
import { computed, ref } from 'vue'
import duration from 'dayjs/plugin/duration'
import { LOG, turnAudioUrl } from '@/utils'

dayjs.extend(duration)

export default function useAudio(audioRef: Ref<HTMLAudioElement | null>, files: ComputedRef<readonly string[]>) {
  // 是否播放
  const isPlay = ref<boolean>(false)
  // 当前正在播放的下标值
  const currentIndex = ref<number>(0)
  // 语音列表是否全部播放完成
  const isEnd = ref<boolean>(false)
  // 当前正在播放语音的总时长
  const currentAudioDuration = ref<number>(0)
  // 已完成的播放时间
  const completedPlayTime = ref<number>(0)
  // 当前正在播放语音的当前的时间
  const currentAudioCurrentTime = ref<number>(0)
  // 当前已播放的时间 :页面中展示(00:00:00)
  const accumulatedCurrentTimeFormat = computed<string>(() => dayjs.duration(completedPlayTime.value + currentAudioCurrentTime.value, 'seconds').format('HH:mm:ss'))
  // 当前音频地址
  const currentAudioUrl = computed<string>(() => turnAudioUrl(files.value[currentIndex.value]))

  // 获取语音总时长
  function loadAudioData(): void {
    if (!audioRef.value)
      return
    currentAudioDuration.value = audioRef.value.duration
  }

  // 获取语音当前播放时长
  function audioTimeUpdate(): void {
    if (!audioRef.value)
      return
    currentAudioCurrentTime.value = audioRef.value.currentTime
  }

  function player(): void {
    if (!audioRef.value || !audioRef.value.src)
      return

    // 执行播放之前 先判断是否已经全部执行完毕 是否需要重头开始播放
    if (isEnd.value)
      reset()

    audioRef.value.play().catch((error) => {
      LOG.error('视频播放出错', error)
    })
    isPlay.value = true
  }

  function pause(): void {
    if (!audioRef.value || !audioRef.value.src)
      return

    audioRef.value.pause()
    isPlay.value = false
  }

  function audioPlayClick(): void {
    isPlay.value ? pause() : player()
  }

  function playNextAudio(): void {
    if (currentIndex.value < files.value.length - 1) {
      completedPlayTime.value += currentAudioDuration.value
      currentIndex.value++
      loadCurrentAudio()
    }
    else {
      pause()
      isEnd.value = true
    }
  }

  // 加载音频
  function loadCurrentAudio(): void {
    if (audioRef.value) {
      audioRef.value.src = currentAudioUrl.value
      audioRef.value.load()
      audioRef.value.onloadedmetadata = () => {
        player()
      }
    }
  }

  // 重新开始 :重置数据
  function reset(): void {
    currentIndex.value = 0
    completedPlayTime.value = 0
    isEnd.value = false
  }

  return {
    isPlay,
    currentAudioUrl,
    accumulatedCurrentTimeFormat,
    loadAudioData,
    audioTimeUpdate,
    audioPlayClick,
    pause,
    playNextAudio,
    reset,
  }
}

关键思路 :

1. 通过currentIndex 下标控制当前是播放第几个,每段音频放完都会触发 ended 事件,在这个事件中做处理即可
2. 能通过computed计算出来的就不需要再定义一个变量(谨记 : 多一个变量就多一个维护)
3. 在页面上展示实时播放的当前语音的时长 ,思路 : 拿到每次已完成播放的语音时间 + 当前正在播放的语音时间 = 当前语音播放的时长 (可以使用 dayjs库实现转换 成00:00:00 放到页面中展示)
4. 需要定义一个 变量表示当前是否的语音列表是否播放完成,因为如果播放已完成后,再次播放 需要从列表中的第一个开始播放 , 这个地方要注意 !!!!!!
5. 迷惑的点 : 在测试的过程中 , 偶发触发不了ended事件,还没有查到真正的原因
今日份分享就到这里啦,希望能够帮助到你们
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐