From 53e26821ade9adc3bad1482dd7ecdb2b4e80b9a5 Mon Sep 17 00:00:00 2001 From: hrz <1710360675@qq.com> Date: Tue, 16 Dec 2025 22:03:12 +0800 Subject: [PATCH] =?UTF-8?q?update:=E8=A1=A5=E5=9B=9E=E5=89=8D5=E4=B8=AA?= =?UTF-8?q?=E5=8C=85=E6=8F=90=E5=89=8D=E5=8F=91=E9=80=81=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=EF=BC=8C=E5=9B=A0=E4=B8=BA=E5=8F=91=E9=80=81=E5=AE=8C?= =?UTF-8?q?=E4=B8=8D=E7=AD=89=E4=BA=8E=E6=92=AD=E6=94=BE=E5=AE=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/handle/sendAudioHandle.py | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/main/xiaozhi-server/core/handle/sendAudioHandle.py b/main/xiaozhi-server/core/handle/sendAudioHandle.py index d0167498..8198dfb0 100644 --- a/main/xiaozhi-server/core/handle/sendAudioHandle.py +++ b/main/xiaozhi-server/core/handle/sendAudioHandle.py @@ -7,6 +7,10 @@ from core.providers.tts.dto.dto import SentenceType from core.utils.audioRateController import AudioRateController TAG = __name__ +# 音频帧时长(毫秒) +AUDIO_FRAME_DURATION = 60 +# 预缓冲包数量,直接发送以减少延迟 +PRE_BUFFER_COUNT = 5 async def sendAudioMessage(conn, sentenceType, audios, text): @@ -45,7 +49,7 @@ async def sendAudioMessage(conn, sentenceType, audios, text): async def _wait_for_audio_completion(conn): """ - 等待音频队列清空 + 等待音频队列清空并等待预缓冲包播放完成 Args: conn: 连接对象 @@ -56,6 +60,13 @@ async def _wait_for_audio_completion(conn): f"等待音频发送完成,队列中还有 {len(rate_controller.queue)} 个包" ) await rate_controller.queue_empty_event.wait() + + # 等待预缓冲包播放完成 + # 前N个包直接发送,增加2个网络抖动包,需要额外等待它们在客户端播放完成 + frame_duration_ms = rate_controller.frame_duration + pre_buffer_playback_time = (PRE_BUFFER_COUNT + 2) * frame_duration_ms / 1000.0 + await asyncio.sleep(pre_buffer_playback_time) + conn.logger.bind(tag=TAG).debug("音频发送完成") @@ -81,14 +92,14 @@ async def _send_to_mqtt_gateway(conn, opus_packet, timestamp, sequence): await conn.websocket.send(complete_packet) -async def sendAudio(conn, audios, frame_duration=60): +async def sendAudio(conn, audios, frame_duration=AUDIO_FRAME_DURATION): """ 发送音频包,使用 AudioRateController 进行精确的流量控制 Args: conn: 连接对象 audios: 单个opus包(bytes) 或 opus包列表 - frame_duration: 帧时长(毫秒),默认60ms + frame_duration: 帧时长(毫秒),默认使用全局常量AUDIO_FRAME_DURATION """ if audios is None or len(audios) == 0: return @@ -187,16 +198,14 @@ async def _send_audio_with_rate_control( flow_control: 流控状态 send_delay: 固定延迟(秒),-1表示使用动态流控 """ - pre_buffer_count = 5 - for packet in audio_list: if conn.client_abort: return conn.last_activity_time = time.time() * 1000 - # 预缓冲:前5个包直接发送 - if flow_control["packet_count"] < pre_buffer_count: + # 预缓冲:前N个包直接发送 + if flow_control["packet_count"] < PRE_BUFFER_COUNT: await _do_send_audio(conn, packet, flow_control) conn.client_is_speaking = True elif send_delay > 0: