speaker_helper package

Subpackages

Submodules

Module contents

speaker-helper — professional text-to-speech, offline and streaming.

Module summary

speaker-helper is the inverse of vocal-helper: it turns text into speech. It wraps the local Voicebox engine behind a small, typed API with two modes — offline (whole text → one audio) and streaming (sentence-split, low time-to-first-audio) — and ships a CLI and a REST API. It runs locally (conda + pip) or as a Docker server.

The default engine is kokoro, which synthesises faster than real time on CPU (real-time factor well below 1.0).

Usage example

>>> from speaker_helper import Speaker, Settings
>>> spk = Speaker(Settings.from_mapping({"engine": "kokoro", "language": "fr"}))
>>> # spk.save("Bonjour le monde.", "hello.wav")   # requires a running Voicebox

See EXAMPLES.md for a runnable cookbook.

Author

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

class speaker_helper.AudioResult(wav_bytes, sample_rate, duration_s, compute_s, text, voice_id, language)[source]

Bases: object

A synthesised audio payload and its measured metadata.

Parameters:
  • wav_bytes (bytes) – The complete WAV file contents (RIFF header + PCM), ready to write to disk or stream to a client.

  • sample_rate (int) – Sample rate of the audio in Hz.

  • duration_s (float) – Audio duration in seconds.

  • compute_s (float) – Wall-clock seconds spent producing this audio (network + synthesis).

  • text (str) – The text that was synthesised.

  • voice_id (str) – The voice used.

  • language (str) – The language used.

Notes

rtf (real-time factor) is derived, not stored: compute_s / duration_s. A value below 1.0 means synthesis was faster than real time — the operating point speaker-helper aims for.

compute_s: float
duration_s: float
language: str
property rtf: float

Real-time factor compute_s / duration_s (inf if silent).

Returns:

Below 1.0 means faster than real time.

Return type:

float

sample_rate: int
text: str
voice_id: str
wav_bytes: bytes
class speaker_helper.LanguageProfile(language, engine='kokoro', voice_id='', normalize=True, first_chunk_sentences=1, stream_concurrency=1, measured_rtf=None, measured_quality=None)[source]

Bases: object

Hyperparameters and a measured operating point for one language.

Parameters:
  • language (str) – ISO-639-1 code this profile targets.

  • engine (str) – Engine/model id to use for this language.

  • voice_id (str) – Preset voice id; empty means “auto-pick a voice for the language”.

  • normalize (bool) – Ask the engine to loudness-normalise the output.

  • first_chunk_sentences (int) – Streaming producer granularity — sentences in the first emitted chunk. 1 minimises time-to-first-audio.

  • stream_concurrency (int) – Streaming consumer parallelism — chunks synthesised at once. 1 is a strict pipeline (lowest first-audio latency).

  • measured_rtf (float or None) – Mean real-time factor measured for this language, or None if untuned.

  • measured_quality (float or None) – Quality score in [0, 1] measured for this language, or None.

apply(settings=None)[source]

Return settings (or fresh defaults) with this profile applied.

Parameters:

settings (Settings or None) – Base configuration to derive from; None uses defaults.

Returns:

A copy carrying this profile’s language, engine, voice, and producer granularity. stream_concurrency is a Speaker argument, not a Settings field, so pass it separately (see from_profile()).

Return type:

Settings

engine: str = 'kokoro'
first_chunk_sentences: int = 1
language: str
measured_quality: float | None = None
measured_rtf: float | None = None
normalize: bool = True
stream_concurrency: int = 1
voice_id: str = ''
with_measurement(report)[source]

Return a copy with measured_rtf/measured_quality from a report.

Parameters:

report (EvalReport) – A report for this language (duck-typed: needs mean_rtf and quality).

Returns:

A copy carrying the measured operating point.

Return type:

LanguageProfile

class speaker_helper.MockEngine(settings)[source]

Bases: object

A 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 language and engine labels and for the mock knobs (rtf, chars_per_sec, sample_rate, amplitude, frequency_hz) read via Settings.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.amplitude above 1.0 to deliberately synthesise a clipping signal for testing the anomaly detector.

async aclose()[source]

No-op: the mock holds no resources.

Return type:

None

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:
Return type:

str

async health()[source]

Return a static healthy document identifying the mock backend.

Return type:

dict

async list_voices(engine=None)[source]

Return a small fixed set of fake voices for engine.

Parameters:

engine (str | None)

Return type:

VoiceList

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

Synthesise text into a deterministic sine-tone WAV.

Parameters:
  • text (str) – Text to “speak” (must be non-empty). Only its length drives the output duration; content is not spoken.

  • language (str or None) – Override the configured language label on the result.

Returns:

A decodable WAV plus duration and a compute time equal to duration * rtf (so result.rtf reproduces the configured RTF).

Return type:

AudioResult

Raises:

ValueError – If text is empty or whitespace-only.

class speaker_helper.OperatingPoint(engine, quality, mean_rtf, quality_source='prior', rtf_source='unknown', backend='voicebox', language=None)[source]

Bases: object

One engine’s position on the quality↔speed plane, with provenance.

Parameters:
  • engine (str) – Engine/model id (e.g. "kokoro").

  • quality (float) – Quality score in [0, 1] to maximise (measured chrF or a prior).

  • mean_rtf (float or None) – Mean real-time factor to minimise; None when never measured (the engine then cannot be routed for the online condition).

  • quality_source (str) – "measured_chrf" or "prior" — how quality was obtained.

  • rtf_source (str) – "measured", "estimate", or "unknown" — how mean_rtf was obtained.

  • backend (str) – The backend that serves this engine (default "voicebox").

  • language (str or None) – Language the measurement pertains to, when language-specific.

backend: str = 'voicebox'
engine: str
language: str | None = None
mean_rtf: float | None
quality: float
quality_source: str = 'prior'
rtf_source: str = 'unknown'
class speaker_helper.RouteDecision(condition, engine, backend, mode, first_chunk_sentences, stream_concurrency, quality, mean_rtf, quality_source, rtf_source, confidence, justification, candidates_considered, pareto_size)[source]

Bases: object

A concrete, justified operating point the caller can act on.

Parameters:
  • condition (str) – The condition this decision answers.

  • engine (str) – The chosen engine and the backend that serves it.

  • backend (str) – The chosen engine and the backend that serves it.

  • mode (str) – "streaming" (online) or "offline".

  • first_chunk_sentences (int) – Streaming producer/consumer knobs implied by the condition (only meaningful when mode == "streaming").

  • stream_concurrency (int) – Streaming producer/consumer knobs implied by the condition (only meaningful when mode == "streaming").

  • quality (float) – The chosen point’s quality score.

  • mean_rtf (float or None) – The chosen point’s mean RTF (None only in the offline, RTF-unknown fallback).

  • quality_source (str) – Provenance of the two axes (see OperatingPoint).

  • rtf_source (str) – Provenance of the two axes (see OperatingPoint).

  • confidence (str) – "high" (both axes measured), "medium" (one measured), or "low" (both from priors/estimates).

  • justification (str) – A human-readable, number-citing explanation of why this point won.

  • candidates_considered (int) – How many candidates were weighed and how many survived to the Pareto front — for auditability.

  • pareto_size (int) – How many candidates were weighed and how many survived to the Pareto front — for auditability.

apply(settings=None)[source]

Return settings (or fresh defaults) reconfigured for this decision.

Parameters:

settings (Settings or None) – Base configuration to derive from; None uses defaults.

Returns:

A copy carrying the chosen backend, engine, mode, and (for streaming) the first-chunk granularity. stream_concurrency is a Speaker argument, not a Settings field, so read it off this decision separately (see from_route()).

Return type:

Settings

backend: str
candidates_considered: int
condition: str
confidence: str
engine: str
first_chunk_sentences: int
justification: str
mean_rtf: float | None
mode: str
pareto_size: int
quality: float
quality_source: str
rtf_source: str
stream_concurrency: int
to_dict()[source]

Return a JSON-serialisable dict of the decision (for API / MCP / CLI).

Return type:

dict

class speaker_helper.RouteRequest(condition, language='fr', rtf_ceiling=0.8, rtf_budget=None, quality_floor=None, require_measured_rtf=True)[source]

Bases: object

What the caller needs; the router turns it into a justified choice.

Parameters:
  • condition (str) – "online_realtime" (delay-bounded streaming) or "offline" (throughput / quality). See CONDITIONS.

  • language (str) – ISO-639-1 target language (drives the default catalogue and profile).

  • rtf_ceiling (float) – Online only: the hard mean_rtf bound an engine must beat to be feasible. Defaults to DEFAULT_RTF_CEILING (0.8).

  • rtf_budget (float or None) – Offline only: optional patience cap on mean_rtf (None = no cap, quality is all that matters).

  • quality_floor (float or None) – Reject any candidate below this quality, in both conditions (None = no floor).

  • require_measured_rtf (bool) – Online only: refuse engines whose RTF was never measured (default True — do not claim an untimed engine keeps up).

condition: str
language: str = 'fr'
quality_floor: float | None = None
require_measured_rtf: bool = True
rtf_budget: float | None = None
rtf_ceiling: float = 0.8
class speaker_helper.Settings(voicebox=<factory>, backend='voicebox', engine='kokoro', voice_id='', language='fr', normalize=True, mode='offline', first_chunk_sentences=1, mock=<factory>, clone=<factory>)[source]

Bases: object

Top-level speaker-helper configuration.

Parameters:
  • voicebox (VoiceboxConfig) – Connection details for the Voicebox engine.

  • backend (str) – Which TTS backend to drive: "voicebox" (the real engine, default) or "mock" (deterministic, serverless — used by tests and the evaluation layer). The backend is an implementation detail; the rest of the package talks only to the TTSEngine protocol. See speaker_helper.engine.available_backends().

  • engine (str) – Backend-specific engine/model id. For Voicebox, kokoro is fast enough for real-time on CPU.

  • voice_id (str) – Preset voice id. Empty (default) means “auto-pick a voice whose language matches language”.

  • language (str) – ISO-639-1 target language (e.g. "fr").

  • normalize (bool) – Ask Voicebox to loudness-normalise the output.

  • mode (str) – "offline" or "streaming".

  • first_chunk_sentences (int) – Streaming only: sentences in the first emitted chunk (1 → lowest TTFA).

  • mock (dict[str, Any])

  • clone (dict[str, Any])

Notes

Precedence, lowest to highest: dataclass defaults → settings.yamlSPEAKER_HELPER_* environment variables.

backend: str = 'voicebox'
property base_url: str

Return the Voicebox base URL, e.g. http://127.0.0.1:17600.

clone: dict[str, Any]
engine: str = 'kokoro'
first_chunk_sentences: int = 1
classmethod from_mapping(mapping)[source]

Build settings from a plain mapping (unknown keys ignored).

Parameters:

mapping (dict or None) – Nested mapping mirroring the dataclass fields.

Returns:

The populated settings, with environment overrides applied.

Return type:

Settings

classmethod from_yaml_text(text)[source]

Build settings from a YAML document string.

Parameters:

text (str) – YAML source.

Returns:

The populated settings.

Return type:

Settings

language: str = 'fr'
classmethod load(path=None)[source]

Load settings from a YAML file if present, else defaults + env.

Parameters:

path (str or Path or None) – Path to a settings.yaml. When None, ./settings.yaml is used if it exists; otherwise dataclass defaults apply. Environment overrides are always applied last.

Returns:

The populated settings.

Return type:

Settings

mock: dict[str, Any]
mode: str = 'offline'
normalize: bool = True
voice_id: str = ''
voicebox: VoiceboxConfig
class speaker_helper.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

class speaker_helper.StreamChunk(seq, audio, ttfa_s=None, is_final=False)[source]

Bases: object

One chunk of a streaming synthesis (one sentence-sized unit).

Parameters:
  • seq (int) – Zero-based index of this chunk within the stream.

  • audio (AudioResult) – The synthesised audio for this chunk.

  • ttfa_s (float | None) – Time-to-first-audio in seconds, set only on the first chunk (seq == 0); None afterwards.

  • is_final (bool) – True for the last chunk of the stream.

audio: AudioResult
is_final: bool = False
seq: int
ttfa_s: float | None = None
class speaker_helper.TTSEngine(*args, **kwargs)[source]

Bases: Protocol

The 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_checkable lets isinstance(obj, TTSEngine) verify the method names are present (not their signatures) — handy in tests and factories.

async aclose()[source]

Release any held resources (HTTP clients, handles, …).

Return type:

None

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

Clone a voice from reference samples and return its id.

Implementations should be idempotent on name (reuse an existing clone rather than duplicating). A backend that cannot clone may raise NotImplementedError.

Parameters:
Return type:

str

async health()[source]

Return a backend health document (must include a status key).

Return type:

dict

async list_voices(engine=None)[source]

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

Parameters:

engine (str | None)

Return type:

VoiceList

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

Synthesise text into one AudioResult.

Parameters:
  • text (str)

  • language (str | None)

Return type:

AudioResult

class speaker_helper.Voice(voice_id, name, language, gender='', engine='')[source]

Bases: object

A preset voice offered by a Voicebox engine.

Parameters:
  • voice_id (str) – Engine-specific identifier (e.g. "ff_siwis" for kokoro French).

  • name (str) – Human-readable display name.

  • language (str) – ISO-639-1 language code the voice speaks (e.g. "fr", "en").

  • gender (str) – Reported voice gender, or "" when the engine does not expose one.

  • engine (str) – Engine the voice belongs to (e.g. "kokoro").

engine: str = ''
gender: str = ''
language: str
name: str
voice_id: str
class speaker_helper.VoiceList(engine, voices=<factory>)[source]

Bases: object

Voices available for an engine.

Parameters:
  • engine (str) – The engine the voices belong to.

  • voices (list[Voice]) – The preset voices, possibly empty.

engine: str
voices: list[Voice]
class speaker_helper.VoiceSample(audio, reference_text)[source]

Bases: object

One reference recording used to clone a voice.

Parameters:
  • audio (bytes or str) – The reference audio: raw bytes, or a filesystem path to an audio file.

  • reference_text (str) – A transcript of exactly what is said in audio. Cloning engines align the audio to this text, so it must match the recording.

Notes

Keep samples short and clean (a few seconds of clear speech). Provide several for a more robust clone.

audio: bytes | str
filename()[source]

Return a filename to send with the upload (from the path, or a default).

Return type:

str

read_bytes()[source]

Return the audio as bytes, reading from disk if a path was given.

Return type:

bytes

reference_text: str
class speaker_helper.VoiceboxClient(settings)[source]

Bases: object

A typed async client over the Voicebox TTS REST API.

Parameters:

settings (Settings) – Connection and voice configuration. See speaker_helper.config.Settings.

Notes

The client owns an httpx.AsyncClient. Use it as an async context manager (async with) or call aclose() when done. A single client caches the resolved profile_id so repeated syntheses skip the profile bootstrap.

async aclose()[source]

Close the underlying HTTP client and release its connections.

Return type:

None

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

Clone a voice from reference samples and use it for synthesis.

Parameters:
  • name (str) – Profile name for the clone (idempotency key). A matching profile is reused rather than duplicated.

  • samples (list of VoiceSample) – Reference recordings. Any sample without a reference_text is transcribed with vocal-helper before upload.

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

Returns:

The cloned profile id (also set as this client’s active profile).

Return type:

str

Raises:

VoiceboxError – On a Voicebox error.

async ensure_profile()[source]

Return a usable profile_id, creating a preset one idempotently.

Returns:

The profile id to pass to synthesis calls.

Return type:

str

Notes

Reuses an existing profile for the resolved preset voice rather than creating a duplicate (Voicebox rejects duplicate names), so a fresh client never fails on the second run. Safe under concurrency via an internal lock.

async health()[source]

Return the Voicebox /health payload.

Returns:

The server health document (backend variant, gpu availability, …).

Return type:

dict

Raises:

VoiceboxError – If the server is unreachable or returns a non-2xx status.

async list_voices(engine=None)[source]

List the preset voices for an engine.

Parameters:

engine (str or None) – Engine id; defaults to the configured engine.

Returns:

The engine and its preset voices (possibly empty).

Return type:

VoiceList

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

Synthesise text into a single AudioResult.

Parameters:
  • text (str) – The text to speak. Must be non-empty.

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

Returns:

The synthesised WAV plus measured duration and compute time.

Return type:

AudioResult

Raises:
  • ValueError – If text is empty or whitespace-only.

  • VoiceboxError – On a Voicebox error or an undecodable response.

Notes

Uses POST /generate/stream (synchronous WAV bytes). The first call for a not-yet-downloaded engine model transparently falls back to the async /generate path, which triggers the download.

class speaker_helper.VoiceboxConfig(host='127.0.0.1', port=17493, timeout_s=300.0, max_retries=2, retry_backoff_s=0.5)[source]

Bases: object

Where the Voicebox REST service lives.

Parameters:
  • host (str) – Hostname or IP of the Voicebox server. Default 127.0.0.1.

  • port (int) – TCP port. Voicebox’s native default is 17493; the bundled docker-compose maps the container to 17600 on the host.

  • timeout_s (float) – Per-request timeout in seconds. The first synthesis of a new engine pays a model download, so keep this generous.

  • max_retries (int) – How many times to retry a request that fails on a transient error (network/transport error or a 5xx from the engine). 0 disables retries. Client errors (4xx) are never retried.

  • retry_backoff_s (float) – Base delay for exponential backoff between retries: attempt k waits retry_backoff_s * 2**(k-1) seconds.

host: str = '127.0.0.1'
max_retries: int = 2
port: int = 17493
retry_backoff_s: float = 0.5
timeout_s: float = 300.0
exception speaker_helper.VoiceboxError[source]

Bases: RuntimeError

Raised when Voicebox returns an error or an unexpected response.

speaker_helper.available_backends()[source]

Return the sorted names of all registered backends.

Return type:

list[str]

speaker_helper.chunk_for_streaming(text, first_chunk_sentences=1)[source]

Group sentences into synthesis chunks, keeping the first one small.

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

  • first_chunk_sentences (int, optional) – How many sentences to place in the first chunk. Keeping this at 1 (the default) minimises TTFA; larger values reduce per-chunk overhead at the cost of a slower first emission.

Returns:

Chunks of text to synthesise in order. The first chunk holds first_chunk_sentences sentences; every remaining sentence is its own chunk so downstream audio keeps flowing steadily.

Return type:

list[str]

Examples

>>> chunk_for_streaming("A. B. C.", first_chunk_sentences=1)
['A.', 'B.', 'C.']
>>> chunk_for_streaming("A. B. C.", first_chunk_sentences=2)
['A. B.', 'C.']
speaker_helper.create_engine(settings)[source]

Instantiate the backend named by settings.backend.

Parameters:

settings (Settings) – Configuration; its backend field selects the engine.

Returns:

A ready-to-use engine instance.

Return type:

TTSEngine

Raises:

ValueError – If settings.backend names no registered backend.

speaker_helper.default_operating_points(language='fr')[source]

Build the fallback candidate set for language from profiles + priors.

The per-language profile supplies the measured kokoro operating point (RTF from native-MLX tuning; quality is the engine prior until a round-trip recalibrates it). Every other engine in the priors table contributes a quality-only candidate with an unknown RTF — enough to reason about offline quality, but deliberately not enough to claim it keeps up online.

Parameters:

language (str) – Language whose profile seeds the measured kokoro point.

Returns:

One candidate per known engine, provenance flagged on both axes.

Return type:

list of OperatingPoint

speaker_helper.profile_for(language)[source]

Return the profile for language (a default profile if none is defined).

Parameters:

language (str)

Return type:

LanguageProfile

speaker_helper.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 by create_engine().

Return type:

None

speaker_helper.route(request, *, points=None, reports=None)[source]

Choose a justified engine + mode for request from the evidence.

Parameters:
  • request (RouteRequest) – The condition and its constraints.

  • points (sequence of OperatingPoint or None) – Explicit candidate operating points. When None and reports is also None, the built-in catalogue for request.language is used.

  • reports (sequence of EvalReport or None) – Measured reports to derive candidates from (highest confidence). Takes precedence over points when both are given.

Returns:

The chosen operating point, mode, streaming knobs, and a number-citing justification.

Return type:

RouteDecision

Raises:

ValueError – If request.condition is unknown, or no candidate satisfies the condition’s constraints (e.g. no engine keeps up online).

Examples

>>> route(RouteRequest(condition="offline", language="fr")).mode
'offline'
speaker_helper.route_settings(condition, *, language='fr', settings=None, **request_kwargs)[source]

Convenience: route for condition and return applied settings + decision.

Parameters:
  • condition (str) – "online_realtime" or "offline".

  • language (str) – Target language.

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

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

Returns:

Settings reconfigured for the decision, and the decision itself (its stream_concurrency still needs forwarding to Speaker).

Return type:

tuple of (Settings, RouteDecision)

speaker_helper.split_sentences(text)[source]

Split text into sentence-sized, non-empty, stripped units.

Parameters:

text (str) – Arbitrary text, possibly multi-sentence and multi-line.

Returns:

Sentences in order, each stripped of surrounding whitespace, with their terminating punctuation preserved. Text without any terminator returns a single-element list (the whole stripped input); empty or whitespace-only input returns an empty list.

Return type:

list[str]

Examples

>>> split_sentences("Un. Deux. Trois.")
['Un.', 'Deux.', 'Trois.']
>>> split_sentences("no terminator here")
['no terminator here']
>>> split_sentences("   ")
[]
async speaker_helper.tune_profiles(base_settings, languages, **eval_kwargs)[source]

Measure a set of languages and return profiles carrying the results.

A thin convenience over run_multilang_eval(): it runs the evaluation per language and folds each report’s RTF/quality into the corresponding LanguageProfile.

Parameters:
  • base_settings (Settings) – Base configuration (backend, engine, connection).

  • languages (list of str) – Language codes to measure and profile.

  • **eval_kwargs – Forwarded to run_multilang_eval() (e.g. thresholds, transcriber, warmup).

Returns:

Mapping language -> LanguageProfile with measured RTF/quality.

Return type:

dict