mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-29 06:23:56 +08:00
update:优化吞音问题,解决播放长音频时的错误退出
This commit is contained in:
@@ -202,12 +202,16 @@ class ConnectionHandler:
|
|||||||
finally:
|
finally:
|
||||||
await self.close(ws)
|
await self.close(ws)
|
||||||
|
|
||||||
|
async def reset_timeout(self):
|
||||||
|
"""重置超时计时器"""
|
||||||
|
if self.timeout_task:
|
||||||
|
self.timeout_task.cancel()
|
||||||
|
self.timeout_task = asyncio.create_task(self._check_timeout())
|
||||||
|
|
||||||
async def _route_message(self, message):
|
async def _route_message(self, message):
|
||||||
"""消息路由"""
|
"""消息路由"""
|
||||||
# 重置超时计时器
|
# 重置超时计时器
|
||||||
if self.timeout_task:
|
await self.reset_timeout()
|
||||||
self.timeout_task.cancel()
|
|
||||||
self.timeout_task = asyncio.create_task(self._check_timeout())
|
|
||||||
|
|
||||||
if isinstance(message, str):
|
if isinstance(message, str):
|
||||||
await handleTextMessage(self, message)
|
await handleTextMessage(self, message)
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ async def sendAudioMessage(conn, audios, text, text_index=0):
|
|||||||
logger.bind(tag=TAG).info(f"发送第一段语音: {text}")
|
logger.bind(tag=TAG).info(f"发送第一段语音: {text}")
|
||||||
await send_tts_message(conn, "sentence_start", text)
|
await send_tts_message(conn, "sentence_start", text)
|
||||||
|
|
||||||
# 播放音频
|
is_first_audio = (text_index == conn.tts_first_text_index)
|
||||||
await sendAudio(conn, audios)
|
await sendAudio(conn, audios, pre_buffer=is_first_audio)
|
||||||
|
|
||||||
await send_tts_message(conn, "sentence_end", text)
|
await send_tts_message(conn, "sentence_end", text)
|
||||||
|
|
||||||
@@ -64,22 +64,32 @@ async def sendAudioMessage(conn, audios, text, text_index=0):
|
|||||||
|
|
||||||
|
|
||||||
# 播放音频
|
# 播放音频
|
||||||
async def sendAudio(conn, audios):
|
async def sendAudio(conn, audios, pre_buffer=True):
|
||||||
# 流控参数优化
|
# 流控参数优化
|
||||||
frame_duration = 60 # 帧时长(毫秒),匹配 Opus 编码
|
frame_duration = 60 # 帧时长(毫秒),匹配 Opus 编码
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
play_position = 0
|
play_position = 0
|
||||||
|
last_reset_time = time.perf_counter() # 记录最后的重置时间
|
||||||
|
|
||||||
# 预缓冲:发送前 3 帧
|
# 仅当第一句话时执行预缓冲
|
||||||
pre_buffer = min(3, len(audios))
|
if pre_buffer:
|
||||||
for i in range(pre_buffer):
|
pre_buffer_frames = min(3, len(audios))
|
||||||
await conn.websocket.send(audios[i])
|
for i in range(pre_buffer_frames):
|
||||||
|
await conn.websocket.send(audios[i])
|
||||||
|
remaining_audios = audios[pre_buffer_frames:]
|
||||||
|
else:
|
||||||
|
remaining_audios = audios
|
||||||
|
|
||||||
# 正常播放剩余帧
|
# 播放剩余音频帧
|
||||||
for opus_packet in audios[pre_buffer:]:
|
for opus_packet in remaining_audios:
|
||||||
if conn.client_abort:
|
if conn.client_abort:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 每分钟重置一次计时器
|
||||||
|
if time.perf_counter() - last_reset_time > 60:
|
||||||
|
await conn.reset_timeout()
|
||||||
|
last_reset_time = time.perf_counter()
|
||||||
|
|
||||||
# 计算预期发送时间
|
# 计算预期发送时间
|
||||||
expected_time = start_time + (play_position / 1000)
|
expected_time = start_time + (play_position / 1000)
|
||||||
current_time = time.perf_counter()
|
current_time = time.perf_counter()
|
||||||
|
|||||||
Reference in New Issue
Block a user