From dcf8c134a2365eebf4cff63291a6fbb44e56ba44 Mon Sep 17 00:00:00 2001 From: 3030332422 <3030332422@qq.com> Date: Thu, 14 Aug 2025 17:57:46 +0800 Subject: [PATCH 1/2] =?UTF-8?q?update:=E4=BC=98=E5=8C=96=E5=A3=B0=E7=BA=B9?= =?UTF-8?q?=E8=AF=86=E5=88=AB=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E5=81=A5=E5=BA=B7=E6=A3=80=E6=9F=A5=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E8=BF=90=E8=A1=8C=E6=97=B6=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E7=AD=89=E5=BE=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/utils/voiceprint_provider.py | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/main/xiaozhi-server/core/utils/voiceprint_provider.py b/main/xiaozhi-server/core/utils/voiceprint_provider.py index b241fb51..4fb174ff 100644 --- a/main/xiaozhi-server/core/utils/voiceprint_provider.py +++ b/main/xiaozhi-server/core/utils/voiceprint_provider.py @@ -1,7 +1,7 @@ import asyncio -import json import time import aiohttp +import requests from urllib.parse import urlparse, parse_qs from typing import Optional, Dict from config.logger import setup_logging @@ -57,8 +57,13 @@ class VoiceprintProvider: logger.bind(tag=TAG).warning("未配置有效的说话人,声纹识别将被禁用") self.enabled = False else: - self.enabled = True - logger.bind(tag=TAG).info(f"声纹识别已配置: API={self.api_url}, 说话人={len(self.speaker_ids)}个") + # 进行健康检查,验证服务器是否可用 + if self._check_server_health(): + self.enabled = True + logger.bind(tag=TAG).info(f"声纹识别已启用: API={self.api_url}, 说话人={len(self.speaker_ids)}个") + else: + self.enabled = False + logger.bind(tag=TAG).warning(f"声纹识别服务器不可用,声纹识别已禁用: {self.api_url}") def _parse_speakers(self) -> Dict[str, Dict[str, str]]: """解析说话人配置""" @@ -76,6 +81,41 @@ class VoiceprintProvider: logger.bind(tag=TAG).warning(f"解析说话人配置失败: {speaker_str}, 错误: {e}") return speaker_map + def _check_server_health(self) -> bool: + """检查声纹识别服务器健康状态""" + if not self.api_url or not self.api_key: + return False + + try: + # 健康检查URL + parsed_url = urlparse(self.api_url) + health_url = f"{parsed_url.scheme}://{parsed_url.netloc}/voiceprint/health?key={self.api_key}" + + # 发送健康检查请求 + response = requests.get(health_url, timeout=3) + + if response.status_code == 200: + result = response.json() + if result.get("status") == "healthy": + logger.bind(tag=TAG).info("声纹识别服务器健康检查通过") + return True + else: + logger.bind(tag=TAG).warning(f"声纹识别服务器状态异常: {result}") + return False + else: + logger.bind(tag=TAG).warning(f"声纹识别服务器健康检查失败: HTTP {response.status_code}") + return False + + except requests.exceptions.ConnectTimeout: + logger.bind(tag=TAG).warning("声纹识别服务器连接超时") + return False + except requests.exceptions.ConnectionError: + logger.bind(tag=TAG).warning("声纹识别服务器连接被拒绝") + return False + except Exception as e: + logger.bind(tag=TAG).warning(f"声纹识别服务器健康检查异常: {e}") + return False + async def identify_speaker(self, audio_data: bytes, session_id: str) -> Optional[str]: """识别说话人""" if not self.enabled or not self.api_url or not self.api_key: @@ -132,3 +172,4 @@ class VoiceprintProvider: elapsed = time.monotonic() - api_start_time logger.bind(tag=TAG).error(f"声纹识别失败: {e}") return None + From 0bfa5cf723e7da3f1529f73f14384b923ec7b8a6 Mon Sep 17 00:00:00 2001 From: 3030332422 <3030332422@qq.com> Date: Fri, 15 Aug 2025 16:58:56 +0800 Subject: [PATCH 2/2] =?UTF-8?q?update:feat:=20=E4=B8=BA=E5=A3=B0=E7=BA=B9?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E6=B7=BB=E5=8A=A0=E7=BC=93=E5=AD=98=E6=9C=BA?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xiaozhi-server/core/utils/cache/config.py | 4 +++ .../core/utils/voiceprint_provider.py | 33 +++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/main/xiaozhi-server/core/utils/cache/config.py b/main/xiaozhi-server/core/utils/cache/config.py index d6d93345..248c2af7 100644 --- a/main/xiaozhi-server/core/utils/cache/config.py +++ b/main/xiaozhi-server/core/utils/cache/config.py @@ -18,6 +18,7 @@ class CacheType(Enum): IP_INFO = "ip_info" CONFIG = "config" DEVICE_PROMPT = "device_prompt" + VOICEPRINT_HEALTH = "voiceprint_health" # 声纹识别健康检查 @dataclass @@ -54,5 +55,8 @@ class CacheConfig: CacheType.DEVICE_PROMPT: cls( strategy=CacheStrategy.TTL, ttl=None, max_size=1000 # 手动失效 ), + CacheType.VOICEPRINT_HEALTH: cls( + strategy=CacheStrategy.TTL, ttl=600, max_size=100 # 10分钟过期 + ), } return configs.get(cache_type, cls()) diff --git a/main/xiaozhi-server/core/utils/voiceprint_provider.py b/main/xiaozhi-server/core/utils/voiceprint_provider.py index 4fb174ff..8e788172 100644 --- a/main/xiaozhi-server/core/utils/voiceprint_provider.py +++ b/main/xiaozhi-server/core/utils/voiceprint_provider.py @@ -5,6 +5,8 @@ import requests from urllib.parse import urlparse, parse_qs from typing import Optional, Dict from config.logger import setup_logging +from core.utils.cache.manager import cache_manager +from core.utils.cache.config import CacheType TAG = __name__ logger = setup_logging() @@ -85,7 +87,18 @@ class VoiceprintProvider: """检查声纹识别服务器健康状态""" if not self.api_url or not self.api_key: return False - + + cache_key = f"{self.api_url}:{self.api_key}" + + # 检查缓存 + cached_result = cache_manager.get(CacheType.VOICEPRINT_HEALTH, cache_key) + if cached_result is not None: + logger.bind(tag=TAG).debug(f"使用缓存的健康状态: {cached_result}") + return cached_result + + # 缓存过期或不存在 + logger.bind(tag=TAG).info("执行声纹服务器健康检查") + try: # 健康检查URL parsed_url = urlparse(self.api_url) @@ -98,23 +111,29 @@ class VoiceprintProvider: result = response.json() if result.get("status") == "healthy": logger.bind(tag=TAG).info("声纹识别服务器健康检查通过") - return True + is_healthy = True else: logger.bind(tag=TAG).warning(f"声纹识别服务器状态异常: {result}") - return False + is_healthy = False else: logger.bind(tag=TAG).warning(f"声纹识别服务器健康检查失败: HTTP {response.status_code}") - return False + is_healthy = False except requests.exceptions.ConnectTimeout: logger.bind(tag=TAG).warning("声纹识别服务器连接超时") - return False + is_healthy = False except requests.exceptions.ConnectionError: logger.bind(tag=TAG).warning("声纹识别服务器连接被拒绝") - return False + is_healthy = False except Exception as e: logger.bind(tag=TAG).warning(f"声纹识别服务器健康检查异常: {e}") - return False + is_healthy = False + + # 使用全局缓存管理器缓存结果 + cache_manager.set(CacheType.VOICEPRINT_HEALTH, cache_key, is_healthy) + logger.bind(tag=TAG).info(f"健康检查结果已缓存: {is_healthy}") + + return is_healthy async def identify_speaker(self, audio_data: bytes, session_id: str) -> Optional[str]: """识别说话人"""