Files
banban/talkingq-url/handlers/audio_packet_parser.py
2026-03-24 15:04:36 +08:00

87 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import struct
from fastapi import WebSocket
from services.audio_session import audio_session_manager, AudioSession
from utils.logger import session_logger
from services.factory import get_asr, get_llm, get_tts
DEVICE_ID_SIZE = 22 # 将大小设为22在实际解析中会更灵活处理
SESSION_ID_SIZE = 33
SAMPLE_RATE = 16000 # 固定为16K采样率
CHANNELS = 1 # 单声道
SAMPLE_WIDTH = 2 # 16位 = 2字节
async def parse_packet(data: bytes, websocket: WebSocket):
try:
min_header_size = 4 + 1 + 4 # sequence_number + packet_type + data_size
if len(data) < min_header_size:
session_logger.warning(
"unknown", "unknown", f"数据包太小: {len(data)} < {min_header_size}"
)
return None, None, None, None, None
null_pos = data.find(b'\x00')
if null_pos == -1 or null_pos > 25: # 如果没找到或超出最大长度限制
null_pos = 22 # 使用默认值
device_id = data[:null_pos].decode("ascii")
session_start = null_pos + 1
session_end = session_start + SESSION_ID_SIZE
session_data = data[session_start:session_end]
session_null_pos = session_data.find(b'\x00')
if session_null_pos != -1:
session_id = session_data[:session_null_pos].decode("ascii")
else:
session_id = session_data.decode("ascii").rstrip("\x00")
offset = session_start + len(session_id) + 1
if offset + min_header_size > len(data):
session_logger.warning(
"unknown", "unknown", f"解析剩余头信息时数据包太小: {len(data)} < {offset + min_header_size}"
)
return None, None, None, None, None
remaining_data = data[offset:]
offset = 0
sequence_number = struct.unpack("<I", remaining_data[offset:offset + 4])[0]
offset += 4
packet_type = remaining_data[offset]
offset += 1
data_size = struct.unpack("<I", remaining_data[offset:offset + 4])[0]
offset += 4
audio_data = remaining_data[offset:offset + data_size]
session_key = (device_id, session_id)
sample_rate = SAMPLE_RATE
session = await audio_session_manager.get_session(session_key)
if not session:
asr_service = await get_asr(None)
llm_service = await get_llm(None)
tts_service = await get_tts(None)
session = AudioSession(
asr_service=asr_service,
llm_service=llm_service,
tts_service=tts_service,
sample_rate=sample_rate,
)
session.device_id = device_id
session.session_id = session_id
await audio_session_manager.set_session(session_key, session)
if packet_type == 1:
session.sample_rate = sample_rate
session.last_received_seq = max(session.last_received_seq, sequence_number)
return session_key, session, packet_type, audio_data, sample_rate
except Exception as e:
session_logger.error(
"unknown",
"unknown",
f"解析WebSocket数据包时出错: {str(e)}",
exc_info=True,
)
return None, None, None, None, None