From 17ac2ce0ed52874616c79c910667e41e34604826 Mon Sep 17 00:00:00 2001
From: wangzhibo <wangzhibo@shsening.com>
Date: 星期一, 31 八月 2026 13:14:12 +0800
Subject: [PATCH] add translation app

---
 xiaozhi-esp32-server/main/xiaozhi-server/core/handle/receiveAudioHandle.py |   92 +++++++++++++++++++++++++++++++++++++++------
 1 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/xiaozhi-esp32-server/main/xiaozhi-server/core/handle/receiveAudioHandle.py b/xiaozhi-esp32-server/main/xiaozhi-server/core/handle/receiveAudioHandle.py
index 504669b..2985600 100644
--- a/xiaozhi-esp32-server/main/xiaozhi-server/core/handle/receiveAudioHandle.py
+++ b/xiaozhi-esp32-server/main/xiaozhi-server/core/handle/receiveAudioHandle.py
@@ -46,22 +46,24 @@
     actual_text = text
 
     try:
-        # 灏濊瘯瑙f瀽JSON鏍煎紡鐨勮緭鍏�
+        # FunASR 绛変細鎶婄粨鏋滃寘鎴� {"content","language","emotion"}锛涘0绾瑰満鏅繕鏈� speaker
         if text.strip().startswith("{") and text.strip().endswith("}"):
             data = json.loads(text)
-            if "speaker" in data and "content" in data:
-                speaker_name = data["speaker"]
-                actual_content = data["content"]
-                conn.logger.bind(tag=TAG).info(f"瑙f瀽鍒拌璇濅汉淇℃伅: {speaker_name}")
-
-                # 浠呭湪璇ヨ璇濅汉棣栨鍑虹幇鏃朵繚鐣� {"speaker":...} JSON锛岃妯″瀷鑷劧绉板懠涓�娆★紱
-                # 鍚庣画杞檷涓虹函鏂囨湰锛岄伩鍏嶆瘡杞噸澶嶅嚭鐜板悕瀛楄瀵兼ā鍨嬪弽澶嶇О鍛�
-                if speaker_name not in conn.introduced_speakers:
-                    conn.introduced_speakers.add(speaker_name)
-                    actual_text = text
-                else:
+            if isinstance(data, dict) and "content" in data:
+                speaker_name = data.get("speaker")
+                actual_content = data.get("content") or ""
+                if speaker_name:
+                    conn.logger.bind(tag=TAG).info(f"瑙f瀽鍒拌璇濅汉淇℃伅: {speaker_name}")
+                    # 浠呭湪璇ヨ璇濅汉棣栨鍑虹幇鏃朵繚鐣� {"speaker":...} JSON锛岃妯″瀷鑷劧绉板懠涓�娆★紱
+                    # 鍚庣画杞檷涓虹函鏂囨湰锛岄伩鍏嶆瘡杞噸澶嶅嚭鐜板悕瀛楄瀵兼ā鍨嬪弽澶嶇О鍛�
+                    if speaker_name not in conn.introduced_speakers:
+                        conn.introduced_speakers.add(speaker_name)
+                        actual_text = text
+                    else:
+                        actual_text = actual_content
+                elif actual_content:
                     actual_text = actual_content
-    except (json.JSONDecodeError, KeyError):
+    except (json.JSONDecodeError, KeyError, TypeError):
         # 濡傛灉瑙f瀽澶辫触锛岀户缁娇鐢ㄥ師濮嬫枃鏈�
         pass
 
@@ -83,6 +85,70 @@
             await max_out_size(conn)
             return
 
+    from core.app_runtime.runtime import (
+        is_exit_translation,
+        match_voice_switch,
+        run_translation,
+        start_app_task,
+        VOICE_MENU,
+    )
+    from core.handle.intentHandler import speak_txt
+
+    mode = getattr(conn, "interaction_mode", "CHAT")
+
+    if getattr(conn, "awaiting_voice_app_choice", False):
+        mapped = match_voice_switch(actual_text)
+        conn.awaiting_voice_app_choice = False
+        if mapped and mapped[0] == "__reserved__":
+            speak_txt(conn, "杩欎釜娓告垙杩樻病寮�鏀撅紝鎴戜滑鍏堣亰澶╁惂銆�")
+            await start_app_task(conn, "chat", "conversation", {}, source="voice")
+            return
+        if mapped and mapped[0] == "__menu__":
+            conn.awaiting_voice_app_choice = True
+            speak_txt(conn, VOICE_MENU)
+            return
+        if mapped and mapped[0] != "__menu__":
+            params = {}
+            await start_app_task(conn, mapped[0], mapped[1], params, source="voice")
+            return
+        speak_txt(conn, VOICE_MENU)
+        conn.awaiting_voice_app_choice = True
+        return
+
+    mapped = match_voice_switch(actual_text)
+    if mapped and mapped[0] == "__menu__":
+        conn.awaiting_voice_app_choice = True
+        speak_txt(conn, VOICE_MENU)
+        return
+    if mapped and mapped[0] == "__reserved__":
+        speak_txt(conn, "杩欎釜杩樻病寮�鏀撅紝鍏堢户缁綋鍓嶅唴瀹瑰惂銆�")
+        return
+    if mapped and mapped[0] in ("english_translation", "english_learning", "chat"):
+        if mapped[0] == "english_learning" and mapped[1] == "repeater":
+            speak_txt(conn, "澶嶈闇�瑕佹寚瀹� SD 鍗′笂鐨勬枃浠跺悕锛屾垨鐢ㄥ皬绋嬪簭寮�濮嬨��")
+            return
+        await start_app_task(conn, mapped[0], mapped[1], {}, source="voice")
+        return
+
+    if mode == "PLAY_AUDIO":
+        conn.logger.bind(tag=TAG).info("PLAY_AUDIO 妯″紡蹇界暐涓婅瀵硅瘽")
+        return
+
+    if mode == "TRANSLATION":
+        if is_exit_translation(actual_text):
+            await start_app_task(conn, "chat", "conversation", {}, source="voice")
+            return
+        await send_stt_message(conn, actual_text)
+        conn.client_abort = False
+        translated = await run_translation(conn, actual_text)
+        if not translated:
+            translated = "娌℃湁鍚竻瑕佺炕璇戠殑鍐呭锛岃鍐嶈涓�娆°��"
+        if not conn.sentence_id:
+            import uuid as _uuid
+            conn.sentence_id = _uuid.uuid4().hex
+        speak_txt(conn, translated)
+        return
+
     # manual 妯″紡涓嬩笉鎵撴柇姝e湪鎾斁鐨勫唴瀹�
     if conn.client_is_speaking and conn.client_listen_mode != "manual":
         await handleAbortMessage(conn)

--
Gitblit v1.9.1