87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
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 |