File size: 1,245 Bytes
414dc55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
"""TTS provider abstraction.

``SupertonicProvider`` gives each suspect a distinct on-device voice. ``NullProvider``
(silent) is the safe fallback, so the game stays fully playable as text if the voice
model is unavailable.
"""

from __future__ import annotations

from pathlib import Path
from typing import Protocol

from ..config import Settings, TTSEngine
from ..schemas.suspect import VoiceAssignment


class TTSProvider(Protocol):
    is_local: bool
    available: bool

    def synth_to_file(self, text: str, voice: VoiceAssignment | None, out_path: Path) -> Path | None:
        """Write a WAV for ``text`` and return its path, or None if unavailable."""
        ...


class NullProvider:
    is_local = True
    available = False

    def synth_to_file(self, text: str, voice: VoiceAssignment | None, out_path: Path) -> None:
        return None


def make_tts_provider(settings: Settings) -> TTSProvider:
    if settings.tts_engine is TTSEngine.SUPERTONIC:
        try:
            from .supertonic_provider import SupertonicProvider

            provider = SupertonicProvider()
            return provider if provider.available else NullProvider()
        except Exception:
            return NullProvider()
    return NullProvider()