Commit graph

191 commits

Author SHA1 Message Date
c161a95eef
pre_process_map: target Provenance (not Providence)
Earlier patch targeted the wrong word; the actual mispronunciation
fox heard was 'Provenance'. Respell as 'Prov-uh-nuns' to hint
syllables + closing /nz/ sound.
2026-06-05 19:18:32 -04:00
5f2f4bfcc8
pre_process_map: Providence -> Prav-uh-dence (fix vowel)
Previous 'Prov-uh-dence' kept the wrong open vowel; native RI
pronunciation is 'prav-uh-dence' with short-a in the first syllable.
2026-06-05 18:40:58 -04:00
221756e501
pre_process_map: track config file in repo; fix Providence pronunciation
F5-TTS mispronounces "Providence" — add hyphenation regex
(Prov-uh-dence). Promote config/pre_process_map.yaml from
gitignored generated file to tracked repo file so the regex
map ships via git pull instead of needing per-host manual edits.
.default.yaml retained as seed for fresh installs.
2026-06-05 18:03:39 -04:00
timehexon
468cd1dfc0 Makefile: fold sox into apt-deps (now a required dep) 2026-06-05 12:33:10 -04:00
timehexon
5e41ab6779 Makefile: add apt-deps + apt-deps-sox targets for venv path 2026-06-05 12:04:24 -04:00
3b58f0c867
F5-TTS: add SSE streaming mode with per-sentence audio + timing
Add `sse: bool` to the request. For tts-1-f5, stream text/event-stream:
one 'sentence' event per sentence the moment it renders, carrying that
sentence's mp3 (base64) plus exact start_ms/end_ms, then a 'done' event
with total duration_ms. Clients begin playback after the first sentence
(no wait for the full clip) and drive a per-sentence highlight off the
timing. A single generation feeds both audio and timing — no double render.
2026-05-29 15:15:32 -04:00
b503c4d5d6
F5-TTS: add opt-in sentence timestamps mode
Add `timestamps: bool` to GenerateSpeechRequest. When set for tts-1-f5,
generate the whole clip up front and return JSON {audio (base64), format,
sample_rate, duration_ms, sentences:[{index,text,start_ms,end_ms}]} instead
of streaming audio. F5 already synthesizes one PCM chunk per sentence, so
each chunk's sample count is its exact duration — no forced aligner needed.
Lets clients highlight each sentence as it is spoken. Non-F5 models with
timestamps=true get a clear 400. Default off preserves streaming behavior.
2026-05-29 12:29:18 -04:00
timehexon
e511d4d105 whisper_refs: fill foxhop ref_text from actual recording 2026-05-25 06:23:18 -04:00
9f15d01569
Add voice 42: foxhop (self-recorded)
Slot 41 intentionally empty (Hitchhiker tribute). Voice is self-recorded by
speaker, AGPL-cleared, registered in voice_registry.json under new
`self-recorded` corpus. ref_text is a placeholder pending `make whisper-refs`
on a GPU host.

  cloned-voices/foxhop.wav            313K  mono 16kHz s16 PCM, ~10s, -3dBFS peak
  voice_registry.json                 +foxhop entry, +self-recorded corpus
  voice_to_speaker.default.yaml       +foxhop block in tts-1-qwen and tts-1-f5
  cloned-voices/voices_metadata.json  +foxhop entry
2026-05-25 06:21:31 -04:00
c5247cd993
whisper_refs: normalize transcripts (sentence-case, strip quote artifacts)
normalize_text() handles three Whisper quirks that produced messy F5
ref_texts:

  1. Lowercase output with no terminal period — capitalize first letter,
     append "." if missing.
  2. Hallucinated "' clusters Whisper inserts when it interprets a
     fragment as quoted dialogue (cora, ivan, atlas, hope had these).
     Strip everywhere; never legitimate English punctuation.
  3. Trailing apostrophe-then-period (.'.) from earlier rounds where a
     closing-quoted line got an extra "." appended — collapse to single
     terminal. Function is now idempotent.

Adds --from-cache flag: skip ASR, re-apply normalize from cached
whisper_refs.json. No GPU needed, useful after tuning the normalizer.
Lazy-imports torch so --from-cache works on any host.

Affects 9 of 40 voices: clara, grace, hazel, iris, felix, hugo
(lowercase fix); cora, ivan, atlas, hope (quote-cluster fix).
2026-05-24 16:02:18 -04:00
72a9553047
CLAUDE.md: replace stale 3090-ai+docker prod docs with 4090+bare-python reality
The prior docs claimed prod = 3090-ai running uncloseai-speech-server-1 via
docker compose. Reality (verified today): prod is bare python on the 4090
(ai.foxhop.net) using the f5-sidecar venv at /mnt/data/f5-sidecar/venv,
fronted by Caddy on 80/443. The container on 3090-ai exited 2 months ago and
docker compose v2 isn't installed there.

Cost of the drift today: one wrong-host deploy attempt that bounced off dead
infrastructure. This rewrites Production Deployment, Quick Production
Commands, Testing, When Things Break, and Common Mistakes to match reality.

Also drops hardcoded tmux window numbers (they shift) — every example now
reads <prod-window> with a reminder to rediscover via tmux-hosts.
2026-05-24 16:02:08 -04:00
4ac192585d F5-TTS: replace LibriSpeech ground-truth labels with real Whisper transcripts
Previous ref_texts were LibriSpeech dataset labels (ALL CAPS, no
punctuation). F5-TTS conditions on ref_text to align reference audio
prosody — commas, periods, casing matter. Now using whisper-large-v3
transcripts of the actual cloned-voices/*.wav files.

Generated via: make whisper-refs (on a GPU host).

Affects all 40 voices in both tts-1-f5 and tts-1-qwen engine blocks.
Sidecar cloned-voices/whisper_refs.json kept for traceability.
2026-05-24 14:47:25 -04:00
e9c978b051
endpoints: filter /v1/models and /v1/voices by engine availability flags 2026-05-24 11:58:35 -04:00
f25731ca08
Add make whisper-refs — re-transcribe cloned-voices/*.wav with whisper-large-v3
F5-TTS cloning quality depends on ref_text matching the prosody of ref_audio
(commas, periods, casing). Previous ref_texts were LibriSpeech ground-truth
labels: ALL CAPS, no punctuation — wrong signal for a flow-matching TTS
conditioned on text. Whisper hears what F5 will hear.

- scripts/whisper_refs.py — transcribe all wavs, rewrite
  voice_to_speaker.default.yaml + cloned-voices/voices_metadata.json
  in place. Also writes cloned-voices/whisper_refs.json sidecar.
- Makefile: whisper-refs target. Idempotent, rerun whenever
  cloned-voices/ changes.

Run on a GPU host (4090/3090). ~30s for 40 short clips on a 4090.
2026-05-24 11:56:15 -04:00
3a76ba6748
CLAUDE.md: refine our 'avoid the' style rule (match unsandbox shard) 2026-05-24 11:56:10 -04:00
831b937fd1
F5-TTS: per-chunk silence trim + fade (port from VoiceClone) + restore per-sentence streaming 2026-05-24 11:39:49 -04:00
timehexon
015bbdfad6 F5-TTS: Whisper-transcribed ref_texts with full punctuation for all 40 cloned voices 2026-05-24 11:34:12 -04:00
960fda4f5c
F5-TTS: sentence-case + period the LibriSpeech ref_texts for cleaner ref-to-gen transition 2026-05-24 11:26:34 -04:00
fc5af2b653
F5-TTS: drop per-sentence split — single infer() call avoids ref-to-gen artifact per chunk 2026-05-24 11:12:57 -04:00
482b17960c
F5-TTS engine consistency sweep (Makefile, startup, README, docs) 2026-05-24 08:24:38 -04:00
2df34f85cc
Add F5-TTS as tts-1-f5 engine (additive, alongside tts-1-qwen) 2026-05-23 13:24:25 -04:00
bfc5260dfc we update gitignore 2026-04-03 14:17:01 -04:00
074cbbd22f style: avoid "the", use "our" — writing style rule + sweep 2026-04-03 14:17:01 -04:00
timehexon
d4d6344326 Replace "AI" with "machine learning" in CLAUDE.md
Machine learning is what we grow. "AI" is forbidden in all
permacomputer discourse, marketing, & documentation.
2026-02-02 19:56:24 +00:00
7e77c3452d Add voices-qwen Makefile target to download cloned voice samples
Runs scripts/download_diverse_voices.py which pulls speaker samples
from LibriSpeech and assigns permanent human names via voice registry.
Works with venv or system python. Also adds Voices section to help.
2026-01-27 17:31:15 -05:00
fox
f58da54fa3 Expand to all 40 test-clean voices with idempotent registry 2026-01-27 15:30:42 -05:00
69d039d1a5 Add datasets and torchcodec to requirements.txt 2026-01-27 15:15:09 -05:00
3f3918fed2 Simplify CLAUDE.md: remove SSH/rsync references, local-only workflow 2026-01-27 13:59:52 -05:00
c3ac2def48 Add idempotent voice registry system for permanent speaker-to-name assignments
- voice_registry.json: append-only registry with 50 name pools per gender,
  locked speaker assignments, and multi-corpus support
- Rewrite download script to be registry-driven: loads registry, assigns
  names deterministically (sorted by speaker ID), never changes existing
  assignments
- Update docs/VOICES.md with registry system documentation
- Support --registry and --corpora CLI flags for multi-corpus downloads
2026-01-27 13:59:39 -05:00
fox
af5c81928d Regenerate voices with upstream-verified genders from SPEAKERS.TXT 2026-01-27 13:22:26 -05:00
35b083ed34 Fetch speaker genders from upstream LibriSpeech SPEAKERS.TXT 2026-01-27 13:17:52 -05:00
b77af6d603 Fix voice gender assignments - verified against LibriSpeech SPEAKERS.TXT 2026-01-27 13:13:07 -05:00
c56b8cb24e Simplify Makefile to run locally, remove all remote SSH/rsync
Remove REMOTE_HOST, REMOTE_USER, REMOTE_PATH, vars.sh loading.
All docker commands use sudo locally. Tests hit localhost:8000.
Delete old non-gendered voice WAV files (alloy, echo, fable, etc).
2026-01-27 12:51:08 -05:00
ebfa0319d1 Replace voices with 21 distinct gendered speakers from LibriSpeech
11 female (aria, clara, elena, grace, hazel, iris, luna, maya, ruby, sage, sofia)
10 male (atlas, caleb, felix, hugo, jasper, kai, leo, marcus, owen, theo)
Each voice is a unique LibriSpeech test-clean speaker for voice cloning diversity.
2026-01-27 12:41:37 -05:00
cd60e31aa2 Use gendered voice names: 11 female + 10 male = 21 distinct voices 2026-01-27 12:07:31 -05:00
4c5b42c062 Mount cloned-voices directory in container 2026-01-27 11:56:17 -05:00
648281cdb6 Update diverse voices script with correct voice names 2026-01-27 11:53:33 -05:00
aa8af56835 Fix remote paths in CLAUDE.md, add tmux-hosts discovery 2026-01-27 09:32:27 -05:00
16b281bab4 Add webm response format (opus in webm container)
Firefox MediaSource API supports audio/webm;codecs=opus but not
audio/ogg. Adding webm format lets Firefox clients use true
streaming playback via MediaSource instead of full buffering.
2026-01-27 09:28:38 -05:00
8f7f1318a1 Split on every sentence for streaming (no combining) 2026-01-26 19:52:41 -05:00
0a0d023517 Fix sentence splitter to split on every sentence boundary
Previous version accumulated sentences until 500 chars, defeating
the purpose of streaming. Now splits on every sentence, only
combining very short sentences (<50 chars) with the next.
2026-01-26 19:41:44 -05:00
802eaf2b29 Add sentence-by-sentence streaming for Qwen TTS
Split text into sentences and stream each as it's generated,
so first audio arrives much faster for long text.
2026-01-26 19:32:51 -05:00
a148088cb0 Fix Qwen TTS deadlock, reduce workers to 1 for GPU
- Fix subprocess deadlock in Qwen TTS by using threading for stdin write
  (prevents pipe buffer deadlock on large audio output)
- Set WORKERS=1 for GPU models to avoid VRAM duplication
  (4 workers × 3GB model = OOM, 1 worker works fine)
- Update CLAUDE.md: use git push/pull instead of rsync for deployment
2026-01-26 19:14:19 -05:00
cac40d75d3 Set default workers to 4 to prevent server lockup 2026-01-26 18:23:51 -05:00
5e5e7936f1 Add 20 cloned voice samples for Qwen3-TTS
LJ Speech samples (public domain) for voice cloning:
- Standard: alloy, echo, fable, onyx, nova, shimmer
- Extended: amber, breeze, coral, dawn, ember, frost,
            glow, haze, ivy, jade, kite, lark, mist, nectar
2026-01-26 17:44:03 -05:00
02b4e7aaf7 Add 20 diverse voice samples for Qwen3-TTS
Standard voices: alloy, echo, fable, onyx, nova, shimmer
Extended voices: amber, breeze, coral, dawn, ember, frost,
                 glow, haze, ivy, jade, kite, lark, mist, nectar

Source: LJ Speech Dataset (public domain)
2026-01-26 16:50:54 -05:00
6b4f66dcf5 Use LJ Speech sample for voice cloning (Alibaba Cloud URL blocked) 2026-01-26 16:28:39 -05:00
ad6a4d4990 Fix docker-compose.yml for older docker-compose versions 2026-01-26 14:25:06 -05:00
0159f1f216 Add configurable WORKERS env var, default to 1 for GPU models 2026-01-26 13:16:44 -05:00
f299b43f1a Fix qwen-tts version constraint (0.0.5 is latest) 2026-01-26 11:14:26 -05:00