speaker_helper.backends.openvoice module

OpenVoice v2: clone a voice from a short recording.

Module summary

OpenVoice splits the job in two, and that split is why it clones well from very little audio. A base speaker model produces the speech — the words, the prosody, the style — and a tone colour converter then morphs that speech onto the timbre of a target speaker, taken from an embedding extracted from a reference recording. Six to sixty seconds of clean speech is enough, because the reference only has to supply timbre; it never has to teach the model to talk.

The practical consequence is in the error messages below: there are two checkpoints and an extracted embedding, and they fail at three different moments. Telling them apart is most of what this wrapper does beyond calling the model.

Author

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

speaker_helper.backends.openvoice.CACHE_CANDIDATES: tuple[Path, ...] = (PosixPath('/Users/warithharchaoui/.cache/speaker-helper/openvoice'), PosixPath('/Users/warithharchaoui/.cache/sprezzature-skill/openvoice'))

Where the installer puts the checkpoints and the little config that points at them. This package’s cache first, then sprezzature’s — the same two downloads, and no reason to fetch them twice.

speaker_helper.backends.openvoice.EMOTION_STYLE: dict[str, str] = {'angry': 'angry', 'cheerful': 'cheerful', 'enthusiastic': 'excited', 'excited': 'excited', 'friendly': 'friendly', 'neutral': 'default', 'sad': 'sad', 'shouting': 'shouting', 'terrified': 'terrified', 'warm': 'friendly', 'whispering': 'whispering'}

A segment’s emotion → the style the base speaker recognises. Anything outside this set reads as default rather than failing: a document is free to ask for a mood this model has never heard of.

class speaker_helper.backends.openvoice.OpenVoiceEngine(settings)[source]

Bases: object

The OpenVoice v2 backend: a base speaker plus a tone colour converter.

Parameters:

settings (Settings) – voice_sample names the recording to clone. Without one, the built-in base speaker reads in its own timbre.

async aclose()[source]

Drop both models so torch can free them.

Return type:

None

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

Extract the timbre of samples and speak in it from now on.

Idempotent on the reference, not on name: the embedding is derived from the recording, so handing the same file a second time produces the same voice and re-extracting it would only cost time.

Parameters:
Return type:

str

async health()[source]

Which of the two halves is missing, named separately.

Return type:

dict

async list_voices(engine=None)[source]

The base speakers the installed checkpoint ships with.

Parameters:

engine (str | None)

Return type:

VoiceList

async synthesize(text, *, language=None, voice=None, speed=1.0, emotion='neutral', intensity='')[source]

Synthesise one piece of text, in the cloned timbre when there is one.

Parameters:
Return type:

AudioResult

speaker_helper.backends.openvoice.SAMPLE_RATE_HZ: int = 24000

OpenVoice v2 produces 24 kHz mono; kept, so narration can lay its output out beside another engine’s without resampling.

speaker_helper.backends.openvoice.check_install()[source]

Return 0 when this engine could synthesise, 1 otherwise.

Two questions, because they fail at different times and have different answers: the package may be importable while the checkpoints were never fetched, and no amount of pip install fixes the second.

Return type:

int

speaker_helper.backends.openvoice.config_path()[source]

The installer’s config.json, or None when nothing is installed.

Return type:

Path | None