Skip to main content

Speech datasets: data_speech

data_speech makes the recordings the speech recipes train and are measured on: a teacher writes lines (or the seeds are the lines), a Piper voice reads each one, Whisper checks what it heard, and the recordings whose transcript matches their text are written out with a manifest that carries the voice's terms.

Shipped configMakesRead byFor
data/speech.yamlassistant lines written by a local model, plus the agent's fixed repliesone voice (jgkawell/jarvis)tts_piper
data/wake_phrase.yamlthe name, "Jarvis.", as a statement, question and call300 speakers of LibriTTS-Rwakeword positives
data/wake_negatives.yamlnear misses, the commands said alone, ordinary lines40 speakerswakeword negatives
data/wake_nearmiss.yaml20 near misses of the name120 more speakerswakeword negatives
data/wake_eval_phrase.yaml, wake_eval_negatives.yamlthe name, near misses and commandsVCTK, a voice training never heardevaluation_wakeword

Five stages take seeds to a directory Piper can train on. The first two are those of data_synthetic (seeds, and the texts made from them); then synthesize, verify and select. Every recording and every transcript is kept under its natural key, so a run that stops halfway continues where it stopped, and a run with stricter checks reuses the recordings it already has.

Stages and settings​

pipeline: {recipe: data_speech, name: jarvis-lines}
teacher: {name: ollama, model: qwen3.5:0.8b} # only for generators that ask a model; passthrough needs none
seeds: [{kind: situation, values: [a morning briefing, a security alert]}]
prompts: {generator: utterances, params: {n: 5, language: English, speaker: "a formal British AI butler"}}
voice:
model: {name: jgkawell/jarvis, revision: <commit>, file: en/en_GB/jarvis/medium/jarvis-medium.onnx} # or a local .onnx
samples: 1 # recordings per text; length_scale, noise_scale, noise_w_scale
speakers: null # a multi-speaker voice: ids [3, 7] or n for ids 0..n-1
verify: {min_seconds: 0.5, max_seconds: 15, max_clipped: 0.001, max_silent: 0.5, max_wer: 0.2, asr: {language: en}}
select: {per_text: 1, max_rows: null} # per_text null keeps every recording of a text
licence: "terms of the voice, copied into the manifest"

A Piper training set from seeds: seeds and prompts are the stages of data_synthetic (the utterances generator asks for lines to be read aloud, one or two sentences with numbers written as words; passthrough reads the seeds as they are, so the lines of an existing metadata.csv can be read again through the delimited source; a seed of kind line, such as the agent's name or a fixed reply, is read as it is by every generator). A Piper voice reads every text and Whisper checks what it heard. The voice runs as a separate process from the Piper environment (environment/piper/setup.sh, PIPER_PYTHON; see the tts_piper section of the main README).

StageDoesIdempotent because
synthesizethe voice reads each prompt samples times, by each of voice.speakers, into audio/<key>.wav; | and line breaks are taken out of the text first, so the text is exactly what was readthe voice, its settings and the Piper lock are in the fingerprint, so a file is named by prompt, speaker and sample alone; a rerun reads only texts without a file. Piper's noise is unseeded, so the first reading is the one kept
verifylength, clipped samples and silent frames first; then Whisper (verify.asr, pinned) transcribes the recording and the word error rate against the text decides; every rejection keeps its reason and measurementspure checks over the files; each transcript is cached under the recording's key
selectper text (case and spacing ignored) the per_text recordings Whisper understood best; wavs/, metadata.csv (wavs/<key>.wav|text), rows.jsonl (audio, text, paths relative to the file) and manifest.json with the voice, the licence and each stage's countspure function of the verified rows; recordings are hard-linked (copied across file systems) through a temporary name

The dataset directory is the stage directory, reached through <experiment>/select/: tts_piper reads its rows.jsonl with local_jsonl, and Piper itself reads metadata.csv with that directory as --data.audio_dir. The licence is a required key because a voice's terms bind every recording it makes; the manifest is where the next reader finds them.

Many speakers serve the wake word: data/wake_phrase.yaml has 300 speakers of one voice read the wake word and keeps every recording Whisper hears exactly, and wakeword trains on them (main README). A Piper training set stays single-voice: Piper's multi-speaker format (a speaker column) is not written yet.

Not yet: Piper's multi-speaker training format, text normalisation beyond what the generator asks for, a speaker-similarity check.

Source: data/README.md. This page is generated; edit the source and run npm run sync.