You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Base64编码音频数组逐个播放 解决同时播放异常问题

问题根因

你现有代码的逻辑本身是符合顺序播放的设计,出现所有音频同时播放的核心原因是playAudio方法的Promise异常场景覆盖不全:audio.play()是浏览器提供的异步方法,会返回Promise,当遇到浏览器自动播放拦截、音频解码失败等异常情况时,播放流程被打断,onended事件永远不会触发,Promise一直处于pending状态,await逻辑失效,循环会直接进入下一轮,就会出现多个音频同时触发播放的情况。

优化后的代码实现

修改playAudio方法

补充错误监听和异常捕获,避免Promise悬停:

async playAudio(encodedAudio: string) {
  return new Promise<void>((resolve, reject) => {
    const audio = new Audio("data:audio/wav;base64," + encodedAudio);
    // 播放正常结束后resolve
    audio.onended = () => resolve();
    // 音频加载/播放出错时reject,避免Promise永远挂起
    audio.onerror = (error) => reject(error);
    // 处理play方法的异步异常,比如浏览器自动播放策略拦截
    audio.play().catch((error) => reject(error));
  })
}

修改sayChunks方法

增加异常捕获,避免单个音频播放出错打断整个播放序列:

async sayChunks() {
  try {
    const ttsResponses = await this.getTestJson();
    console.log("ttsResponses:", ttsResponses);
    for (const ttsResponse of ttsResponses) 
    {
      console.log("playing audio chunk");
      const encodedAudio = ttsResponse.base64Audio.replace(/['"]+/g, '')
      await this.playAudio(encodedAudio);
      console.log("stopped playing audio chunk");
    }
  } catch (error) {
    console.error("音频播放序列出错:", error);
  }
}

注意事项

  • 浏览器自动播放策略要求音频播放必须由用户交互行为(点击、触摸等事件)回调内触发,如果你是页面加载完成后直接调用sayChunks大概率会被拦截,建议将触发逻辑绑定到按钮点击等用户操作的回调中。
  • 如果音频片段较短对播放连贯性要求高,可以提前预创建所有Audio对象完成解码,避免实时解码base64带来的延迟。

内容的提问来源于stack exchange,提问作者DiracSpace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 01:06:08