speaker_helper.engine module
Backend-agnostic text-to-speech engine interface and registry.
Module summary
speaker-helper’s value is a small, typed façade over a local TTS engine. The
concrete engine (Voicebox today) is deliberately an implementation detail: the
rest of the package — Speaker, the REST API,
the CLI, the evaluation layer — talks only to the TTSEngine protocol
defined here. Swapping or adding a backend is therefore a local change: write a
class with four coroutines and register it.
Two backends ship in-tree:
voicebox— the real engine,VoiceboxClient.mock—MockEngine, a deterministic, dependency-light synthesiser that needs no server. It makes the test suite and the evaluation layer runnable in CI (and proves the abstraction: the same code paths drive any backend).
create_engine() dispatches on settings.backend. Third parties can add
their own backend at runtime with register_backend().
Usage example
>>> from speaker_helper.config import Settings
>>> from speaker_helper.engine import create_engine
>>> eng = create_engine(Settings.from_mapping({"backend": "mock"}))
>>> type(eng).__name__
'MockEngine'
- class speaker_helper.engine.MockEngine(settings)[source]
Bases:
objectA deterministic, serverless TTS backend for tests and evaluation.
It produces a real (decodable) WAV whose duration is proportional to the input length at a fixed speaking rate, and reports a compute time derived from a configured real-time factor. No audio model runs and no network call is made, so behaviour is reproducible and fast — ideal for CI, for exercising the evaluation layer’s anomaly checks, and for proving that engine-agnostic code paths work against any backend.
- Parameters:
settings (Settings) – Used for
languageandenginelabels and for themockknobs (rtf,chars_per_sec,sample_rate,amplitude,frequency_hz) read viaSettings.mock.
Notes
The audio is a quiet sine tone (not silence) so evaluation’s “empty audio” and “clipping” checks see a realistic, non-degenerate signal. Set
mock.amplitudeabove 1.0 to deliberately synthesise a clipping signal for testing the anomaly detector.- async clone_voice(name, samples, *, language=None)[source]
Pretend to clone a voice; return a deterministic id (no audio model).
Validates that at least one sample is provided (matching the real engine’s contract) but performs no synthesis-model work, so cloning is testable without a server.
- Parameters:
name (str)
samples (list[VoiceSample])
language (str | None)
- Return type:
- async synthesize(text, *, language=None)[source]
Synthesise
textinto a deterministic sine-tone WAV.- Parameters:
- Returns:
A decodable WAV plus duration and a compute time equal to
duration * rtf(soresult.rtfreproduces the configured RTF).- Return type:
- Raises:
ValueError – If
textis empty or whitespace-only.
- class speaker_helper.engine.TTSEngine(*args, **kwargs)[source]
Bases:
ProtocolThe minimal surface every speaker-helper backend must provide.
A backend is any object exposing these four coroutines. Everything else in the package is written against this protocol, never against a concrete engine, so the backend stays swappable.
Notes
@runtime_checkableletsisinstance(obj, TTSEngine)verify the method names are present (not their signatures) — handy in tests and factories.- async clone_voice(name, samples, *, language=None)[source]
Clone a voice from reference
samplesand return its id.Implementations should be idempotent on
name(reuse an existing clone rather than duplicating). A backend that cannot clone may raiseNotImplementedError.- Parameters:
name (str)
samples (list[VoiceSample])
language (str | None)
- Return type:
- speaker_helper.engine.available_backends()[source]
Return the sorted names of all registered backends.
- speaker_helper.engine.create_engine(settings)[source]
Instantiate the backend named by
settings.backend.- Parameters:
settings (Settings) – Configuration; its
backendfield selects the engine.- Returns:
A ready-to-use engine instance.
- Return type:
- Raises:
ValueError – If
settings.backendnames no registered backend.
- speaker_helper.engine.register_backend(name, factory)[source]
Register (or override) a backend factory under
name.- Parameters:
name (str) – Backend identifier used in
settings.backend(case-insensitive).factory (callable) –
Settings -> TTSEngine. Called lazily bycreate_engine().
- Return type:
None