音频流式播放——vue实践

内容分享5小时前发布
0 1 0

在大模型应用中,有时需要将模型输出的内容使用语音播报出来。由于大模型一般是流式输出,然后服务端需要将一段段的文字转成语音再推给前端。

之前的文章中介绍过服务端给前端推送mp3格式的音频字节流。那么前端该如何处理呢?

前端是vue框架,我们可以直接使用MediaSource的sequence模式来流式播放音频。直接看代码

const audioRef = ref(null);
const sourceBuffer = ref(null)
const mediaSource = ref(null)

// 服务端推送的音频流处理
const appendVideoBlob = async (blob) => {
  blobToArrayBuffer(blob)
    .then(arrayBuffer => {
      sourceBuffer.value.appendBuffer(new Uint8Array(arrayBuffer));
    })
    .catch(error => {
      console.error(error);
    });
}

export const blobToArrayBuffer = async (blob) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    // 当读取操作成功完成时触发
    reader.onload = () => {
      resolve(reader.result);
    };

    // 当发生错误时触发
    reader.onerror = () => {
      reject(new Error('Failed to read the blob as an ArrayBuffer'));
    };

    // 开始读取 Blob 数据作为 ArrayBuffer
    reader.readAsArrayBuffer(blob);
  });
}


// 播放
const startStreaming = () => {
  console.warn('startStreaming')
  if ('MediaSource' in window && MediaSource.isTypeSupported('audio/mpeg')) {
    console.log('support mediaSource')
    mediaSource.value = new MediaSource()
    audioRef.value.src = URL.createObjectURL(mediaSource.value);
    mediaSource.value.addEventListener('sourceopen', () => {
      sourceBuffer.value = mediaSource.value.addSourceBuffer('audio/mpeg');
      sourceBuffer.value.mode = 'sequence'
      sourceBuffer.value.addEventListener('updateend', () => {
        console.log('update end current buffers length:' + mediaSource.value.sourceBuffers.length)
        if (!mediaSource.value.sourceBuffers.length) return
        // Play the audio after appending the buffer
        audioRef.value.play().catch(error => console.error('Play failed:', error));
      });
      sourceBuffer.value.addEventListener('updateend', () => {
        // console.error('sourceBuffer update end')
      })
      mediaSource.value.addEventListener('sourceended', function () {
        console.error('MediaSource ended.');
      });

      mediaSource.value.addEventListener('sourceclose', function () {
        console.error('MediaSource closed.');
      });

    });

    mediaSource.value.addEventListener('error', event => {
      console.error('MediaSource error:', event.target.error);
    });

  } else {
    console.error("Your browser doesn't support MediaSource API.");
  }

}

除了这种方式之外,也可以使用第三方工具库,封装的更简洁,但实践中可能会遇到一些问题。直接用MediaSource来写是比较稳定兼容性良好的方式。

这样我们从前后端整个流程就可以完成大模型+语音播报功能啦,如果是数字人也差不多,音频换成视频而已。

© 版权声明

相关文章

1 条评论

您必须登录才能参与评论!
立即登录
  • 头像
    易小模 读者

    收藏了,感谢分享

    无记录