diff --git a/main/xiaozhi-server/core/handle/sendAudioHandle.py b/main/xiaozhi-server/core/handle/sendAudioHandle.py index 789d61f6..0ae801ed 100644 --- a/main/xiaozhi-server/core/handle/sendAudioHandle.py +++ b/main/xiaozhi-server/core/handle/sendAudioHandle.py @@ -17,7 +17,11 @@ AUDIO_FRAME_DURATION = 60 PRE_BUFFER_COUNT = 5 -async def sendAudioMessage(conn: "ConnectionHandler", sentenceType, audios, text): +async def sendAudioMessage(conn: "ConnectionHandler", sentenceType, audios, text, sentence_id=None): + # 跳过旧句子残留音频 + if sentence_id is not None and sentence_id != conn.sentence_id: + return + if conn.tts.tts_audio_first_sentence: conn.logger.bind(tag=TAG).info(f"发送第一段语音: {text}") conn.tts.tts_audio_first_sentence = False @@ -281,12 +285,14 @@ async def send_tts_message(conn: "ConnectionHandler", state, text=None): await sendAudio(conn, audios) # 等待所有音频包发送完成 await _wait_for_audio_completion(conn) - # 停止音频发送循环(仅在流控器已初始化时调用) - if hasattr(conn, "audio_rate_controller") and conn.audio_rate_controller: - conn.audio_rate_controller.stop_sending() + # 检查是否是当前轮次 if current_sentence_id != conn.sentence_id: return + + # 停止音频发送循环(仅在流控器已初始化时调用) + if hasattr(conn, "audio_rate_controller") and conn.audio_rate_controller: + conn.audio_rate_controller.stop_sending() conn.clearSpeakStatus() # 发送消息到客户端 diff --git a/main/xiaozhi-server/core/providers/tts/base.py b/main/xiaozhi-server/core/providers/tts/base.py index 1a04907a..25ade2d6 100644 --- a/main/xiaozhi-server/core/providers/tts/base.py +++ b/main/xiaozhi-server/core/providers/tts/base.py @@ -83,7 +83,7 @@ class TTSProviderBase(ABC): def handle_opus(self, opus_data: bytes): logger.bind(tag=TAG).debug(f"推送数据到队列里面帧数~~ {len(opus_data)}") - self.tts_audio_queue.put((SentenceType.MIDDLE, opus_data, None)) + self.tts_audio_queue.put((SentenceType.MIDDLE, opus_data, None, getattr(self, 'current_sentence_id', None))) def handle_audio_file(self, file_audio: bytes, text): self.before_stop_play_files.append((file_audio, text)) @@ -97,7 +97,7 @@ class TTSProviderBase(ABC): try: audio_bytes = asyncio.run(self.text_to_speak(text, None)) if audio_bytes: - self.tts_audio_queue.put((SentenceType.FIRST, None, text)) + self.tts_audio_queue.put((SentenceType.FIRST, None, text, getattr(self, 'current_sentence_id', None))) audio_bytes_to_data_stream( audio_bytes, file_type=self.audio_file_type, @@ -146,7 +146,7 @@ class TTSProviderBase(ABC): logger.bind(tag=TAG).error( f"语音生成失败: {text},请检查网络或服务是否正常" ) - self.tts_audio_queue.put((SentenceType.FIRST, None, text)) + self.tts_audio_queue.put((SentenceType.FIRST, None, text, getattr(self, 'current_sentence_id', None))) self._process_audio_file_stream(tmp_file, callback=opus_handler) except Exception as e: logger.bind(tag=TAG).error(f"Failed to generate TTS file: {e}") @@ -327,7 +327,7 @@ class TTSProviderBase(ABC): logger.bind(tag=TAG).info("收到打断信息,终止TTS文本处理线程") continue if message.sentence_type == SentenceType.FIRST: - # 初始化参数 + self.current_sentence_id = message.sentence_id self.tts_stop_request = False self.processed_chars = 0 self.tts_text_buff = [] @@ -348,7 +348,7 @@ class TTSProviderBase(ABC): if message.sentence_type == SentenceType.LAST: self._process_remaining_text_stream(opus_handler=self.handle_opus) self.tts_audio_queue.put( - (message.sentence_type, [], message.content_detail) + (message.sentence_type, [], message.content_detail, message.sentence_id) ) except queue.Empty: @@ -367,9 +367,12 @@ class TTSProviderBase(ABC): text = None try: try: - sentence_type, audio_datas, text = self.tts_audio_queue.get( - timeout=0.1 - ) + item = self.tts_audio_queue.get(timeout=0.1) + if len(item) == 4: + sentence_type, audio_datas, text, sentence_id = item + else: + sentence_type, audio_datas, text = item + sentence_id = None except queue.Empty: if self.conn.stop_event.is_set(): break @@ -404,7 +407,7 @@ class TTSProviderBase(ABC): # 发送音频 future = asyncio.run_coroutine_threadsafe( - sendAudioMessage(self.conn, sentence_type, audio_datas, text), + sendAudioMessage(self.conn, sentence_type, audio_datas, text, sentence_id), self.conn.loop, ) future.result() @@ -493,9 +496,9 @@ class TTSProviderBase(ABC): def _process_before_stop_play_files(self): for audio_datas, text in self.before_stop_play_files: - self.tts_audio_queue.put((SentenceType.MIDDLE, audio_datas, text)) + self.tts_audio_queue.put((SentenceType.MIDDLE, audio_datas, text, getattr(self, 'current_sentence_id', None))) self.before_stop_play_files.clear() - self.tts_audio_queue.put((SentenceType.LAST, [], None)) + self.tts_audio_queue.put((SentenceType.LAST, [], None, getattr(self, 'current_sentence_id', None))) def _process_remaining_text_stream( self, opus_handler: Callable[[bytes], None] = None