feat(audio): choose a male or female local voice per language
The installer now fetches one male and one female Piper voice per language (Swedish NST/Lisa, English Ryan/Lessac), with genders confirmed by measuring each voice's pitch rather than guessed from the name. Settings -> Audio gets a voice selector per language with its own Test button that always plays the Piper voice. Male is preselected for both. The integration test now runs its server with an empty home directory, so voices installed on the developer's own machine can't leak into it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -235,6 +235,7 @@ Role:
|
||||
- local neural text-to-speech via Piper (CommonJS, required by `server.js`)
|
||||
|
||||
Owns:
|
||||
- voice catalog in `tts_install.js`: one male + one female voice per language with gender/label (genders measured by pitch, not guessed); `pickVoice` prefers the voice chosen in Settings, then the catalog default
|
||||
- `tts.js`: finds the Piper binary (`RC_PIPER_BIN`, then `<project>/piper/`, then PATH, then `~/.local/bin`) and voices (`RC_PIPER_VOICES_DIR`, `data/piper-voices`, `<project>/piper/voices`, `~/.local/share/piper-voices`); generates one line at a time into a WAV cache under `data/tts/` keyed by voice + speed + text; dedupes identical in-flight requests; background pre-generation with progress
|
||||
- `tts_install.js`: downloads the standalone Piper release for the OS and the `sv_SE-nst-medium` / `en_US-lessac-medium` voices into `<project>/piper/`, skipping anything present; used by both `npm run tts:install` (`scripts/install-piper.js`) and `POST /api/tts/install`
|
||||
- routes in `server.js`: `GET /api/tts/status` (open), `POST /api/tts/speech`, `POST /api/tts/pregenerate`, `POST /api/tts/install` (all PIN-protected once a PIN is set)
|
||||
@@ -2099,6 +2100,8 @@ Practical shape (field names as actually read/written in `src/settings.js` and `
|
||||
speechRate: number,
|
||||
speechPitch: number,
|
||||
ttsEngine: "browser" | "piper", // voice engine; Piper falls back to the browser voice on any failure
|
||||
ttsVoiceSv: string, // chosen Piper voice name per language; "" = catalog default (male)
|
||||
ttsVoiceEn: string,
|
||||
speakerPassingCueEnabled: boolean,
|
||||
speakerLeaderCueEnabled: boolean,
|
||||
speakerFinishCueEnabled: boolean,
|
||||
|
||||
Reference in New Issue
Block a user