Local speech synthesis through sherpa-onnx.
Two families, one shape: make the assets present, build one OfflineTts,
generate. They differ only in what a VOICE is.
:piper a voice IS a model — one VITS network per speaker, phonemized
through eSpeak NG tables. Vis uses a system copy when present or the
verified tables carried by a downloaded publisher model archive.
:pocket-tts a voice is a reference CLIP the model clones, so the catalogue
is a WAV per voice: the clips the bundle ships and the ones
somebody imported through voices.clj. Vis exports those
weights itself, so they arrive with every other model.
Which assets exist, where they come from and what they are licensed under is
assets.clj's question; this namespace only asks for them by id.
Local speech synthesis through sherpa-onnx.
Two families, one shape: make the assets present, build one `OfflineTts`,
generate. They differ only in what a VOICE is.
:piper a voice IS a model — one VITS network per speaker, phonemized
through eSpeak NG tables. Vis uses a system copy when present or the
verified tables carried by a downloaded publisher model archive.
:pocket-tts a voice is a reference CLIP the model clones, so the catalogue
is a WAV per voice: the clips the bundle ships and the ones
somebody imported through `voices.clj`. Vis exports those
weights itself, so they arrive with every other model.
Which assets exist, where they come from and what they are licensed under is
`assets.clj`'s question; this namespace only asks for them by id.Speech is roughly this many characters a second, and that is the only estimate available before generation starts: an offline TTS model reports the samples it has produced, never the ones it still owes. Progress is therefore honest about being an estimate — it never goes backwards and never reaches 100 until the audio is written.
Speech is roughly this many characters a second, and that is the only estimate available before generation starts: an offline TTS model reports the samples it has produced, never the ones it still owes. Progress is therefore honest about being an estimate — it never goes backwards and never reaches 100 until the audio is written.
Where each package manager puts the tables, in the order they are tried.
Where each package manager puts the tables, in the order they are tried.
(espeak-data-dir)Usable eSpeak NG phoneme tables. An explicitly named directory wins, then a Piper archive installed in Vis' model store, then a system package.
Usable eSpeak NG phoneme tables. An explicitly named directory wins, then a Piper archive installed in Vis' model store, then a system package.
(espeak-data-dir? dir)True when dir holds espeak-ng's tables and not merely the right name.
True when `dir` holds espeak-ng's tables and not merely the right name.
What makes a directory espeak-ng's data directory rather than any directory.
What makes a directory espeak-ng's data directory rather than any directory.
(espeak-install-hint)How to get the tables on THIS platform, in the words that machine uses.
How to get the tables on THIS platform, in the words that machine uses.
(install-model! family)(install-model! family voice-id on-progress)Blocking install of everything family needs before it can speak, for the
CLI. Unlike start-download! it accepts an OPT-IN model: a user naming one
IS the explicit ask assets/ensure! refuses to make on their behalf.
Returns the install dir of every asset actually fetched, in order.
Blocking install of everything `family` needs before it can speak, for the CLI. Unlike [[start-download!]] it accepts an OPT-IN model: a user naming one IS the explicit ask [[assets/ensure!]] refuses to make on their behalf. Returns the install dir of every asset actually fetched, in order.
(piper-assets)Every Piper voice in the manifest, in manifest order. The FIRST is the default.
Every Piper voice in the manifest, in manifest order. The FIRST is the default.
(piper-sample voice-id)Where the sample of a Piper voice is - or what it would take to have one, and never a byte the user did not ask for:
{:audio-path …} one is already on disk
{:is-preparable true} prepare-piper-sample! can make one out of the
0.7 MB pack, or out of a model already installed
nil the only way to hear this voice is to install it,
and a play press is not consent to 115 MB
Throws for a voice no Piper entry names.
Where the sample of a Piper voice is - or what it would take to have one, and
never a byte the user did not ask for:
{:audio-path …} one is already on disk
{:is-preparable true} [[prepare-piper-sample!]] can make one out of the
0.7 MB pack, or out of a model already installed
nil the only way to hear this voice is to install it,
and a play press is not consent to 115 MB
Throws for a voice no Piper entry names.(piper-voices)Piper voices with the licence facts a consent surface must show.
Piper voices with the licence facts a consent surface must show.
(pocket-sample voice-id)A pocket voice IS a reference clip, so its sample is that clip: already on disk for a voice somebody imported, part of the bundle for a shipped one. Nothing to prepare and nothing to fetch - when the bundle is absent there is no sample, because 96 MB is not a preview.
A pocket voice IS a reference clip, so its sample is that clip: already on disk for a voice somebody imported, part of the bundle for a shipped one. Nothing to prepare and nothing to fetch - when the bundle is absent there is no sample, because 96 MB is not a preview.
(pocket-voice-catalogue)The pocket catalogue with each clip resolved to an absolute path: the clips the bundle ships first, then the imported ones. An import with the same id WINS - somebody who names their own recording after a shipped voice meant their own recording.
The pocket catalogue with each clip resolved to an absolute path: the clips the bundle ships first, then the imported ones. An import with the same id WINS - somebody who names their own recording after a shipped voice meant their own recording.
(pocket-voices)The voices pocket-tts can speak in - the clips the bundle carries and the ones somebody imported - without the path: which file backs a voice is nobody else's business.
The voices pocket-tts can speak in - the clips the bundle carries and the ones somebody imported - without the path: which file backs a voice is nobody else's business.
(prepare-piper-sample! voice-id)Make the sample piper-sample said was preparable and return it. Installs
the pack (0.7 MB, four voices at once) or speaks the sentence with a model
that is already here and KEEPS the result, so the second press is instant and
shared by every surface on this machine. Never downloads a voice model.
Make the sample [[piper-sample]] said was preparable and return it. Installs the pack (0.7 MB, four voices at once) or speaks the sentence with a model that is already here and KEEPS the result, so the second press is instant and shared by every surface on this machine. Never downloads a voice model.
The sentence every voice reads. A sample is a COMPARISON, and a comparison where each voice reads different words compares the words: one sentence, ordinary punctuation, long enough to hear a pace and a breath. (The pocket reference clips differ on purpose - those are cloned, not compared.)
The sentence every voice reads. A sample is a COMPARISON, and a comparison where each voice reads different words compares the words: one sentence, ordinary punctuation, long enough to hear a pace and a breath. (The pocket reference clips differ on purpose - those are cloned, not compared.)
(start-download! family)(start-download! family voice-id)(start-download! family voice-id is-license-accepted)Begin every required download without blocking. An opt-in voice starts only when
is-license-accepted is true for this explicit request.
Begin every required download without blocking. An opt-in voice starts only when `is-license-accepted` is true for this explicit request.
(synthesize! family request)Synthesize audio with correlated, content-free lifecycle diagnostics.
Synthesize audio with correlated, content-free lifecycle diagnostics.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |