Fish-Speech emotion tags were silently ignored on non-English books: per-line
emotions are LLM-generated in the book's own language, but Fish-Speech only
recognizes English [tag] markers, and a double-tagging bug was stacking a
broken server-derived tag on top of the client's own. Added a DE->EN
translation table and removed the double-tagging. Also wires the existing
book-profile context and race_species field into character portrait prompts
(previously only used for voice design), adds a recast-until-threshold loop
for casting, and adds backend-aware emotion quick-picks to Read Aloud, Try a
Voice, and Conversation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Voice consistency:
- Read back each voice's pinned seed (Seed Finder / Batch Seeds) on every
generation. The seed was saved to voice metadata but only ever read by the
Seed Finder's own benchmark path, so all per-voice seed pinning was inert.
- Stop coercing the "voice_design_playback" stability profile back to
"voice_clone". The pseudo-backend key isn't a real routing target, so the
backend-name normalizer silently rewrote it — reintroducing the hardcoded
seed:0 that profile exists to avoid, overriding every per-voice pin.
- Apply the accent clause on every line, not just at voice-creation time,
and reorder the instruct so emotion leads and accent trails (Qwen3-TTS
doesn't reliably follow multiple conflicting instructions).
- Pass an explicit language to Voice Design instead of leaving it on "Auto".
Audio effects:
- Add a limiter after compressor makeup gain. Makeup gain pushed peaks to
~1.9, and the final hard clip turned that into broadband distortion that
swamped the rest of the chain.
- Cascade highpass/lowpass 3 stages each (~18 dB/octave). Single-pole
filters were too gentle to band-limit speech audibly.
- Add a Bandpass control and wire it into the Telephone/Radio presets —
compression alone never sounded like a phone; band-limiting is the
defining trait.
Persona / Try It Out:
- Disable "Apply character persona" with an explanatory tooltip when the
voice has no persona saved, and error clearly server-side instead of
silently no-op'ing. Persona is typed manually per voice, never auto-filled.
- Stop dropping applyPersona in the chunked generation path (>200 chars).
- Populate the Voice Design dropdown from the user's own library rather than
filtering the engine's discovery list, which never contains custom voices.
Navigation and library:
- Use pushState instead of replaceState so browser Back/Forward step through
in-app navigation instead of leaving the app entirely.
- Show real dialogue line counts in the character sidebar instead of the
capped reference-quote count (which showed a misleading uniform "12").
Also fixes a crash in /api/transcribe-bytes that referenced an undefined
source_id in its cleanup path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Introduces the new Studio section (Source -> Characters -> Voices ->
Perform & Export) that reuses the existing Read Aloud/Library/Script
Rehearsal code via DOM reparenting instead of duplicating it, and rolls up
a long tail of bugs found while producing a real audiobook through it:
umlaut-eating name sanitizers, a voice picker that mispositioned itself and
capped results at 60, PDF pagination silently breaking on trimmed \f
markers, a race letting stale audio keep playing after a new line was
clicked, an alias-overlap bug that could silently redirect a voice/image
save onto the wrong character, voice design failing outright during brief
TTS backend restarts instead of retrying, sparse cast entries defaulting to
English/wrong gender, and a reassigned voice never reaching an already-open
Stage session or invalidating its cached audio. Also adds a persistent
per-line audio cache, audiobook export browsing/download, and an inline
voice-design prompt editor. Full details in CHANGELOG.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Add a 6-stage pipeline stepper (Source -> Cast Audiobook -> Cast Characters
-> Script Rehearser -> Generate MP3s -> Audiobook) with direct, non-destructive
jumps between stages and a prominent guided-tour look
- Split PDF import into an explicit "load" then "Extract Text" step, with
in-browser OCR (Tesseract.js, vendored) to recover chapter headlines baked
into a PDF as images instead of real text
- Fix casting feed silently merging pages after leaving/returning: segments
now carry their own page number instead of re-guessing it from text
- Fix excessive "Unknown" speaker attribution: restore the attribution LLM's
output token budget, which had been cut roughly in half and was truncating
dialogue-dense passages
- Fix Theater Play library cards failing to open (dead pre-migration
IndexedDB API calls, missing section navigation)
- Fix bulk "Set tag" wiping a voice's existing tags instead of adding to them
- Start merging Casting's feed with Script Rehearser's Stage UI: collapsible
character sidebar, shared "paper" page styling, inline text editing
- Fix a performance regression from that merge (per-row listeners on every
redraw) by moving to event delegation
- Various layout/clutter fixes: hide reader chrome until a document is
loaded, collapse secondary settings by default, fix overlapping toolbar
icons, fix duplicate "opening" notifications
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Exposes the `speed` parameter (0.5–2.0) on the TTS `/v1/audio/speech`
request so audio is generated at the target tempo natively via the
faster-qwen3-tts backend rather than post-processing.
- Backend: `/api/tts-preview` now extracts and forwards a `speed`
override (clamped 0.1–4.0) through the same extra-params mechanism
already used for seed/temperature; backends that reject it fall back
cleanly via `_post_tts_with_fallback`.
- Try it out: "Native Speed" number input (0.5–2, step 0.05) added to
the text card; value persists in localStorage per browser; passed as
`extra` through `createTtsAudioSource` and `generateChunkedTts`.
- Read aloud: "Native Speed" control added to the generation controls
row alongside seed/temperature; included in `readerGenParams()` and
saved/restored with library documents (each book tracks its own speed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a collapsible "🎲 Seed Finder" panel to the voice inspector pane.
Select a voice, expand the panel, set a seed range (default 1–15), and
click Run to generate audio samples with different seeds.
Each result row has Play and "Use this seed" buttons. "Use this seed"
saves the chosen seed to the faster-qwen3-tts voices.json via the new
/api/tts-voice-seed proxy endpoint (which calls /voice-seed on the TTS
server). The saved row gets a ✓ marker.
Test sentence auto-selects DE/EN mixed or EN-only based on voice name.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- voice_clone and streaming now return active library voices instead of
probing upstream /v1/models (which only exposed 8 model entries)
- Accept POST on /v1/audio/voices for clients that probe with POST
- Fall back to first active voice when voice field missing in /v1/audio/speech
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>