speaker_helper.speaker module

High-level speaker-helper API: text in, speech out.

Module summary

Speaker is the façade most applications use. It wraps a TTSEngine backend and offers two modes:

  • offlineSpeaker.say() synthesises the whole text into one AudioResult, optimising throughput/quality.

  • streamingSpeaker.stream() splits the text into sentence-sized chunks and yields audio as soon as each is ready, minimising time to first audio (TTFA). Synthesis is pipelined (bounded concurrency) while emission stays strictly in order.

Blocking convenience wrappers (Speaker.say_sync(), Speaker.save()) are provided for scripts and CLIs that are not already inside an event loop.

Usage example

>>> from speaker_helper import Speaker
>>> # sync, offline — the simplest possible call:
>>> # Speaker().save("Bonjour le monde.", "hello.wav")   # requires Voicebox

Author

Warith HARCHAOUI — https://linkedin.com/in/warith-harchaoui

class speaker_helper.speaker.Speaker(settings=None, *, engine=None, stream_concurrency=1)[source]

Bases: object

Turn text into speech via a pluggable TTS engine, offline or streaming.

The concrete engine (Voicebox, mock, …) is selected by settings.backend and reached only through the TTSEngine protocol, so Speaker never depends on a specific backend.

Parameters:
  • settings (Settings or None) – Configuration; when None, Settings.load() is used (reads ./settings.yaml if present, then SPEAKER_HELPER_* env vars).

  • engine (TTSEngine or None) – Inject a ready backend instance (e.g. a mock in tests). When None (default), one is built from settings via create_engine().

  • stream_concurrency (int) – Maximum number of chunks synthesised in parallel in streaming mode. The default of 1 (a strict pipeline) gives the lowest time to first audio: the first chunk gets the whole engine to itself, and because kokoro synthesises faster than real time (RTF < 1) each later chunk is ready before playback of the previous one finishes. Raise it only to favour total throughput over first-audio latency.

Examples

>>> from speaker_helper import Speaker, Settings
>>> spk = Speaker(Settings.from_mapping({"engine": "kokoro", "language": "fr"}))
>>> spk.settings.engine
'kokoro'
async aclose()[source]

Release the underlying engine’s resources.

Return type:

None

property client: TTSEngine

Backward-compatible alias for engine.

Earlier releases exposed the backend as speaker.client (it was always a Voicebox client). It is now any TTSEngine; this alias keeps old call sites working.

async clone_voice(name=None, samples=None, *, language=None)[source]

Clone a voice and make this speaker synthesise with it.

Parameters:
  • name (str or None) – Profile name for the clone (idempotency key). Defaults to the configured clone name, or "ref-malo".

  • samples (list of VoiceSample or None) – Reference recordings. When None, they are resolved from settings.clone — falling back to the bundled ref-malo reference. A sample without a transcript is transcribed with vocal-helper.

  • language (str or None) – Language of the cloned voice (defaults to the configured language).

Returns:

The cloned voice/profile id.

Return type:

str

Examples

>>> from speaker_helper import Speaker, Settings, VoiceSample
>>> spk = Speaker(Settings.from_mapping({"backend": "mock"}))
>>> # give only the audio; the transcript is derived automatically:
>>> # await spk.clone_voice("malo", [VoiceSample("ref.wav", "")])
classmethod from_profile(profile, settings=None, *, engine=None)[source]

Build a Speaker from a per-language operating profile.

Applies the profile’s language/engine/voice/producer settings and its stream_concurrency (a consumer-parallelism argument, not a Settings field).

Parameters:
Returns:

A speaker configured for the profile’s language.

Return type:

Speaker

classmethod from_route(condition, *, language='fr', settings=None, engine=None, **route_kwargs)[source]

Build a Speaker from a routed operating point.

Asks speaker_helper.router.route() to choose an engine + mode from measured quality↔speed evidence for the given condition ("online_realtime" or "offline"), applies that choice, and forwards the decision’s stream_concurrency.

Parameters:
  • condition (str) – "online_realtime" (delay-bounded streaming) or "offline".

  • language (str) – Target language driving the candidate catalogue.

  • settings (Settings or None) – Base configuration to reconfigure; None uses defaults.

  • engine (TTSEngine or None) – Optional injected backend (e.g. a mock in tests); when given, the routing choice still sets language/mode but this engine is used.

  • **route_kwargs – Extra RouteRequest fields (rtf_ceiling, rtf_budget, quality_floor, require_measured_rtf).

Returns:

A speaker configured for the routed operating point. The chosen RouteDecision is attached as speaker.route for inspection / logging.

Return type:

Speaker

save(text, path, *, language=None)[source]

Synthesise text and write the WAV to path (blocking).

Parameters:
  • text (str) – The text to speak.

  • path (str or Path) – Destination .wav file.

  • language (str or None) – Override the configured target language.

Returns:

The synthesised audio (also written to path).

Return type:

AudioResult

async say(text, *, language=None)[source]

Synthesise text into one AudioResult (offline mode).

Parameters:
  • text (str) – The text to speak.

  • language (str or None) – Override the configured target language for this call.

Returns:

The synthesised audio and its metadata.

Return type:

AudioResult

say_sync(text, *, language=None)[source]

Blocking wrapper around say() for non-async callers.

Parameters:
  • text (str) – The text to speak.

  • language (str or None) – Override the configured target language.

Returns:

The synthesised audio.

Return type:

AudioResult

Raises:

RuntimeError – If called from within a running event loop (use await say).

async stream(text, *, language=None)[source]

Yield audio chunks as they are synthesised (streaming mode).

Parameters:
  • text (str) – The text to speak, split into sentence-sized chunks.

  • language (str or None) – Override the configured target language for this call.

Yields:

StreamChunk – Chunks in order. The first carries ttfa_s (time to first audio); the last has is_final=True.

Return type:

AsyncIterator[StreamChunk]

Notes

Synthesis is pipelined up to stream_concurrency chunks at a time so later chunks are produced while earlier ones are being consumed, but emission order matches the text.

async voices(engine=None)[source]

List preset voices for an engine (defaults to the configured one).

Parameters:

engine (str | None)

Return type:

VoiceList

async warmup()[source]

Prime the engine so the first real request is not the slow one.

Synthesises a tiny throwaway utterance, which forces backend-specific one-time costs (profile bootstrap, model download / load) to happen now rather than on a user’s first call. Failures are logged and swallowed — warm-up is best-effort and must never break startup.

Return type:

None