From 220af8068e38d5919123f1f24bf360c57b2db30c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=81=A5=E8=B1=AA?= Date: Fri, 21 Mar 2025 14:59:01 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9F=B3=E4=B9=90?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E6=96=AD=E5=BC=80bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复音乐播放速度太快导致设备内存溢出断开连接的问题 --- .../core/handle/sendAudioHandle.py | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/main/xiaozhi-server/core/handle/sendAudioHandle.py b/main/xiaozhi-server/core/handle/sendAudioHandle.py index 8999bf08..a6fed97b 100644 --- a/main/xiaozhi-server/core/handle/sendAudioHandle.py +++ b/main/xiaozhi-server/core/handle/sendAudioHandle.py @@ -14,33 +14,37 @@ async def sendAudioMessage(conn, audios, text, text_index=0): await send_tts_message(conn, "sentence_start", text) # 流控参数优化 - original_frame_duration = 60 # 原始帧时长(毫秒) - adjusted_frame_duration = int(original_frame_duration * 0.8) # 缩短20% - total_frames = len(audios) # 获取总帧数 - compensation = total_frames * (original_frame_duration - adjusted_frame_duration) / 1000 # 补偿时间(秒) - + frame_duration = 62 # 帧时长(毫秒),增加余量 start_time = time.perf_counter() play_position = 0 # 已播放时长(毫秒) - for opus_packet in audios: + # 预发送前 n 帧 + pre_buffer = min(5, len(audios)) + for i in range(pre_buffer): + await conn.websocket.send(audios[i]) + conn.logger.bind(tag=TAG).debug(f"预缓冲帧 {i}") + + # 正常播放剩余帧 + for opus_packet in audios[pre_buffer:]: if conn.client_abort: return - - # 计算带加速因子的预期时间 + + # 计算预期发送时间 expected_time = start_time + (play_position / 1000) current_time = time.perf_counter() - - # 流控等待(使用加速后的帧时长) delay = expected_time - current_time if delay > 0: await asyncio.sleep(delay) - await conn.websocket.send(opus_packet) - play_position += adjusted_frame_duration # 使用调整后的帧时长 + send_start = time.perf_counter() - # 补偿因加速损失的时长 - if compensation > 0: - await asyncio.sleep(compensation) + await conn.websocket.send(opus_packet) + + send_duration = (time.perf_counter() - send_start) * 1000 + logger.bind(tag=TAG).debug(f"发送帧,位置: {play_position}ms, 实际间隔: {(time.perf_counter() - current_time) * 1000:.2f}ms, 发送耗时: {send_duration:.2f}ms") + + # 动态调整下次延迟,补偿发送耗时 + play_position += frame_duration # 更新播放位置 await send_tts_message(conn, "sentence_end", text) From 49cb98a60654871f6a645d2867079501b851366d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=81=A5=E8=B1=AA?= Date: Mon, 24 Mar 2025 09:28:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9F=B3=E4=B9=90?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=8D=A1=E9=A1=BF=E5=92=8C=E6=96=AD=E8=BF=9E?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/handle/sendAudioHandle.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/main/xiaozhi-server/core/handle/sendAudioHandle.py b/main/xiaozhi-server/core/handle/sendAudioHandle.py index ffb36398..c0a664eb 100644 --- a/main/xiaozhi-server/core/handle/sendAudioHandle.py +++ b/main/xiaozhi-server/core/handle/sendAudioHandle.py @@ -28,15 +28,15 @@ async def sendAudioMessage(conn, audios, text, text_index=0): # 播放音频 async def sendAudio(conn, audios): # 流控参数优化 - frame_duration = 62 # 帧时长(毫秒),增加余量 + frame_duration = 60 # 帧时长(毫秒),匹配 Opus 编码 start_time = time.perf_counter() - play_position = 0 # 已播放时长(毫秒) + play_position = 0 - # 预发送前 n 帧 - pre_buffer = min(5, len(audios)) + # 预缓冲:发送前 3 帧 + pre_buffer = min(3, len(audios)) for i in range(pre_buffer): await conn.websocket.send(audios[i]) - conn.logger.bind(tag=TAG).debug(f"预缓冲帧 {i}") + conn.logger.bind(tag=TAG).debug(f"预缓冲帧 {i}, 时间: {(time.perf_counter() - start_time) * 1000:.2f}ms") # 正常播放剩余帧 for opus_packet in audios[pre_buffer:]: @@ -50,15 +50,11 @@ async def sendAudio(conn, audios): if delay > 0: await asyncio.sleep(delay) - send_start = time.perf_counter() - await conn.websocket.send(opus_packet) + conn.logger.bind(tag=TAG).debug(f"发送帧,位置: {play_position}ms, 实际间隔: {(time.perf_counter() - current_time) * 1000:.2f}ms") - send_duration = (time.perf_counter() - send_start) * 1000 - logger.bind(tag=TAG).debug(f"发送帧,位置: {play_position}ms, 实际间隔: {(time.perf_counter() - current_time) * 1000:.2f}ms, 发送耗时: {send_duration:.2f}ms") + play_position += frame_duration - # 动态调整下次延迟,补偿发送耗时 - play_position += frame_duration # 更新播放位置 async def send_tts_message(conn, state, text=None):