Repository navigation
feat(voices): voice picker with audio preview in the generate box - #1200
Open
joshfrenette22-stack wants to merge 2 commits into
Open
joshfrenette22-stack wants to merge 2 commits into
joshfrenette22-stack wants to merge 2 commits into
Conversation
The model download only fetches the Kokoro weights; each voice is a separate file that KPipeline pulls from the Hub the first time the voice is used. huggingface_hub keeps one HTTP session per thread, and a session built inside an offline window (opened while loading a cached model) keeps its offline adapter. A thread reused for generation then failed with OfflineModeIsEnabled for every voice that had not been used before. Check the voice file is cached before generating, and if not, fetch it inside a network-allowed window with fresh sessions. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Add a searchable voice picker to the generate box that lists your voices
and every built-in Kokoro and Qwen CustomVoice voice, each with a play
button that speaks a short sample phrase before you generate. Choosing a
built-in voice adds it as a preset profile (generation is always tied to a
profile) and selects it. The Create Voice dialog's built-in voice grid gets
the same preview buttons.
Backend:
- GET /profiles/presets/{engine}/{voice_id}/preview renders the sample
phrase in the voice's own language and caches it on disk.
- GET /profiles/{profile_id}/preview does the same for any profile, so
cloned and designed voices can be heard too.
- A missing model returns a 409 that points at the Models tab.
The picker replaces the plain voice dropdown that only the Stories tab had.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A searchable voice picker in the generate box, with a ▶ button on every voice that plays a short sample phrase before you generate. Built-in Kokoro and Qwen CustomVoice voices are listed alongside your own voices, so you can audition them without leaving the generate box.
Also fixes a Kokoro bug that made every voice you hadn't used before fail on generation (second commit below).
Why
Right now the generate box has no way to choose a voice (only the Stories tab had a plain dropdown), and the Create Voice dialog's built-in voice grid can't be auditioned. You pick a name from a list of 54 Kokoro voices blind, create a profile, and only then hear it.
How it works
Picker (
VoicePicker.tsx)Selectthat only the Stories tab had, so theshowVoiceSelectorprop is gone.Preview playback (
useVoicePreview,VoicePreviewButton)Backend
GET /profiles/presets/{engine}/{voice_id}/preview: renders a short phrase in the voice's own language (11 phrases; unknown languages fall back to English) with a fixed seed and caches the WAV under the cache dir. Cache file names are digests, so a voice id never shapes a path.GET /profiles/{profile_id}/preview: same for any profile. Built-in profiles share the preset cache; cloned and designed voices render on demand (not disk-cached, since editing the profile changes the sound)./generate.Kokoro fix (separate commit)
fix(kokoro): the model download only fetches the weights; each voice is a separate file thatKPipelinepulls from the Hub on first use.huggingface_hubkeeps one HTTP session per thread, and a session built during an offline window (opened while loading a cached model) keeps its offline adapter. A thread reused for generation then fails withOfflineModeIsEnabledfor every voice that hasn't been used before. This reproduced on a plain generation, not just previews. The fix checks the voice file is cached and, if not, fetches it inside a network-allowed window with fresh sessions.Testing
tscpasses forappandweb. Biome reports nothing in the new files (remaining findings are in lines I didn't touch).af_bella,bm_george) rendered and downloaded the voice on demand. Transcribing the clips with the app's Whisper returned the exact phrase.Not covered / notes
backend/tests/test_offline_guard.py::test_nesting_opposite_mode_on_same_thread_raises_instead_of_deadlockingfails on currentmaintoo, independent of this change.🤖 Generated with Claude Code