File size: 1,790 Bytes
5838d6a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"""TTS backend abstraction and automatic backend selection.

The dataset builder is agnostic to which engine produces audio. Two
backends are provided:

* :class:`~src.backends.gcp.GCPTTSBackend` — Google Cloud TTS via REST
  API key. Used when a key is available.
* :class:`~src.backends.piper.PiperTTSBackend` — free, local Piper TTS.
  Used as the fall back.
"""

from __future__ import annotations

from typing import List, Optional

from .base import SynthesisResult, TTSBackend, Voice
from .gcp import GCPTTSBackend
from .piper import PiperTTSBackend

__all__ = [
    "SynthesisResult",
    "TTSBackend",
    "Voice",
    "GCPTTSBackend",
    "PiperTTSBackend",
    "select_backend",
]


def select_backend(
    gcp_api_key: Optional[str],
    language_prefixes: List[str],
    max_gcp_voices_per_locale: int,
    max_piper_voices: int,
    sample_rate_hz: int,
) -> TTSBackend:
    """Return a ready TTS backend.

    Prefers Google Cloud TTS when ``gcp_api_key`` is provided and the key
    validates. Otherwise (no key, or the key fails to initialise) falls
    back to the free Piper backend.
    """
    if gcp_api_key and gcp_api_key.strip():
        backend = GCPTTSBackend(
            api_key=gcp_api_key.strip(),
            language_prefixes=language_prefixes,
            max_voices_per_locale=max_gcp_voices_per_locale,
            sample_rate_hz=sample_rate_hz,
        )
        try:
            backend.prepare()
            return backend
        except Exception as exc:  # noqa: BLE001 - any failure => fall back
            print(f"[backend] Google Cloud TTS unavailable ({exc}); falling back to Piper.")

    backend = PiperTTSBackend(
        max_voices=max_piper_voices,
        sample_rate_hz=sample_rate_hz,
    )
    backend.prepare()
    return backend