From 7974ab3f2b825ed4f70a7aafa35733b5efa3b2bf Mon Sep 17 00:00:00 2001 From: Del Wang Date: Wed, 21 May 2025 19:29:28 +0800 Subject: [PATCH] fix: pause kws on wake up --- examples/xiaozhi/xiaozhi/event.py | 17 ++++++++++- .../xiaozhi/services/audio/kws/__init__.py | 29 ++++++++++++------- examples/xiaozhi/xiaozhi/xiaoai.py | 11 ++----- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/examples/xiaozhi/xiaozhi/event.py b/examples/xiaozhi/xiaozhi/event.py index 634a13c..ef637b6 100644 --- a/examples/xiaozhi/xiaozhi/event.py +++ b/examples/xiaozhi/xiaozhi/event.py @@ -1,7 +1,14 @@ import asyncio from config import APP_CONFIG -from xiaozhi.ref import get_audio_codec, get_speaker, get_vad, get_xiaoai, get_xiaozhi +from xiaozhi.ref import ( + get_audio_codec, + get_kws, + get_speaker, + get_vad, + get_xiaoai, + get_xiaozhi, +) from xiaozhi.services.protocols.typing import AbortReason, DeviceState, ListeningMode @@ -155,5 +162,13 @@ class __EventManager: await xiaozhi.protocol.send_stop_listening() xiaozhi.set_device_state(DeviceState.IDLE) + async def wakeup(self, text, source): + before_wakeup = APP_CONFIG["wakeup"]["before_wakeup"] + get_kws().pause() # 暂停 KWS 检测 + wakeup = await before_wakeup(get_speaker(), text, source) + get_kws().resume() # 恢复 KWS 检测 + if wakeup: + self.on_wakeup() + EventManager = __EventManager() diff --git a/examples/xiaozhi/xiaozhi/services/audio/kws/__init__.py b/examples/xiaozhi/xiaozhi/services/audio/kws/__init__.py index 5003d20..e7b0286 100644 --- a/examples/xiaozhi/xiaozhi/services/audio/kws/__init__.py +++ b/examples/xiaozhi/xiaozhi/services/audio/kws/__init__.py @@ -31,6 +31,7 @@ class _KWS: ) # 启动 KWS 服务 + self.paused = False self.thread = threading.Thread(target=self._detection_loop, daemon=True) self.thread.start() @@ -38,6 +39,12 @@ class _KWS: current_dir = os.path.dirname(os.path.abspath(__file__)) return os.path.join(current_dir, "../../../models", file_name) + def pause(self): + self.paused = True + + def resume(self): + self.paused = False + def _detection_loop(self): SherpaOnnx.start() self.stream.start_stream() @@ -46,10 +53,15 @@ class _KWS: frames = self.stream.read() # 在说话和监听状态时,暂停 KWS - if not frames or get_xiaozhi().device_state in [ - DeviceState.LISTENING, - DeviceState.SPEAKING, - ]: + if ( + not frames + or self.paused + or get_xiaozhi().device_state + in [ + DeviceState.LISTENING, + DeviceState.SPEAKING, + ] + ): time.sleep(0.01) continue @@ -60,14 +72,9 @@ class _KWS: def on_message(self, text: str): asyncio.run_coroutine_threadsafe( - self._on_message(text), get_xiaoai().async_loop + EventManager.wakeup(text, "kws"), + get_xiaoai().async_loop, ) - async def _on_message(self, text: str): - before_wakeup = APP_CONFIG["wakeup"]["before_wakeup"] - wakeup = await before_wakeup(get_speaker(), text, "kws") - if wakeup: - EventManager.on_wakeup() - KWS = _KWS() diff --git a/examples/xiaozhi/xiaozhi/xiaoai.py b/examples/xiaozhi/xiaozhi/xiaoai.py index cbdeae8..38d0af8 100644 --- a/examples/xiaozhi/xiaozhi/xiaoai.py +++ b/examples/xiaozhi/xiaozhi/xiaoai.py @@ -5,7 +5,6 @@ import threading import numpy as np import open_xiaoai_server -from config import APP_CONFIG from xiaozhi.event import EventManager from xiaozhi.ref import get_speaker, set_xiaoai from xiaozhi.services.audio.stream import GlobalStream @@ -69,12 +68,6 @@ class XiaoAI: event_data = event_json.get("data", {}) event_type = event_json.get("event") - async def on_wakeup(text, source): - before_wakeup = APP_CONFIG["wakeup"]["before_wakeup"] - wakeup = await before_wakeup(get_speaker(), text, source) - if wakeup: - EventManager.on_wakeup() - if not event_json.get("event"): return @@ -87,11 +80,11 @@ class XiaoAI: ): text = line.get("payload", {}).get("results")[0].get("text") if not text and not line.get("payload", {}).get("is_vad_begin"): - print(f"🔥 唤醒小爱: {line}") + print("🔥 唤醒小爱") EventManager.on_interrupt() elif text and line.get("payload", {}).get("is_final"): print(f"🔥 收到指令: {text}") - await on_wakeup(text, "xiaoai") + await EventManager.wakeup(text, "xiaoai") elif event_type == "playing": get_speaker().status = event_data.lower()