前端实现音频的简单播放与停止

4 阅读1分钟

背景:前端UI上有两个按钮【试听】【停止】,要求点击试听的时候播放音频,点击停止的时候停止播放,后端返回的.wav字节流

实现:拉取二进制Blob播放

const audioPlayer = ref(null)
const audioObjectUrl = ref('')

const handlePreview = async () => {
  try {
    const res = await apis.system.getVoicePreview({
      voiceSpeed: speed.value,
      voiceType: AudioTypeShort[audioType.value],
    })

    if (!audioPlayer.value) {
      audioPlayer.value = new Audio()
    }

    if (audioObjectUrl.value) {
      URL.revokeObjectURL(audioObjectUrl.value)
      audioObjectUrl.value = ''
    }

    let audioBlob = res?.data
    if (audioBlob instanceof ArrayBuffer) {
      audioBlob = new Blob([audioBlob], { type: 'audio/wav' })
    }
    if (!audioBlob || !(audioBlob instanceof Blob)) {
      console.error('获取音频失败: 响应不是音频 Blob')
      return
    }

    audioObjectUrl.value = URL.createObjectURL(audioBlob)
    audioPlayer.value.src = audioObjectUrl.value
    audioPlayer.value.currentTime = 0
    await audioPlayer.value.play()
  } catch (error) {
    console.error('试听失败:', error)
  }
}

const handleStop = () => {
  if (!audioPlayer.value) return
  audioPlayer.value.pause()
  audioPlayer.value.currentTime = 0
  if (audioObjectUrl.value) {
    URL.revokeObjectURL(audioObjectUrl.value)
    audioObjectUrl.value = ''
  }
}

onBeforeUnmount(() => {
  if (!audioPlayer.value) return
  audioPlayer.value.pause()
  audioPlayer.value.src = ''
  audioPlayer.value = null
  if (audioObjectUrl.value) {
    URL.revokeObjectURL(audioObjectUrl.value)
    audioObjectUrl.value = ''
  }
})

播放音频的方案一般有:

  1. 直接URL播放:后端返回可访问音频URL,前端用或Audio对象控制play()/pause()/currentTime=0.
  2. 拉取二进制Blob播放:前端用fetch拿到音频二进制,URL.createObjectURL(blob)生成本地URL再播放。
  3. Range分段流式播放:后端支持Range请求,前端只请求需要的片段,适合大文件/首播快
  4. MediaSource流式拼接:前端使用MediaSource动态喂数据,适合长音频或自定义流式控制。
  5. WebSocket/实时流:用于实时生成语音(TTS)或直播式音频
  • 短音频、权限简单:优先用“直接 URL 播放”。
  • 需要鉴权/防盗链:用“Blob 播放”或“签名 URL”。
  • 大文件/首播慢:用“Range”或 “HLS”。
  • 实时语音/TTS:用 “WebSocket + MediaSource”。