Spaces:
Runtime error
Runtime error
| """TTS client contract + offline fake. | |
| Real implementations land in M2: edge-tts as primary (unofficial API, hence | |
| fragile) plus a local fallback behind this same Protocol (ADR 0001). | |
| The fake returns a *valid* WAV (short silence) so audio components and tests | |
| exercise the real byte path end to end. | |
| """ | |
| import io | |
| import wave | |
| from typing import Protocol, runtime_checkable | |
| from pydantic import BaseModel | |
| class TTSResult(BaseModel): | |
| audio: bytes | |
| format: str = "wav" | |
| voice: str | None = None | |
| class TTSClient(Protocol): | |
| async def synthesize( | |
| self, text: str, *, language: str = "en", voice: str | None = None | |
| ) -> TTSResult: ... | |
| def _silent_wav(duration_s: float = 0.2, sample_rate: int = 16_000) -> bytes: | |
| buffer = io.BytesIO() | |
| with wave.open(buffer, "wb") as wav: | |
| wav.setnchannels(1) | |
| wav.setsampwidth(2) # 16-bit PCM | |
| wav.setframerate(sample_rate) | |
| wav.writeframes(b"\x00\x00" * int(duration_s * sample_rate)) | |
| return buffer.getvalue() | |
| class FakeTTSClient: | |
| def __init__(self) -> None: | |
| self.calls: list[str] = [] | |
| async def synthesize( | |
| self, text: str, *, language: str = "en", voice: str | None = None | |
| ) -> TTSResult: | |
| self.calls.append(text) | |
| return TTSResult(audio=_silent_wav(), format="wav", voice=voice or f"fake-{language}") | |