diff --git a/main/xiaozhi-server/core/providers/tts/alibl_stream.py b/main/xiaozhi-server/core/providers/tts/alibl_stream.py index 4ab30593..7618cbbd 100644 --- a/main/xiaozhi-server/core/providers/tts/alibl_stream.py +++ b/main/xiaozhi-server/core/providers/tts/alibl_stream.py @@ -145,6 +145,8 @@ class TTSProvider(TTSProviderBase): elif ContentType.TEXT == message.content_type: if message.content_detail: try: + # 保存原始文本用于流式响应时显示/上报 + self.store_tts_text(self.conn.sentence_id, message.content_detail) logger.bind(tag=TAG).debug( f"开始发送TTS文本: {message.content_detail}" ) diff --git a/main/xiaozhi-server/core/providers/tts/aliyun_stream.py b/main/xiaozhi-server/core/providers/tts/aliyun_stream.py index 66a0df9c..0479cd15 100644 --- a/main/xiaozhi-server/core/providers/tts/aliyun_stream.py +++ b/main/xiaozhi-server/core/providers/tts/aliyun_stream.py @@ -251,6 +251,8 @@ class TTSProvider(TTSProviderBase): elif ContentType.TEXT == message.content_type: if message.content_detail: try: + # 保存原始文本用于流式响应时显示/上报 + self.store_tts_text(self.conn.sentence_id, message.content_detail) logger.bind(tag=TAG).debug( f"开始发送TTS文本: {message.content_detail}" ) diff --git a/main/xiaozhi-server/core/providers/tts/huoshan_double_stream.py b/main/xiaozhi-server/core/providers/tts/huoshan_double_stream.py index a6ecc21c..4dbacda9 100644 --- a/main/xiaozhi-server/core/providers/tts/huoshan_double_stream.py +++ b/main/xiaozhi-server/core/providers/tts/huoshan_double_stream.py @@ -321,6 +321,8 @@ class TTSProvider(TTSProviderBase): elif ContentType.TEXT == message.content_type: if message.content_detail: try: + # 保存原始文本用于流式响应时显示/上报 + self.store_tts_text(self.conn.sentence_id, message.content_detail) logger.bind(tag=TAG).debug( f"开始发送TTS文本: {message.content_detail}" ) @@ -511,11 +513,14 @@ class TTSProvider(TTSProviderBase): logger.bind(tag=TAG).debug(f"释放服务端资源成功~~") self.activate_session = False elif not self.resource_type and res.optional.event == EVENT_TTSSentenceStart: - json_data = json.loads(res.payload.decode("utf-8")) - self.tts_text = json_data.get("text", "") - logger.bind(tag=TAG).debug(f"句子语音生成开始: {self.tts_text}") + # 使用保存的原始文本用于显示/上报(而不是服务端返回的替换后文本) + tts_text = self.get_tts_text(self.conn.sentence_id) + if not tts_text: + json_data = json.loads(res.payload.decode("utf-8")) + tts_text = json_data.get("text", "") + logger.bind(tag=TAG).debug(f"句子语音生成开始: {tts_text}") self.tts_audio_queue.put( - (SentenceType.FIRST, [], self.tts_text) + (SentenceType.FIRST, [], tts_text) ) elif ( res.optional.event == EVENT_TTSResponse diff --git a/main/xiaozhi-server/core/providers/tts/index_stream.py b/main/xiaozhi-server/core/providers/tts/index_stream.py index 7314ac9c..d1616874 100644 --- a/main/xiaozhi-server/core/providers/tts/index_stream.py +++ b/main/xiaozhi-server/core/providers/tts/index_stream.py @@ -97,7 +97,7 @@ class TTSProvider(TTSProviderBase): if self._correct_words_pattern: text = self._correct_words_pattern.sub(lambda m: self.correct_words[m.group(0)], text) try: - asyncio.run(self.text_to_speak(text, is_last)) + asyncio.run(self.text_to_speak(text, original_text, is_last)) except Exception as e: logger.bind(tag=TAG).warning( f"语音生成失败{5 - max_repeat_time + 1}次: {original_text},错误: {e}" @@ -117,7 +117,7 @@ class TTSProvider(TTSProviderBase): finally: return None - async def text_to_speak(self, text, is_last): + async def text_to_speak(self, text, original_text, is_last): """流式处理TTS音频,每句只推送一次音频列表""" payload = {"text": text, "character": self.voice} @@ -140,7 +140,7 @@ class TTSProvider(TTSProviderBase): return self.pcm_buffer.clear() - self.tts_audio_queue.put((SentenceType.FIRST, [], text)) + self.tts_audio_queue.put((SentenceType.FIRST, [], original_text)) # 处理音频流数据 async for chunk in resp.content.iter_any(): diff --git a/main/xiaozhi-server/core/providers/tts/linkerai.py b/main/xiaozhi-server/core/providers/tts/linkerai.py index ecfb8b38..145da1ae 100644 --- a/main/xiaozhi-server/core/providers/tts/linkerai.py +++ b/main/xiaozhi-server/core/providers/tts/linkerai.py @@ -89,7 +89,7 @@ class TTSProvider(TTSProviderBase): if self._correct_words_pattern: text = self._correct_words_pattern.sub(lambda m: self.correct_words[m.group(0)], text) try: - asyncio.run(self.text_to_speak(text, is_last)) + asyncio.run(self.text_to_speak(text, original_text, is_last)) except Exception as e: logger.bind(tag=TAG).warning( f"语音生成失败{5 - max_repeat_time + 1}次: {original_text},错误: {e}" @@ -109,9 +109,9 @@ class TTSProvider(TTSProviderBase): finally: return None - async def text_to_speak(self, text, is_last): + async def text_to_speak(self, text, original_text, is_last): """流式处理TTS音频,每句只推送一次音频列表""" - await self._tts_request(text, is_last) + await self._tts_request(text, original_text, is_last) async def close(self): """资源清理""" @@ -119,7 +119,7 @@ class TTSProvider(TTSProviderBase): if hasattr(self, "opus_encoder"): self.opus_encoder.close() - async def _tts_request(self, text: str, is_last: bool) -> None: + async def _tts_request(self, text: str, original_text: str, is_last: bool) -> None: params = { "tts_text": text, "spk_id": self.voice, @@ -157,7 +157,7 @@ class TTSProvider(TTSProviderBase): return self.pcm_buffer.clear() - self.tts_audio_queue.put((SentenceType.FIRST, [], text)) + self.tts_audio_queue.put((SentenceType.FIRST, [], original_text)) # 兼容 iter_chunked / iter_chunks / iter_any async for chunk in resp.content.iter_any(): diff --git a/main/xiaozhi-server/core/providers/tts/minimax_httpstream.py b/main/xiaozhi-server/core/providers/tts/minimax_httpstream.py index f620adfb..b6ad1a9d 100644 --- a/main/xiaozhi-server/core/providers/tts/minimax_httpstream.py +++ b/main/xiaozhi-server/core/providers/tts/minimax_httpstream.py @@ -153,7 +153,7 @@ class TTSProvider(TTSProviderBase): if self._correct_words_pattern: text = self._correct_words_pattern.sub(lambda m: self.correct_words[m.group(0)], text) try: - asyncio.run(self.text_to_speak(text, is_last)) + asyncio.run(self.text_to_speak(text, original_text, is_last)) except Exception as e: logger.bind(tag=TAG).warning( f"语音生成失败{5 - max_repeat_time + 1}次: {original_text},错误: {e}" @@ -173,7 +173,7 @@ class TTSProvider(TTSProviderBase): finally: return None - async def text_to_speak(self, text, is_last): + async def text_to_speak(self, text, original_text, is_last): """流式处理TTS音频,每句只推送一次音频列表""" payload = { "model": self.model, @@ -212,7 +212,7 @@ class TTSProvider(TTSProviderBase): return self.pcm_buffer.clear() - self.tts_audio_queue.put((SentenceType.FIRST, [], text)) + self.tts_audio_queue.put((SentenceType.FIRST, [], original_text)) # 处理音频流数据 buffer = b"" diff --git a/main/xiaozhi-server/core/providers/tts/xunfei_stream.py b/main/xiaozhi-server/core/providers/tts/xunfei_stream.py index 812c282b..9baed36c 100644 --- a/main/xiaozhi-server/core/providers/tts/xunfei_stream.py +++ b/main/xiaozhi-server/core/providers/tts/xunfei_stream.py @@ -197,6 +197,8 @@ class TTSProvider(TTSProviderBase): if ContentType.TEXT == message.content_type: if message.content_detail: try: + # 保存原始文本用于流式响应时显示/上报 + self.store_tts_text(self.conn.sentence_id, message.content_detail) logger.bind(tag=TAG).debug( f"开始发送TTS文本: {message.content_detail}" )