mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-26 00:53:54 +08:00
fix: 停止帧发送后与原先音频时序问题
回退退出工具打断处理(在大模型思考期间进行打断,然后大模型立马调用退出工具会造成死锁,因模型思考时间和是否调用工具不确定性,状态难管理)
This commit is contained in:
@@ -148,8 +148,6 @@ class ConnectionHandler:
|
|||||||
self.memory = _memory
|
self.memory = _memory
|
||||||
self.intent = _intent
|
self.intent = _intent
|
||||||
|
|
||||||
self.is_exiting = False # 标记是否正在执行退出流程
|
|
||||||
|
|
||||||
# 为每个连接单独管理声纹识别
|
# 为每个连接单独管理声纹识别
|
||||||
self.voiceprint_provider = None
|
self.voiceprint_provider = None
|
||||||
|
|
||||||
@@ -350,10 +348,6 @@ class ConnectionHandler:
|
|||||||
|
|
||||||
async def _route_message(self, message):
|
async def _route_message(self, message):
|
||||||
"""消息路由"""
|
"""消息路由"""
|
||||||
# 退出状态丢弃所有消息
|
|
||||||
if self.is_exiting:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 检查是否已经获取到真实的绑定状态
|
# 检查是否已经获取到真实的绑定状态
|
||||||
if not self.bind_completed_event.is_set():
|
if not self.bind_completed_event.is_set():
|
||||||
# 还没有获取到真实状态,等待直到获取到真实状态或超时
|
# 还没有获取到真实状态,等待直到获取到真实状态或超时
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ TAG = __name__
|
|||||||
|
|
||||||
|
|
||||||
async def handleAbortMessage(conn: "ConnectionHandler"):
|
async def handleAbortMessage(conn: "ConnectionHandler"):
|
||||||
if conn.close_after_chat or conn.is_exiting:
|
|
||||||
conn.logger.bind(tag=TAG).info("退出流程中被打断,直接关闭连接")
|
|
||||||
return
|
|
||||||
|
|
||||||
conn.logger.bind(tag=TAG).info("Abort message received")
|
conn.logger.bind(tag=TAG).info("Abort message received")
|
||||||
# 设置成打断状态,会自动打断llm、tts任务
|
# 设置成打断状态,会自动打断llm、tts任务
|
||||||
conn.client_abort = True
|
conn.client_abort = True
|
||||||
|
|||||||
@@ -33,10 +33,6 @@ async def handle_user_intent(conn: "ConnectionHandler", text):
|
|||||||
if await check_direct_exit(conn, filtered_text):
|
if await check_direct_exit(conn, filtered_text):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# 明确再见不被打断
|
|
||||||
if conn.is_exiting:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 检查是否是唤醒词
|
# 检查是否是唤醒词
|
||||||
if await checkWakeupWords(conn, filtered_text):
|
if await checkWakeupWords(conn, filtered_text):
|
||||||
return True
|
return True
|
||||||
@@ -62,7 +58,6 @@ async def check_direct_exit(conn: "ConnectionHandler", text):
|
|||||||
if text == cmd:
|
if text == cmd:
|
||||||
conn.logger.bind(tag=TAG).info(f"识别到明确的退出命令: {text}")
|
conn.logger.bind(tag=TAG).info(f"识别到明确的退出命令: {text}")
|
||||||
await send_stt_message(conn, text)
|
await send_stt_message(conn, text)
|
||||||
conn.is_exiting = True
|
|
||||||
await conn.close()
|
await conn.close()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ TAG = __name__
|
|||||||
|
|
||||||
|
|
||||||
async def handleAudioMessage(conn: "ConnectionHandler", audio):
|
async def handleAudioMessage(conn: "ConnectionHandler", audio):
|
||||||
if conn.is_exiting:
|
|
||||||
return
|
|
||||||
# 当前片段是否有人说话
|
# 当前片段是否有人说话
|
||||||
have_voice = conn.vad.is_vad(conn, audio)
|
have_voice = conn.vad.is_vad(conn, audio)
|
||||||
# 如果设备刚刚被唤醒,短暂忽略VAD检测
|
# 如果设备刚刚被唤醒,短暂忽略VAD检测
|
||||||
|
|||||||
@@ -84,12 +84,6 @@ class ASRProviderBase(ABC):
|
|||||||
async def handle_voice_stop(self, conn: "ConnectionHandler", asr_audio_task: List[bytes]):
|
async def handle_voice_stop(self, conn: "ConnectionHandler", asr_audio_task: List[bytes]):
|
||||||
"""并行处理ASR和声纹识别"""
|
"""并行处理ASR和声纹识别"""
|
||||||
try:
|
try:
|
||||||
# 如果处于退出流程中,直接关闭连接,不处理新消息
|
|
||||||
if conn.close_after_chat or conn.is_exiting:
|
|
||||||
logger.bind(tag=TAG).info("退出流程中收到新消息,直接关闭连接")
|
|
||||||
await conn.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
total_start_time = time.monotonic()
|
total_start_time = time.monotonic()
|
||||||
|
|
||||||
# 准备音频数据
|
# 准备音频数据
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class ASRProvider(ASRProviderBase):
|
|||||||
self.asr_ws = None
|
self.asr_ws = None
|
||||||
self.forward_task = None
|
self.forward_task = None
|
||||||
self.is_processing = False # 添加处理状态标志
|
self.is_processing = False # 添加处理状态标志
|
||||||
|
self._is_stopping = False # 添加停止标志,防止竞态条件
|
||||||
|
|
||||||
# 配置参数
|
# 配置参数
|
||||||
self.appid = str(config.get("appid"))
|
self.appid = str(config.get("appid"))
|
||||||
@@ -148,7 +149,7 @@ class ASRProvider(ASRProviderBase):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# 发送当前音频数据
|
# 发送当前音频数据
|
||||||
if self.asr_ws and self.is_processing:
|
if self.asr_ws and self.is_processing and not self._is_stopping:
|
||||||
try:
|
try:
|
||||||
pcm_frame = self.decoder.decode(audio, 960)
|
pcm_frame = self.decoder.decode(audio, 960)
|
||||||
payload = gzip.compress(pcm_frame)
|
payload = gzip.compress(pcm_frame)
|
||||||
@@ -256,6 +257,7 @@ class ASRProvider(ASRProviderBase):
|
|||||||
await self.asr_ws.close()
|
await self.asr_ws.close()
|
||||||
self.asr_ws = None
|
self.asr_ws = None
|
||||||
self.is_processing = False
|
self.is_processing = False
|
||||||
|
self._is_stopping = False
|
||||||
# 重置所有音频相关状态
|
# 重置所有音频相关状态
|
||||||
conn.reset_audio_states()
|
conn.reset_audio_states()
|
||||||
|
|
||||||
@@ -264,9 +266,11 @@ class ASRProvider(ASRProviderBase):
|
|||||||
asyncio.create_task(self.asr_ws.close())
|
asyncio.create_task(self.asr_ws.close())
|
||||||
self.asr_ws = None
|
self.asr_ws = None
|
||||||
self.is_processing = False
|
self.is_processing = False
|
||||||
|
self._is_stopping = False
|
||||||
|
|
||||||
async def _send_stop_request(self):
|
async def _send_stop_request(self):
|
||||||
"""发送最后一个音频帧以通知服务器结束"""
|
"""发送最后一个音频帧以通知服务器结束"""
|
||||||
|
self._is_stopping = True # 先标记为停止状态,阻止后续音频发送
|
||||||
if self.asr_ws:
|
if self.asr_ws:
|
||||||
try:
|
try:
|
||||||
# 发送结束标记的音频帧(gzip压缩的空数据)
|
# 发送结束标记的音频帧(gzip压缩的空数据)
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ handle_exit_intent_function_desc = {
|
|||||||
"handle_exit_intent", handle_exit_intent_function_desc, ToolType.SYSTEM_CTL
|
"handle_exit_intent", handle_exit_intent_function_desc, ToolType.SYSTEM_CTL
|
||||||
)
|
)
|
||||||
def handle_exit_intent(conn: "ConnectionHandler", say_goodbye: str | None = None):
|
def handle_exit_intent(conn: "ConnectionHandler", say_goodbye: str | None = None):
|
||||||
conn.is_exiting = True
|
|
||||||
# 处理退出意图
|
# 处理退出意图
|
||||||
try:
|
try:
|
||||||
if say_goodbye is None:
|
if say_goodbye is None:
|
||||||
|
|||||||
Reference in New Issue
Block a user