useAudioPlayer.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import { ref } from 'vue';
  2. export function useAudioPlayer() {
  3. let audioContext = null;
  4. let audioQueue = [];
  5. let isPlaying = false;
  6. // 初始化AudioContext
  7. const initAudioContext = () => {
  8. if (!audioContext) {
  9. audioContext = new (window.AudioContext || window.webkitAudioContext)({
  10. sampleRate: 24000 // 匹配TTS采样率
  11. });
  12. }
  13. };
  14. // 播放音频块
  15. const playAudioChunk = async (base64Audio) => {
  16. // console.log('playAudioChunk=========', base64Audio);
  17. initAudioContext();
  18. // 解码Base64音频数据
  19. const audioBytes = Uint8Array.from(atob(base64Audio), c => c.charCodeAt(0));
  20. audioQueue.push(audioBytes);
  21. if (!isPlaying) {
  22. processAudioQueue();
  23. }
  24. };
  25. // 处理音频队列
  26. const processAudioQueue = async () => {
  27. if (audioQueue.length === 0) {
  28. isPlaying = false;
  29. return;
  30. }
  31. isPlaying = true;
  32. const audioData = audioQueue.shift();
  33. try {
  34. const audioBuffer = await audioContext.decodeAudioData(audioData.buffer);
  35. const source = audioContext.createBufferSource();
  36. source.buffer = audioBuffer;
  37. source.connect(audioContext.destination);
  38. source.start(0);
  39. // 播放完成后继续处理队列
  40. source.onended = processAudioQueue;
  41. } catch (error) {
  42. console.error('音频解码失败:', error);
  43. isPlaying = false;
  44. }
  45. };
  46. // 停止播放并清理
  47. const stopPlayback = () => {
  48. if (audioContext) {
  49. audioContext.close().then(() => {
  50. audioContext = null;
  51. });
  52. }
  53. audioQueue = [];
  54. isPlaying = false;
  55. };
  56. return {
  57. playAudioChunk,
  58. stopPlayback
  59. };
  60. }