Merge pull request #3309 from xinnan-tech/py-fix-reportHandle

refactor(reportHandle): 重构上报处理逻辑,适配多格式音频转换
This commit is contained in:
Sakura-RanChen
2026-07-27 15:24:15 +08:00
committed by GitHub
+79 -18
View File
@@ -22,39 +22,45 @@ from config.manage_api_client import report as manage_report
TAG = __name__
async def report(conn: "ConnectionHandler", type, text, opus_data, report_time):
async def report(conn: "ConnectionHandler", chat_type, text, audio_data, report_time):
"""执行聊天记录上报操作
Args:
conn: 连接对象
type: 上报类型,1为用户2为智能体3为工具调用
chat_type: 上报类型,1为用户(ASR/PCM)2为智能体(TTS/Opus)3为工具调用
text: 合成文本
opus_data: opus音频数据
audio_data: 音频数据chat_type=1时为PCM格式,chat_type=2时为Opus格式)
report_time: 上报时间
"""
try:
if opus_data:
audio_data = opus_to_wav(conn, opus_data)
if audio_data:
if chat_type == 1:
wav_data = pcm_to_wav(conn, audio_data)
elif chat_type == 2:
wav_data = opus_to_wav(conn, audio_data)
else:
wav_data = None
else:
audio_data = None
wav_data = None
# 执行异步上报
await manage_report(
mac_address=conn.device_id,
session_id=conn.session_id,
chat_type=type,
chat_type=chat_type,
content=text,
audio=audio_data,
audio=wav_data,
report_time=report_time,
)
except Exception as e:
conn.logger.bind(tag=TAG).error(f"聊天记录上报失败: {e}")
def opus_to_wav(conn: "ConnectionHandler", pcm_data):
def pcm_to_wav(conn: "ConnectionHandler", pcm_data):
"""将PCM数据转换为WAV格式的字节流
Args:
output_dir: 输出目录(保留参数以保持接口兼容)
conn: 连接对象
pcm_data: PCM音频数据(可能是列表或bytes)
Returns:
@@ -96,11 +102,62 @@ def opus_to_wav(conn: "ConnectionHandler", pcm_data):
raise
def opus_to_wav(conn: "ConnectionHandler", opus_data):
"""将Opus数据转换为WAV格式的字节流
Args:
conn: 连接对象
opus_data: Opus音频数据(可能是列表或bytes)
Returns:
bytes: WAV格式的音频数据
"""
decoder = None
try:
decoder = opuslib_next.Decoder(16000, 1)
pcm_data = []
if isinstance(opus_data, list):
for opus_packet in opus_data:
try:
pcm_frame = decoder.decode(opus_packet, 960)
pcm_data.append(pcm_frame)
except opuslib_next.OpusError as e:
conn.logger.bind(tag=TAG).error(f"Opus解码错误: {e}", exc_info=True)
elif isinstance(opus_data, bytes):
pcm_frame = decoder.decode(opus_data, 960)
pcm_data.append(pcm_frame)
if not pcm_data:
raise ValueError("没有有效的音频数据")
pcm_data_bytes = b"".join(pcm_data)
wav_header = bytearray()
wav_header.extend(b"RIFF")
wav_header.extend((36 + len(pcm_data_bytes)).to_bytes(4, "little"))
wav_header.extend(b"WAVE")
wav_header.extend(b"fmt ")
wav_header.extend((16).to_bytes(4, "little"))
wav_header.extend((1).to_bytes(2, "little"))
wav_header.extend((1).to_bytes(2, "little"))
wav_header.extend((16000).to_bytes(4, "little"))
wav_header.extend((32000).to_bytes(4, "little"))
wav_header.extend((2).to_bytes(2, "little"))
wav_header.extend((16).to_bytes(2, "little"))
wav_header.extend(b"data")
wav_header.extend(len(pcm_data_bytes).to_bytes(4, "little"))
return bytes(wav_header) + pcm_data_bytes
finally:
if decoder is not None:
try:
del decoder
except Exception as e:
conn.logger.bind(tag=TAG).debug(f"释放decoder资源时出错: {e}")
def enqueue_tts_report(conn: "ConnectionHandler", text, opus_data):
if not conn.read_config_from_api or conn.need_bind or not conn.report_tts_enable:
return
if conn.chat_history_conf == 0:
return
"""将TTS数据加入上报队列
Args:
@@ -108,6 +165,10 @@ def enqueue_tts_report(conn: "ConnectionHandler", text, opus_data):
text: 合成文本
opus_data: opus音频数据
"""
if not conn.read_config_from_api or conn.need_bind or not conn.report_tts_enable:
return
if conn.chat_history_conf == 0:
return
try:
# 使用连接对象的队列,传入文本和二进制数据而非文件路径
if conn.chat_history_conf == 2:
@@ -164,10 +225,6 @@ def enqueue_tool_report(conn: "ConnectionHandler", tool_name: str, tool_input: d
def enqueue_asr_report(conn: "ConnectionHandler", text, opus_data):
if not conn.read_config_from_api or conn.need_bind or not conn.report_asr_enable:
return
if conn.chat_history_conf == 0:
return
"""将ASR数据加入上报队列
Args:
@@ -175,6 +232,10 @@ def enqueue_asr_report(conn: "ConnectionHandler", text, opus_data):
text: 合成文本
opus_data: opus音频数据
"""
if not conn.read_config_from_api or conn.need_bind or not conn.report_asr_enable:
return
if conn.chat_history_conf == 0:
return
try:
# 使用连接对象的队列,传入文本和二进制数据而非文件路径
if conn.chat_history_conf == 2: