Files
2026-07-13 12:28:27 +08:00

115 lines
3.5 KiB
Python

# coding: utf-8
"""
通信协议模块
定义客户端与服务端之间的消息协议数据类。
这些类同时用于服务端和客户端,确保消息格式一致。
"""
from __future__ import annotations
from dataclasses import dataclass, field, asdict
from typing import List, Literal, Optional
import json
@dataclass
class AudioMessage:
"""
客户端 -> 服务端:音频数据消息
Attributes:
task_id: 任务唯一标识
source: 音频来源 ('mic' 麦克风 或 'file' 文件)
data: Base64 编码的音频数据 (float32, 16kHz, mono)
is_final: 是否为当前任务的最后一个数据包
time_start: 录音/音频开始时间戳
seg_duration: 分段时长(秒)
seg_overlap: 重叠时长(秒)
"""
task_id: str
source: Literal['mic', 'file']
data: str # base64 编码的音频
is_final: bool
time_start: float
seg_duration: float = 15.0
seg_overlap: float = 2.0
context: str = ''
language: str = 'auto'
def to_json(self) -> str:
"""序列化为 JSON 字符串"""
return json.dumps(asdict(self), ensure_ascii=False)
@classmethod
def from_dict(cls, data: dict) -> AudioMessage:
"""从字典创建实例"""
return cls(
task_id=data['task_id'],
source=data['source'],
data=data['data'],
is_final=data['is_final'],
time_start=data['time_start'],
seg_duration=data.get('seg_duration', 15.0),
seg_overlap=data.get('seg_overlap', 2.0),
context=data.get('context', ''),
language=data.get('language', 'auto'),
)
@dataclass
class RecognitionMessage:
"""
服务端 -> 客户端:识别结果消息
Attributes:
task_id: 任务唯一标识
is_final: 是否为最终结果(所有片段识别完成)
duration: 已处理的音频总时长(秒)
time_start: 录音/音频开始时间戳
time_submit: 最后一个片段的提交时间戳
time_complete: 识别完成时间戳
text: 主要输出 - 简单文本拼接结果(不依赖时间戳)
text_accu: 精确输出 - 基于时间戳去重的拼接结果(用于字幕生成)
tokens: 字级 token 列表(与 timestamps 对应)
timestamps: 字级时间戳列表(秒)
"""
task_id: str
is_final: bool
duration: float
time_start: float
time_submit: float
time_complete: float
# 主要输出(简单文本拼接)
text: str
# 精确输出(时间戳拼接)
text_accu: str = ''
tokens: List[str] = field(default_factory=list)
timestamps: List[float] = field(default_factory=list)
def to_json(self) -> str:
"""序列化为 JSON 字符串"""
return json.dumps(asdict(self), ensure_ascii=False)
def to_dict(self) -> dict:
"""转换为字典"""
return asdict(self)
@classmethod
def from_dict(cls, data: dict) -> RecognitionMessage:
"""从字典创建实例"""
return cls(
task_id=data['task_id'],
is_final=data['is_final'],
duration=data['duration'],
time_start=data['time_start'],
time_submit=data['time_submit'],
time_complete=data['time_complete'],
text=data['text'],
text_accu=data.get('text_accu', ''),
tokens=data.get('tokens', []),
timestamps=data.get('timestamps', []),
)