diff --git a/core/connection.py b/core/connection.py index cb2d06d0..3f59762f 100644 --- a/core/connection.py +++ b/core/connection.py @@ -153,12 +153,17 @@ class ConnectionHandler: text = None try: future = self.tts_queue.get() + if future is None: + continue text = None try: + self.logger.debug("正在处理TTS任务...") tts_file, text = future.result(timeout=10) + self.logger.debug(f"TTS文件生成完毕,文件路径: {tts_file}") if os.path.exists(tts_file): opus_datas, duration = self.tts.wav_to_opus_data(tts_file) else: + self.logger.error(f"TTS文件不存在: {tts_file}") opus_datas = [] duration = 0 except TimeoutError: @@ -175,6 +180,7 @@ class ConnectionHandler: if self.tts.delete_audio_file and os.path.exists(tts_file): os.remove(tts_file) except Exception as e: + self.logger.error(f"TTS任务处理错误: {e}") self.clearSpeakStatus() asyncio.run_coroutine_threadsafe( self.websocket.send(json.dumps({"type": "tts", "state": "stop", "session_id": self.session_id})), @@ -190,7 +196,7 @@ class ConnectionHandler: if tts_file is None: self.logger.error(f"tts转换失败,{text}") return None - self.logger.debug(f"TTS 文件生成完毕") + self.logger.debug(f"TTS 文件生成完毕: {tts_file}") return tts_file, text def clearSpeakStatus(self): diff --git a/core/handle/audioHandle.py b/core/handle/audioHandle.py index d15d1ff5..4e55d115 100644 --- a/core/handle/audioHandle.py +++ b/core/handle/audioHandle.py @@ -55,60 +55,51 @@ async def startToChat(conn, text): async def sendAudioMessage(conn, audios, duration, text): base_delay = conn.tts_duration + # 发送 tts.start if text == conn.tts_first_text: logger.info(f"发送第一段语音: {text}") conn.tts_start_speak_time = time.time() - await conn.websocket.send(json.dumps({ - "type": "tts", - "state": "start", - "session_id": conn.session_id - })) + await send_tts_message(conn, "start", text) - # 调度文字显示任务 - text_task = asyncio.create_task( - schedule_with_interrupt( - base_delay - 0.5, - send_sentence_start(conn, text) - ) - ) - conn.scheduled_tasks.append(text_task) + # 先等待0.5秒,确保客户端处于 speaking 状态 + await asyncio.sleep(0.5) - conn.tts_duration = conn.tts_duration + duration + # 发送 sentence_start(每个音频文件之前发送一次) + await send_tts_message(conn, "sentence_start", text) + + conn.tts_duration += duration # 发送音频数据 - for opus_packet in audios: + for idx, opus_packet in enumerate(audios): await conn.websocket.send(opus_packet) + # 每个音频文件发送结束时,发送 sentence_end + if idx == len(audios) - 1: + await send_tts_message(conn, "sentence_end", text) + if conn.llm_finish_task and text == conn.tts_last_text: - stop_duration = conn.tts_duration - (time.time() - conn.tts_start_speak_time) + stop_duration = conn.tts_duration - \ + (time.time() - conn.tts_start_speak_time) stop_task = asyncio.create_task( - schedule_with_interrupt(stop_duration, send_tts_stop(conn, text)) + schedule_with_interrupt( + stop_duration, send_tts_message(conn, 'stop')) ) conn.scheduled_tasks.append(stop_task) -async def send_sentence_start(conn, text): - await conn.websocket.send(json.dumps({ +async def send_tts_message(conn, state, text=None): + """发送 TTS 状态消息""" + message = { "type": "tts", - "state": "sentence_start", - "text": text, + "state": state, "session_id": conn.session_id - })) + } + if text is not None: + message["text"] = text - -async def send_tts_stop(conn, text): - await conn.websocket.send(json.dumps({ - "type": "tts", - "state": "sentence_end", - "text": text, - "session_id": conn.session_id - })) - await conn.websocket.send(json.dumps({ - "type": "tts", - "state": "stop", - "session_id": conn.session_id - })) - conn.clearSpeakStatus() + await conn.websocket.send(json.dumps(message)) + if state == "stop": + conn.clearSpeakStatus() async def schedule_with_interrupt(delay, coro):