Files
voiceagent/src/voice_assistant/audio/models.py

41 lines
1.2 KiB
Python

"""PCM format contracts shared by application, transports, and providers.
The canonical input is mono PCM S16LE at 16 kHz. Output uses the format
explicitly declared by the TTS provider. Declaring a sample rate does not
convert or resample audio; provider adapters own any required conversion.
"""
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field
class AudioFormat(BaseModel):
"""An immutable PCM format; a frame contains one sample per channel."""
model_config = ConfigDict(frozen=True)
encoding: Literal["pcm_s16le"]
sample_rate: int = Field(gt=0, strict=True)
channels: int = Field(gt=0, strict=True)
@property
def frame_size_bytes(self) -> int:
return 2 * self.channels
def validate_chunk(self, audio: bytes) -> None:
if not audio:
raise ValueError("Audio chunk cannot be empty.")
if len(audio) % self.frame_size_bytes:
raise ValueError(
"PCM chunk must contain complete frames of "
f"{self.frame_size_bytes} bytes."
)
CANONICAL_AUDIO_FORMAT = AudioFormat(
encoding="pcm_s16le",
sample_rate=16000,
channels=1,
)