From 6f6c39da238e2ba91bceeb59d5b2c5f120d3643b Mon Sep 17 00:00:00 2001 From: hrz <1710360675@qq.com> Date: Fri, 27 Jun 2025 23:38:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?update:=E4=BC=98=E5=8C=96=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/core/connection.py | 37 +++++++++++-------- .../core/handle/receiveAudioHandle.py | 9 ++--- .../core/handle/sendAudioHandle.py | 2 +- .../core/providers/vad/silero.py | 8 ++-- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index fc674527..e789fc05 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -110,10 +110,8 @@ class ConnectionHandler: # vad相关变量 self.client_audio_buffer = bytearray() self.client_have_voice = False - self.client_have_voice_last_time = 0.0 - self.client_no_voice_last_time = 0.0 + self.last_activity_time = 0.0 # 统一的活动时间戳(毫秒) self.client_voice_stop = False - self.client_voice_frame_count = 0 # asr相关变量 # 因为实际部署时可能会用到公共的本地ASR,不能把变量暴露给公共ASR @@ -143,10 +141,10 @@ class ConnectionHandler: self.load_function_plugin = False self.intent_type = "nointent" - self.timeout_task = None self.timeout_seconds = ( int(self.config.get("close_connection_no_voice_time", 120)) + 60 ) # 在原来第一道关闭的基础上加60秒,进行二道关闭 + self.timeout_task = None # {"mcp":true} 表示启用MCP功能 self.features = None @@ -187,6 +185,9 @@ class ConnectionHandler: self.websocket = ws self.device_id = self.headers.get("device-id", None) + # 初始化活动时间戳 + self.last_activity_time = time.time() * 1000 + # 启动超时检查任务 self.timeout_task = asyncio.create_task(self._check_timeout()) @@ -243,12 +244,8 @@ class ConnectionHandler: async def _route_message(self, message): """消息路由""" - # 重置超时计时器 - if self.timeout_task: - self.timeout_task.cancel() - self.timeout_task = asyncio.create_task(self._check_timeout()) - if isinstance(message, str): + self.last_activity_time = time.time() * 1000 await handleTextMessage(self, message) elif isinstance(message, bytes): if self.vad is None: @@ -898,7 +895,6 @@ class ConnectionHandler: def reset_vad_states(self): self.client_audio_buffer = bytearray() self.client_have_voice = False - self.client_have_voice_last_time = 0 self.client_voice_stop = False self.logger.bind(tag=TAG).debug("VAD states reset.") @@ -917,10 +913,21 @@ class ConnectionHandler: """检查连接超时""" try: while not self.stop_event.is_set(): - await asyncio.sleep(self.timeout_seconds) - if not self.stop_event.is_set(): - self.logger.bind(tag=TAG).info("连接超时,准备关闭") - await self.close(self.websocket) - break + # 检查是否超时(只有在时间戳已初始化的情况下) + if self.last_activity_time > 0.0: + current_time = time.time() * 1000 + if ( + current_time - self.last_activity_time + > self.timeout_seconds * 1000 + ): + if not self.stop_event.is_set(): + self.logger.bind(tag=TAG).info("连接超时,准备关闭") + await self.close(self.websocket) + break + # 每10秒检查一次,避免过于频繁 + self.logger.bind(tag=TAG).info( + f"检查连接超时...{self.last_activity_time}" + ) + await asyncio.sleep(10) except Exception as e: self.logger.bind(tag=TAG).error(f"超时检查任务出错: {e}") diff --git a/main/xiaozhi-server/core/handle/receiveAudioHandle.py b/main/xiaozhi-server/core/handle/receiveAudioHandle.py index fd58f49d..465b081a 100644 --- a/main/xiaozhi-server/core/handle/receiveAudioHandle.py +++ b/main/xiaozhi-server/core/handle/receiveAudioHandle.py @@ -66,12 +66,11 @@ async def startToChat(conn, text): async def no_voice_close_connect(conn, have_voice): if have_voice: - conn.client_no_voice_last_time = 0.0 + conn.last_activity_time = time.time() * 1000 return - if conn.client_no_voice_last_time == 0.0: - conn.client_no_voice_last_time = time.time() * 1000 - else: - no_voice_time = time.time() * 1000 - conn.client_no_voice_last_time + # 只有在已经初始化过时间戳的情况下才进行超时检查 + if conn.last_activity_time > 0.0: + no_voice_time = time.time() * 1000 - conn.last_activity_time close_connection_no_voice_time = int( conn.config.get("close_connection_no_voice_time", 120) ) diff --git a/main/xiaozhi-server/core/handle/sendAudioHandle.py b/main/xiaozhi-server/core/handle/sendAudioHandle.py index 6e3bca62..eb9f565f 100644 --- a/main/xiaozhi-server/core/handle/sendAudioHandle.py +++ b/main/xiaozhi-server/core/handle/sendAudioHandle.py @@ -93,7 +93,7 @@ async def sendAudio(conn, audios, pre_buffer=True): break # 重置没有声音的状态 - conn.client_no_voice_last_time = 0.0 + conn.last_activity_time = time.time() * 1000 # 计算预期发送时间 expected_time = start_time + (play_position / 1000) diff --git a/main/xiaozhi-server/core/providers/vad/silero.py b/main/xiaozhi-server/core/providers/vad/silero.py index 9df5188c..2c45ba8c 100644 --- a/main/xiaozhi-server/core/providers/vad/silero.py +++ b/main/xiaozhi-server/core/providers/vad/silero.py @@ -35,7 +35,7 @@ class VADProvider(VADProviderBase): pcm_frame = self.decoder.decode(opus_packet, 960) conn.client_audio_buffer.extend(pcm_frame) # 将新数据加入缓冲区 - # 初始化帧计数器 + # 确保帧计数器存在 if not hasattr(conn, "client_voice_frame_count"): conn.client_voice_frame_count = 0 @@ -66,14 +66,12 @@ class VADProvider(VADProviderBase): # 如果之前有声音,但本次没有声音,且与上次有声音的时间差已经超过了静默阈值,则认为已经说完一句话 if conn.client_have_voice and not client_have_voice: - stop_duration = ( - time.time() * 1000 - conn.client_have_voice_last_time - ) + stop_duration = time.time() * 1000 - conn.last_activity_time if stop_duration >= self.silence_threshold_ms: conn.client_voice_stop = True if client_have_voice: conn.client_have_voice = True - conn.client_have_voice_last_time = time.time() * 1000 + conn.last_activity_time = time.time() * 1000 return client_have_voice except opuslib_next.OpusError as e: From 500b0ebde3c89fbd21ea1760877e1351ae839ec4 Mon Sep 17 00:00:00 2001 From: hrz <1710360675@qq.com> Date: Fri, 27 Jun 2025 23:47:17 +0800 Subject: [PATCH 2/2] =?UTF-8?q?update:=E5=8E=BB=E9=99=A4=E6=97=A0=E5=85=B3?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/core/connection.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index e789fc05..9d1949c4 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -925,9 +925,6 @@ class ConnectionHandler: await self.close(self.websocket) break # 每10秒检查一次,避免过于频繁 - self.logger.bind(tag=TAG).info( - f"检查连接超时...{self.last_activity_time}" - ) await asyncio.sleep(10) except Exception as e: self.logger.bind(tag=TAG).error(f"超时检查任务出错: {e}")