This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
"""
|
||||
Data models for real-time ASR WebSocket communication.
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from typing import Optional, List, Dict, Any
|
||||
from dataclasses import dataclass, field, asdict
|
||||
import time
|
||||
|
||||
|
||||
class MessageType(str, Enum):
|
||||
"""WebSocket message types."""
|
||||
# Client -> Server
|
||||
AUDIO_CHUNK = "audio_chunk"
|
||||
CONFIG = "config"
|
||||
START = "start"
|
||||
STOP = "stop"
|
||||
|
||||
# Server -> Client
|
||||
PARTIAL_RESULT = "partial_result"
|
||||
FINAL_RESULT = "final_result"
|
||||
VAD_EVENT = "vad_event"
|
||||
ERROR = "error"
|
||||
STATUS = "status"
|
||||
|
||||
|
||||
class VADEventType(str, Enum):
|
||||
"""VAD event types."""
|
||||
SPEECH_START = "speech_start"
|
||||
SPEECH_END = "speech_end"
|
||||
|
||||
|
||||
@dataclass
|
||||
class SessionConfig:
|
||||
"""Configuration for a real-time ASR session."""
|
||||
# Audio parameters
|
||||
sample_rate: int = 16000
|
||||
chunk_duration_sec: float = 3.0
|
||||
overlap_sec: float = 0.5
|
||||
|
||||
# VAD parameters
|
||||
vad_threshold: float = 0.5
|
||||
min_speech_duration_ms: int = 250
|
||||
min_silence_duration_ms: int = 500
|
||||
min_volume_threshold: float = 0.01 # Minimum RMS volume (0.0-1.0) to consider as potential speech
|
||||
|
||||
# ASR parameters
|
||||
max_new_tokens: int = 512
|
||||
temperature: float = 0.0
|
||||
context_info: Optional[str] = None
|
||||
|
||||
# Behavior
|
||||
return_partial_results: bool = True
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return asdict(self)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "SessionConfig":
|
||||
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
|
||||
|
||||
|
||||
@dataclass
|
||||
class TranscriptionSegment:
|
||||
"""A single transcription segment with metadata."""
|
||||
start_time: float
|
||||
end_time: float
|
||||
speaker_id: str
|
||||
text: str
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return asdict(self)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TranscriptionResult:
|
||||
"""Transcription result message."""
|
||||
type: MessageType
|
||||
text: str
|
||||
is_final: bool
|
||||
segments: List[TranscriptionSegment] = field(default_factory=list)
|
||||
latency_ms: float = 0.0
|
||||
timestamp: float = field(default_factory=time.time)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"type": self.type.value,
|
||||
"text": self.text,
|
||||
"is_final": self.is_final,
|
||||
"segments": [s.to_dict() for s in self.segments],
|
||||
"latency_ms": self.latency_ms,
|
||||
"timestamp": self.timestamp,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class VADEvent:
|
||||
"""VAD event message."""
|
||||
type: MessageType = MessageType.VAD_EVENT
|
||||
event: VADEventType = VADEventType.SPEECH_START
|
||||
timestamp: float = field(default_factory=time.time)
|
||||
audio_timestamp_sec: float = 0.0
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"type": self.type.value,
|
||||
"event": self.event.value,
|
||||
"timestamp": self.timestamp,
|
||||
"audio_timestamp_sec": self.audio_timestamp_sec,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class StatusMessage:
|
||||
"""Status message."""
|
||||
type: MessageType = MessageType.STATUS
|
||||
status: str = ""
|
||||
message: str = ""
|
||||
timestamp: float = field(default_factory=time.time)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"type": self.type.value,
|
||||
"status": self.status,
|
||||
"message": self.message,
|
||||
"timestamp": self.timestamp,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class ErrorMessage:
|
||||
"""Error message."""
|
||||
type: MessageType = MessageType.ERROR
|
||||
error: str = ""
|
||||
code: str = ""
|
||||
timestamp: float = field(default_factory=time.time)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"type": self.type.value,
|
||||
"error": self.error,
|
||||
"code": self.code,
|
||||
"timestamp": self.timestamp,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class SpeechSegment:
|
||||
"""Detected speech segment from VAD."""
|
||||
start_sample: int
|
||||
end_sample: int
|
||||
start_sec: float
|
||||
end_sec: float
|
||||
confidence: float = 1.0
|
||||
Reference in New Issue
Block a user