dangdang 1 mēnesi atpakaļ
vecāks
revīzija
b885953f74
1 mainītis faili ar 175 papildinājumiem un 86 dzēšanām
  1. 175 86
      src/views/ChatTts.vue

+ 175 - 86
src/views/ChatTts.vue

@@ -119,136 +119,225 @@ const handleStopRecord = (message) => {
   sessionId.value = generateSessionId();
   chatGpt(message);
 };
-let audioQueue = [];  // 音频队列,保存按请求顺序的音频数据
-let playingQueue = []; // 用来记录当前正在播放的音频序号
-let isPlaying = false;  // 当前是否正在播放
-let orderId = 0;  // 请求顺序号
+// let audioQueue = [];  // 音频队列,保存按请求顺序的音频数据
+// let playingQueue = []; // 用来记录当前正在播放的音频序号
+// let isPlaying = false;  // 当前是否正在播放
+// let orderId = 0;  // 请求顺序号
 
 // 用来控制正在播放音频的锁定机制
 let playingLock = false;  // 标识是否正在播放
 
-// 1. 发起 TTS 请求
-// const playTTS = async (ttsMessage) => {
-//   const currentOrderId = orderId++;  // 获取当前请求的顺序号
-
-//   try {
-//     // 发起请求
-//     const res = await axios.get(
-//         `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`,
-//         { responseType: "arraybuffer" }
-//     );
 
-//     // 将音频数据和顺序号一起存入 audioQueue
-//     audioQueue.push({ orderId: currentOrderId, audioData: res.data });
+let audioQueue = [];  // 音频队列,保存按请求顺序的音频数据
+let playingQueue = []; // 记录已播放的音频序号
+let isPlaying = false;  // 当前是否正在播放
+let orderId = 0;  // 请求顺序号
 
-//     // 如果当前没有音频在播放,开始播放
-//     if (!isPlaying && !playingLock) {
-//       await playNextAudio();  // 开始播放
-//     }
-//   } catch (error) {
-//     console.error("调用 TTS API 时出错:", error);
-//   }
-// };
+// 1. 发起 TTS 请求(修改后)
 const playTTS = async (ttsMessage) => {
   queue.add(async () => {
-    const currentOrderId = orderId++;
+    const currentOrderId = orderId++;  // 先获取顺序号再发送请求
 
     try {
       const res = await axios.get(
         `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`,
         { responseType: "arraybuffer" }
       );
-      if (!res.data || res.data.byteLength === 0) {
-        console.error("音频数据无效,无法播放.");
-        return;
-      }
-      // 按顺序存入音频队列
-      audioQueue.push({ orderId: currentOrderId, audioData: res.data });
-
-      // 仅在没有播放时启动播放
-      if (!isPlaying) {
-        await playNextAudio();
-      }
+      
+      // 即使请求失败也要保持队列连续性(新增部分)
+      const audioItem = {
+        orderId: currentOrderId,
+        audioData: res.data || null,
+        status: res.data ? 'valid' : 'invalid'
+      };
+      
+      audioQueue.push(audioItem);
+      audioQueue.sort((a, b) => a.orderId - b.orderId);  // 保持队列有序
+
+      if (!isPlaying) await playNextAudio();
     } catch (error) {
       console.error("调用 TTS API 时出错:", error);
+      // 请求失败时插入占位符保持顺序(关键修复)
+      audioQueue.push({ 
+        orderId: currentOrderId,
+        audioData: null,
+        status: 'invalid'
+      });
+      audioQueue.sort((a, b) => a.orderId - b.orderId);
+      if (!isPlaying) await playNextAudio();
     }
   });
 };
-// 2. 播放下一个音频
+
+// 2. 播放下一个音频(修改后)
 const playNextAudio = async () => {
-  // 如果播放队列为空,停止播放
   if (audioQueue.length === 0) {
-    isPlaying = false;  // 播放完所有音频
-    // audioQueue = []; // 确保列表为空
+    isPlaying = false;
     console.log("所有音频播放完毕.");
     return;
   }
 
-  // 找到队列中最小序号的音频,确保顺序播放
   const nextAudio = getNextAudioToPlay();
-  console.log(nextAudio,"没有找到下一个应该播放的音频,队列尚未按顺序准备好.");
-
-  // 如果找不到下一个应该播放的音频,表示队列还没有按顺序准备好
   if (!nextAudio) {
-    console.log("没有找到下一个应该播放的音频,队列尚未按顺序准备好.");
-    console.log("当前音频队列:", audioQueue);  // 打印当前音频队列
-    console.log("当前已播放的序列:", playingQueue);  // 打印已经播放的音频序列
+    console.log("等待后续音频数据...");
     return;
   }
 
-  // 打印正在播放的音频序号
-  console.log(`正在播放音频,序号:${nextAudio.orderId}`);
-
   try {
-    isPlaying = true;  // 标记当前正在播放
-    playingLock = true;  // 锁定播放,避免新的音频插入
+    isPlaying = true;
+    console.log(`正在播放音频,序号:${nextAudio.orderId}`);
 
-    // 播放当前音频
-    await playAudio(nextAudio.audioData);
+    if (nextAudio.status === 'valid') {
+      await playAudio(nextAudio.audioData);
+    } else {
+      console.warn(`跳过无效音频,序号:${nextAudio.orderId}`);
+    }
 
-    // 播放完成后,移除已播放的音频
+    // 更新播放状态(优化处理)
+    playingQueue = [...new Set([...playingQueue, nextAudio.orderId])].sort((a, b) => a - b);
     audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);
-    playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录
-
-    // 输出音频播放完成的日志
-    console.log(`音频序号 ${nextAudio.orderId} 播放完成,等待播放下一个包...`);
-
-    // 解除锁定,等待下一个音频播放
-    playingLock = false;
 
-    // 使用定时器周期性检查是否可以播放下一个音频
-    const checkNextAudioTimer = setInterval(async () => {
-      if (!playingLock) {
-        await playNextAudio();
-        clearInterval(checkNextAudioTimer);  // 清除定时器
-      }
-    }, 300); // 每秒检查一次
+    // 立即尝试播放下一个(优化播放流程)
+    isPlaying = false;
+    await playNextAudio();
   } catch (error) {
-    console.error(`播放音频序号 ${nextAudio.orderId} 时出错:`, error);
-    // 如果某个音频播放失败,跳过这个音频,继续播放下一个
-    audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);  // 移除报错的音频
-    playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录
-    playingLock = false;  // 解除锁定
-    // 继续播放下一个音频
+    console.error(`播放失败,序号:${nextAudio.orderId}`, error);
+    audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);
+    isPlaying = false;
     await playNextAudio();
   }
 };
 
-// 获取下一个应该播放的音频(保证顺序
+// 获取下一个应该播放的音频(修改后
 const getNextAudioToPlay = () => {
-  // 检查音频队列中是否有下一个应该播放的音频
-  console.log("检查下一个播放的音频...");
-  for (let i = 0; i < audioQueue.length; i++) {
-    const audio = audioQueue[i];
-    // 找到最小的序号,即请求的顺序号
-    if (audio.orderId === playingQueue.length) {
-      console.log(`找到了下一个应该播放的音频,序号:${audio.orderId}`);
-      return audio;
+  // 获取当前应该播放的最小序号
+  const expectedOrderId = playingQueue.length > 0 
+    ? Math.max(...playingQueue) + 1 
+    : 0;
+
+  // 查找第一个匹配的有效音频(新增有效性检查)
+  const nextAudio = audioQueue.find(audio => 
+    audio.orderId === expectedOrderId &&
+    audio.status === 'valid'
+  );
+
+  // 如果找不到有效音频但有序号匹配的无效项,跳过该序号
+  if (!nextAudio) {
+    const invalidAudio = audioQueue.find(audio => 
+      audio.orderId === expectedOrderId
+    );
+    
+    if (invalidAudio) {
+      console.warn(`检测到无效音频,自动跳过序号:${expectedOrderId}`);
+      playingQueue.push(expectedOrderId);
+      return getNextAudioToPlay(); // 递归处理
     }
   }
-  console.log("没有找到下一个应该播放的音频,返回 null");
-  return null;  // 如果没有找到匹配的音频,返回 null
+
+  return nextAudio || null;
 };
+// 1. 发起 TTS 请求
+
+// const playTTS = async (ttsMessage) => {
+//   queue.add(async () => {
+//     const currentOrderId = orderId++;
+
+//     try {
+//       const res = await axios.get(
+//         `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`,
+//         { responseType: "arraybuffer" }
+//       );
+//       if (!res.data || res.data.byteLength === 0) {
+//         console.error("音频数据无效,无法播放.");
+//         return;
+//       }
+//       // 按顺序存入音频队列
+//       audioQueue.push({ orderId: currentOrderId, audioData: res.data });
+
+//       // 仅在没有播放时启动播放
+//       if (!isPlaying) {
+//         await playNextAudio();
+//       }
+//     } catch (error) {
+//       console.error("调用 TTS API 时出错:", error);
+//     }
+//   });
+// };
+// 2. 播放下一个音频
+// const playNextAudio = async () => {
+//   // 如果播放队列为空,停止播放
+//   if (audioQueue.length === 0) {
+//     isPlaying = false;  // 播放完所有音频
+//     // audioQueue = []; // 确保列表为空
+//     console.log("所有音频播放完毕.");
+//     return;
+//   }
+
+//   // 找到队列中最小序号的音频,确保顺序播放
+//   const nextAudio = getNextAudioToPlay();
+//   console.log(nextAudio,"没有找到下一个应该播放的音频,队列尚未按顺序准备好.");
+
+//   // 如果找不到下一个应该播放的音频,表示队列还没有按顺序准备好
+//   if (!nextAudio) {
+//     console.log("没有找到下一个应该播放的音频,队列尚未按顺序准备好.");
+//     console.log("当前音频队列:", audioQueue);  // 打印当前音频队列
+//     console.log("当前已播放的序列:", playingQueue);  // 打印已经播放的音频序列
+//     return;
+//   }
+
+//   // 打印正在播放的音频序号
+//   console.log(`正在播放音频,序号:${nextAudio.orderId}`);
+
+//   try {
+//     isPlaying = true;  // 标记当前正在播放
+//     playingLock = true;  // 锁定播放,避免新的音频插入
+
+//     // 播放当前音频
+//     await playAudio(nextAudio.audioData);
+
+//     // 播放完成后,移除已播放的音频
+//     audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);
+//     playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录
+
+//     // 输出音频播放完成的日志
+//     console.log(`音频序号 ${nextAudio.orderId} 播放完成,等待播放下一个包...`);
+
+//     // 解除锁定,等待下一个音频播放
+//     playingLock = false;
+
+//     // 使用定时器周期性检查是否可以播放下一个音频
+//     const checkNextAudioTimer = setInterval(async () => {
+//       if (!playingLock) {
+//         await playNextAudio();
+//         clearInterval(checkNextAudioTimer);  // 清除定时器
+//       }
+//     }, 300); // 每秒检查一次
+//   } catch (error) {
+//     console.error(`播放音频序号 ${nextAudio.orderId} 时出错:`, error);
+//     // 如果某个音频播放失败,跳过这个音频,继续播放下一个
+//     audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);  // 移除报错的音频
+//     playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录
+//     playingLock = false;  // 解除锁定
+//     // 继续播放下一个音频
+//     await playNextAudio();
+//   }
+// };
+
+// 获取下一个应该播放的音频(保证顺序)
+// const getNextAudioToPlay = () => {
+//   // 检查音频队列中是否有下一个应该播放的音频
+//   console.log("检查下一个播放的音频...");
+//   for (let i = 0; i < audioQueue.length; i++) {
+//     const audio = audioQueue[i];
+//     // 找到最小的序号,即请求的顺序号
+//     if (audio.orderId === playingQueue.length) {
+//       console.log(`找到了下一个应该播放的音频,序号:${audio.orderId}`);
+//       return audio;
+//     }
+//   }
+//   console.log("没有找到下一个应该播放的音频,返回 null");
+//   return null;  // 如果没有找到匹配的音频,返回 null
+// };
 
 // 播放音频的方法
 const playAudio = (audioData) => {