update:优化吞音问题,解决播放长音频时的错误退出

This commit is contained in:
Sakura-RanChen
2025-04-29 17:14:53 +08:00
parent 2d5ef3011a
commit b0262cfe72
2 changed files with 26 additions and 12 deletions
+7 -3
View File
@@ -202,12 +202,16 @@ class ConnectionHandler:
finally:
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):
"""消息路由"""
# 重置超时计时器
if self.timeout_task:
self.timeout_task.cancel()
self.timeout_task = asyncio.create_task(self._check_timeout())
await self.reset_timeout()
if isinstance(message, str):
await handleTextMessage(self, message)
@@ -51,8 +51,8 @@ async def sendAudioMessage(conn, audios, text, text_index=0):
logger.bind(tag=TAG).info(f"发送第一段语音: {text}")
await send_tts_message(conn, "sentence_start", text)
# 播放音频
await sendAudio(conn, audios)
is_first_audio = (text_index == conn.tts_first_text_index)
await sendAudio(conn, audios, pre_buffer=is_first_audio)
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 编码
start_time = time.perf_counter()
play_position = 0
last_reset_time = time.perf_counter() # 记录最后的重置时间
# 预缓冲:发送前 3 帧
pre_buffer = min(3, len(audios))
for i in range(pre_buffer):
await conn.websocket.send(audios[i])
# 仅当第一句话时执行预缓冲
if pre_buffer:
pre_buffer_frames = min(3, len(audios))
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:
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)
current_time = time.perf_counter()