Commit Graph

50 Commits

Author SHA1 Message Date
30bac15b6e Open toolbar flyout menus downwards when there is room (v1.20.18)
The Identify/Cast flyouts were hard-anchored to open above their trigger,
which suited the casting panel's bottom footer but clipped them off the top of
the screen in Studio, where the same toolbar sits near the top — the first two
entries were unreachable. They now pick the side with space, prefer opening
downwards, stay clamped inside the viewport and scroll if taller than it.

Also reorders the Identify menu to the sequence the passes should run in, with
the one-click Auto-repair cast first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 08:47:17 +02:00
4c686165b3 Add targeted dialogue-repair pass and auto-repair chain, fix rollback on stopped runs (v1.20.16)
Spoken lines that PDF extraction typed as narration were invisible to
"Identify unknown characters" (it only scans type==='dialogue'), so no number
of re-runs could fix them, while the pass that could re-sent all ~1000
narration segments to the LLM. Adds a detector that scores narration for
direct-speech signals and re-checks only those: 36 candidates instead of 1036
on a real novel. Adds "Auto-repair cast" to chain the passes in the right
order automatically after casting.

Also fixes a rollback gap where stopping a run skipped the safety net that
undoes a pass which increased Unknown speakers (confirmed live: 80 -> 159
with no warning), corrects an attribution rule that taught the model the
listener is the speaker, and stops the threshold loop from re-verifying every
narration segment each round.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 08:40:38 +02:00
5fecbf06d4 Fix Fish-Speech emotion tags, wire book context into portraits, add emotion controls app-wide (v1.20.5)
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>
2026-08-11 18:02:41 +02:00
a62dd0bac1 Fix voice stability, audio effects, and character/voice pipeline bugs
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>
2026-07-29 15:33:24 +02:00
ea50267c30 Add unified Studio casting workflow and fix voice/casting pipeline bugs
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>
2026-07-26 02:03:56 +02:00
588ba3fcb8 Refine character sheets and live output UI 2026-07-09 19:47:16 +02:00
8f3fcbae04 Release v1.14.19 2026-07-09 14:11:40 +02:00
17716ac740 Stop retried/recast audiobook casts from creating duplicate scripts (v1.14.18)
A fresh (non-resume) cast unconditionally nulled _audiobook.rehId even
when retrying or recasting a book that already had a linked Rehearsal
Library record from a prior attempt — silently orphaning it and
creating a new one on the next save. Now only nulled for a genuinely
first-ever cast; retries/recasts overwrite the existing record.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 12:23:55 +02:00
b96968ac5d Add mid-quote-dash and voice-announcement rules to casting attribution prompt (v1.14.15)
Two gaps observed in real casting output:
1. A mid-quote " - " (em-dash pause) was being read as the end of the
   quotation, handing the rest of the line to a wrong/new speaker.
2. Narration naming whose voice is about to speak (e.g. "Marcians
   Stimme wirkte nicht mehr so fest") wasn't being used to resolve the
   following unattributed line away from 'Unknown'.

Added as rules 11/12 to the client-side AB_DEFAULT_PROMPT (the prompt
actually sent to the LLM) and to normalizeCastingPrompt()'s migration
so already-saved custom prompts pick them up automatically, same
mechanism as the earlier Doppelpunkt-Regel upgrade. Also added
equivalent rules to the server-side fallback prompt in
routes/conversation.py for completeness, though the client-sent prompt
is what's actually used in normal operation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 02:51:46 +02:00
83808a22e1 Fix assign popup being closed before a name-elsewhere click could fill it (v1.14.14)
A document-level "click outside closes the popup" handler only exempted
clicks on the paragraph's speaker label, not clicks anywhere else in the
passage text. Since mousedown fires before click, this closed the popup
(clearing assignModeRow) before the v1.14.13 name-click logic ever ran,
making "click a name elsewhere to feed the open popup" silently do
nothing. Passage-text clicks/drags no longer auto-close the popup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 02:44:10 +02:00
cd20df315d Stop click/drag-on-a-name from reassigning the wrong paragraph (v1.14.13)
The intended flow is: click the broken paragraph's speaker label to open
"Assign to", then supply the name (type, click it anywhere in the text,
or drag-select it). But clicking or drag-selecting a name with no popup
open yet used to open/target a popup for whichever paragraph that name
lived in, silently reassigning THAT paragraph instead of the one the
user meant to fix. Both paths now require an already-open popup before
they do anything — a paragraph is only ever selected via its own
speaker label (or the existing double-click fast-assign shortcut).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 02:33:56 +02:00
3db3616830 Show character avatar images in casting pickers (v1.14.12)
The Characters Found sidebar, the "Assign to" popup's character list,
and the "merge with an already-found character" list now show each
character's saved portrait when one exists (same source as the profile
detail panel), falling back to the existing colour-keyed initial-letter
dot otherwise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 02:09:20 +02:00
2133fe25c7 Stop assign popup from retargeting when reusing a name from another paragraph (v1.14.11)
Clicking a name inside a paragraph's text always retargeted the "Assign
to" popup (and its highlight) to that paragraph, even when the popup was
already open for a different one. That made it look like the wrong
paragraph was being reassigned when the user just wanted to reuse a name
they saw elsewhere. Now, while a popup is open, clicking a name outside
its target paragraph only fills the search box.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 02:02:31 +02:00
f139367f74 Make casting live-view panels resizable, fix collapse chevron direction (v1.14.10)
Passage/Thinking boxes in the audiobook casting live view can now be
resized vertically. Also fixed the character-list collapse button's
chevron pointing opposite to the direction the panel edge actually moves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 01:50:36 +02:00
8d5050bb80 Raise audiobook casting timeouts to 10min/5min for large models (v1.14.8)
Was 6min/3min. 122B+ models can take longer than that just to produce
a first token; 10min also happens to match the server-side cap
(_request_timeout_seconds), so this is the max without raising that too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:09:04 +02:00
c969150095 Fix triple-duplicated passage in audiobook casting's live LLM view (v1.14.7)
The "LLM Reading…" split view showed the same passage text three times
(reader pane, Passage column, and a full-width block toggled by the
chevron that duplicated the Passage column). Removed the redundant
full-width block, repurposed the chevron to show/hide the two-column
view itself, and swapped the columns to Passage (left) / Thinking (right).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 23:00:16 +02:00
6a9c827ec9 Scope Recast-selected to only the relevant passages (v1.13.9)
Recasting one character out of a 149-passage book was reading the
entire text every time, exactly as flagged: "you only need to read a
couple of paragraphs before and after his name." csForReaderSelective
now matches the picked character's name + known aliases against the
book's chunks, keeps one chunk of context on either side for
pronoun/"he" resolution, and only extracts from those - falling back
to the full book only if nothing matched at all (e.g. a name typo).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 15:10:20 +02:00
07eadeff1e Fix Recast-selected running on the full roster, improve dropdown positioning (v1.13.7)
csForReaderSelective passed the ENTIRE roster to csGenerate as the
target list, so the "N cast characters queued" progress dialog showed
every character regardless of what was actually checked in the picker
- only the final save step was correctly filtered, making the whole
run look like it ignored the selection. Now only the picked name(s)
go in as the target roster.

Also fixed the "Recast options" dropdown opening off-screen: its
anchor sits in the bottom action bar, so opening downward (the
default) routinely pushed it past the viewport edge. Opens upward
when there isn't enough room below, with more prominent styling.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 14:35:27 +02:00
ebd18bcc14 Fix merge-freeze with chunked redraw, add sidebar search/sort (v1.13.5)
Merging two characters could block the main thread long enough to
trigger the browser's own "Page Unresponsive" dialog - the merge
itself is a fast array loop, but redrawing the whole feed afterward
(thousands of DOM rows, each running highlightText's regex pass) was
one long synchronous chunk. A plain spinner overlay can't fix that,
since it freezes right along with everything else in the same JS
turn. Split _abMergeCharacters into a fast relabel step plus a new
_abRedrawSegmentsChunked that rebuilds the feed across animation
frames, driving a real progress bar in the busy overlay instead of a
static "please wait".

Also added search + sort (line count / alphabetical) to the Casting
sidebar's character list, matching the Library's character list
controls.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 12:12:36 +02:00
139cb6b85b Fix table-view column misalignment for real, add character-merge via alias popup (v1.13.4)
The earlier table-view fix (display:table-row on <tr>) wasn't the
whole story: display:flex directly on a <td> (Stimme, Tags columns)
also broke its table-cell participation in Chromium, rendering that
cell stacked at the PREVIOUS column's x-position regardless of
table-layout mode - confirmed via direct DOM/rect inspection, not
guesswork. Moved flex layout to inner wrapper divs and switched to
table-layout:fixed with an explicit colgroup so column widths are
never re-negotiated by content again.

Also added actual character merging to the "also known as" alias
popup: picking an existing roster entry (e.g. "Schmied" from Darag's
popup, when the LLM split one person into two roster names) reassigns
every one of its segments to the character you opened the popup from,
with undo support - not just a linked library alias that left the
live cast still showing both as separate people.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:58:42 +02:00
cb76a2f237 Fix short quoted-line drag opening Assign popup instead of Split (v1.13.3)
Any selection under 40 chars was treated as "assign this as a
character name," including short quoted lines like "»Henker«." that
the user clearly meant to split into their own Unknown-speaker
segment - guillemets/quotes are never part of a name. Selections
starting with a quote mark now skip the assign-popup hijack and fall
through to the already-visible "Split text to Unknown Speaker" button.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:32:06 +02:00
204bc3a6c6 Add View Characters + recast-all/selected once a book is already cast (v1.13.1)
"Cast Characters" always blindly regenerated the whole cast from
scratch, even for a book already fully cast - no way to just look at
what's there or touch up a handful of characters without redoing
everyone. Once clGetAllByTagOrBook finds existing characters for this
book, the button becomes a split control: View Characters (jump to the
Library overview) plus a dropdown for Recast all or Recast selected...
(checkbox picker that re-scans the book but only saves updates for the
characters checked).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 01:03:30 +02:00
3fd4f7d052 Fix UTF-8 mojibake, thinking-pane duplication, stale popup closures (v1.12.97)
The streaming attribution endpoint decoded the LLM's SSE response with
requests' guessed encoding (Latin-1 fallback when no charset is declared),
mangling every German umlaut. Forced UTF-8 explicitly.

The "LLM Thinking" pane duplicated the passage text for models that
ignore the <think> instruction and stream straight into JSON - it now
only shows real reasoning when present, and otherwise labels raw output
honestly instead of passing it off as thinking.

Also fixed three UI bugs found while testing a live multi-hour cast:
- A-/A+ font buttons had no effect (a hardcoded font-size on .ab-cv-row
  always overrode the CSS variable they set).
- Typing a name + Enter in the "Assign to" popup (and drag-to-assign,
  which reuses it) silently did nothing after the first cast/recast run
  in a session - the popup is a page-lifetime singleton but its input
  handlers closed over the first run's now-stale assignName/closePopup.
  Every popup open now repoints them at the current run.
- "Split text to Unknown Speaker" split at the wrong spot when the
  selected phrase repeated earlier in the same paragraph (indexOf found
  the first occurrence, not the dragged one). Now uses the exact DOM
  range offset instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 20:18:41 +02:00
6bc98e2b62 Fix ASGI middleware crash and stream/blocking lock race (v1.12.96)
The static-asset caching middleware used BaseHTTPMiddleware, which has a
known Starlette bug: a client disconnecting mid-StreamingResponse (the new
live-attribution SSE stream hitting its idle timeout) raced its internal
task group and raised "RuntimeError: No response returned", crashing that
request. Rewritten as plain ASGI middleware that only touches headers via
the raw send callable, removing the race.

Also found the real cause of the casting timeouts/405s: the streaming
attribution endpoint had its own lock instead of sharing the one the
blocking endpoint already used to serialize on the LLM's single slot -
letting a stream call and its own blocking fallback fire concurrently,
exactly the ghost-request pile-up that lock was built to prevent. Unified
onto one lock and added server-side logging for stream failures.

The "LLM Thinking" pane now shows the model's actual <think> reasoning
instead of the in-progress JSON answer echoed back at the user.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 18:08:54 +02:00
3503f5bda6 Live LLM-thinking stream, fix resolver garbage names, safer rules (v1.12.95)
The LLM Reading card splits into thinking-stream (left) and passage
(right), fed by a new SSE endpoint that shares prompt-building and
parsing with the blocking one and falls back to it on any stream
failure (inactivity timeout, not overall). The deterministic resolver
no longer invents speakers from scenery nouns (PLATZ/GESICHTER/
KLEINIGKEIT) — person-noun whitelist plus a clause-subject pattern —
and gains the impersonal post-quote formula and strict two-person
alternation with colon/page/window guards. All reported failure cases
verified against the exact book sentences.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 10:50:34 +02:00
d1969b7609 Fix quality-run roster display, blank API errors, resolver-first (v1.12.94)
The recast/quality view's sidebar rebuilt its roster from only the
lines being checked, appearing to wipe every named character (the cast
itself was safe: named lines are never recast targets and increases in
Unknowns already roll back). The sidebar now seeds from the full cast
and refreshes during the run. Error notes fall back to the HTTP status
(statusText is empty on HTTP/2). The deterministic grammar resolver
runs before any LLM call in quality runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 23:17:59 +02:00
42a45c43b6 Resolve Unknown speakers deterministically after each passage (v1.12.93)
The LLM left ~44% of dialogue Unknown even with all deduction rules in
its prompt, so the mechanical ones now run in code per passage: colon
rule (with a non-agent-noun stoplist), post-quote inquit, and the "who
had spoken" pattern. Fills only Unknowns, never overrides the LLM.
Tested against the exact reported failure cases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 22:40:14 +02:00
3c3c209d3a Guarantee attribution rules server-side, fix highlight corruption (v1.12.92)
The saved casting prompt was the 2nd-quality verification prompt, so
first-pass attribution ran with the wrong job description and none of
the deduction rules — and the client-side prompt migration had no
anchor to upgrade. The server now appends the rules to any prompt
lacking them, and the saved prompt was reset to the default (backed up
to config/audiobook_prompt.backup.txt). Also: single-pass combined name
regex (a shorter alias could match inside a longer name's data-name
attribute and leak raw style="..." into the feed), stopword filter so a
comma-split alias like "Die, die den Vampir verließ" can't underline
every article, heading-like narration renders bold/centered, and A-/A+
font controls in the casting toolbar sharing the Rehearser Stage scale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 18:19:01 +02:00
e02ca4d703 Fix casting-feed freeze, zip cast export, character generation prompts (v1.12.90)
The per-word <span> wrapping behind "click any word to assign" created
~100k DOM nodes at book scale and froze the tab on every feed redraw;
replaced with native caretRangeFromPoint word detection plus a single
reused hover overlay — same UX, zero extra DOM. Export button gained a
2s re-entry guard (queued clicks during a freeze fired as a download
burst) and now delivers one zip: the cast script in Markdown plus a
sheet per character. Character detail view gains a Generation Prompts
section — four fold-out copy boxes (Voice Design, Character Image,
SillyTavern card, Concept Art sheet) filled by one LLM call over the
full profile via the new /api/character-generate-prompts endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 12:48:00 +02:00
637aeb3a2c Sharpen speaker attribution rules and auto-detect book language (v1.12.86)
The casting prompt now teaches the deduction patterns behind most false
Unknown/Narrator assignments: colon-introduced quotes, post-quote inquit
attribution, pronoun resolution to the last-named matching-gender
character, addressee rule, strict two-person ping-pong, and role names
(Ork, Nachbar) as valid speakers. Saved prompts upgrade in place; the
2nd Quality Run prompt gets the same toolkit. The attribution language
hint falls back to detecting the book's language from its text instead
of relying on a usually-empty dropdown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 02:36:28 +02:00
cfe15a72f5 Optimize and clean up the pipeline merge (v1.12.85)
Speed: OCR renders only the heading band (was full page at 2.5x),
Tesseract worker freed after extraction, name-underline index cached
instead of rebuilt per segment, constant regexes hoisted, old drafts
migrate segment page numbers once at load (single-path feed renderer).

Quality: global [hidden]{display:none!important} ends the empty-box bug
class; racy deferred cast-restore + _readerSuppressCastRestore flag
replaced by a synchronous, caller-wins restore; card collapse defaults
move to data-collapse-default markup; duplicated join/colour/alias/LLM-
target helpers now delegate to their canonical implementations; dead
reader state removed; stepper hide-guard fixed for the merged Source key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 21:52:33 +02:00
9d80ec27e7 Merge Reader/Casting/Rehearser pipeline into one guided workflow (v1.12.84)
- 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>
2026-07-03 17:45:38 +02:00
34e4bb99e1 Keep audiobook casting moving on slow LLMs 2026-06-30 22:06:39 +02:00
32a3c838fe Fix audiobook stop casting state 2026-06-30 21:04:53 +02:00
586dc3dc3f release: v1.12.52 2026-06-30 13:53:08 +02:00
04dee87710 feat: auto-save audiobook to Rehearser IndexedDB + Edit in Rehearser (v1.12.6)
- Casting completion auto-saves to Rehearser IndexedDB (same format
  as script rehearsals). Manual speaker corrections in the cast view
  debounce-save after 1.5s.
- rehId tracked across session (stored in localStorage draft) so
  updates go to the same record instead of creating duplicates.
- Voice assignments made in Script Rehearser survive an auto-update:
  only script text and emotions are overwritten; voice/instruct/soul
  are merged from the existing record.
- "Edit in Rehearser" button in the completed cast footer opens the
  saved record directly in Script Rehearser, ready for voice casting.
- Expose rehDbGetById + rehLoadRecord globally from rehearser.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:21:21 +02:00
9c975a651c feat: autosave casting progress to localStorage (v1.12.5)
Saves accumulated segments after every chunk. On page refresh or crash,
reopening Cast as Audiobook for the same document restores the session
automatically — shows a banner with completion % and save age.

Manual speaker reassignments in the cast view are also autosaved so
review corrections survive a refresh. Draft clears when the script is
saved to Script Rehearsals or a fresh Recast All is triggered.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:13:36 +02:00
87cac1f5f5 feat: expandable ⋯ dividers in Recast Unknown (v1.12.4)
Click any gap divider to reveal the hidden segments between two Unknown
passages inline — shows speaker + text so context is clear before
making an assignment. Displays line count ("42 lines hidden — click
to expand") so users know what they are opening.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 19:49:04 +02:00
7a75d1ecf4 feat: casting badge, navigate-away/back, live character count (v1.12.3)
- Pulsing blue dot on the Read Aloud nav item while casting is active
- Navigating away and returning restores the cast panel automatically
- Reassigning a segment's speaker decrements the old count so the
  Characters Found panel stays in sync; speakers at 0 disappear

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 19:45:41 +02:00
4f795e820c feat: noise gate, PDF search, sidebar active highlight, stats collapse, tooltip + dialogue fixes
- Conversation: adjustable noise gate slider (RMS threshold + 300 ms
  minimum burst duration) prevents short noise spikes from triggering
  STT; level meter shows gate position as a blue marker
- Conversation stats panel now collapsible (chevron button) to free
  chat width; floating expand button restores it; state persists
- Read Aloud: text search input in PDF toolbar (Enter = next hit,
  Shift+Enter = previous, Esc = clear)
- Sidebar: tooltip now works for all item types including sub-items
  that had no .nav-label span (text extracted by stripping icon/badge)
- Sidebar active section indicator added (.nav-tree-item.active was
  previously unstyled — active section now has bg + right accent bar)
- Casting audiobook: prompt instructs LLM to handle ?« / !« endings
  and unclosed » at passage end as dialogue; deterministic fallback
  also handles unclosed opening quote

Bumps to v1.12.2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 16:48:48 +02:00
a4128788d6 feat: slim icon-rail sidebar, collapsible panels, Read Aloud fit-height (v1.12.0)
- Sidebar collapses to a 56px icon rail; hovering flies the full menu out as
  an overlay (icons + titles/nested items). Language picker moved to Settings.
- Unify settings collapsibles to the app's standard card-collapse style:
  Conversation, Read Aloud (drag-&-drop now inside), Try It Out, Casting panel.
- Read Aloud: reordered (settings → toolbar → document → transport/synth) and
  the document fits the viewport height so controls below stay visible; remove
  the redundant My Books card (lives in Library → Books).
- Conversation: stacked full-width config, fills viewport height; fix
  intermittent webm decode in hands-free mode (recorder restarts cleanly,
  in-browser WAV encode); barge-in via Live agent.
- Fix casting feed overflow that pushed the sidebar off-screen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 15:47:52 +02:00
6b52a346d5 fix: stop casting feed from hijacking scroll and deleting visible rows
- Auto-scroll to bottom is now gated on the user being within 80px of
  the bottom. Scrolling up to review or edit a line freezes the feed
  in place — new rows are still added, but the viewport doesn't move.
- Row-trimming is likewise suppressed while the user is scrolled up,
  so old lines stay visible as long as they're being read/edited.
  Trim limit raised from 80 → 600 rows so almost nothing is evicted.
- A floating "↓ Live" pill button appears at the bottom of the feed
  whenever the user has scrolled up. Clicking it returns to the live
  bottom and re-enables auto-scroll.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:47:25 +02:00
a978e39e49 feat: expandable LLM panel + page markers in casting feed; fix page numbering
Casting view improvements:
- "LLM Reading…" row now shows a preview of the passage being processed.
  A chevron button expands it to a full scrollable view of the passage
  text (up to 260px), so you can follow what the LLM is reading live.
- Page-break dividers ("Page N") appear in the casting feed whenever the
  source PDF page changes, giving a real-time view of page boundaries.

Bug fix:
- Page numbers in the Rehearser script were 0-indexed (PDF-internal) so
  the first page break showed "Page 1" for what was PDF page 2, etc.
  Now always emits 1-indexed page numbers (\f${page+1}).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:23:19 +02:00
868ce6a7bd feat: show page numbers on page-break markers in Script Rehearser
When a PDF audiobook is cast and saved to the Rehearser, page breaks now
carry the source PDF page number. In the Stage view each divider renders
as "— Page N —" instead of the generic "— Page break —".

Implementation:
- audiobook.js: `audiobookBuildScript()` encodes the page number in the
  form-feed line (\fN instead of bare \f) at each page boundary.
- rehearser-parse.js: `parseScript()` now matches `line.startsWith('\f')`
  and extracts the trailing page number into `line.page`.
- rehearser.js: `buildScriptPage()` renders "— Page N —" when `line.page`
  is set; `toScript()` round-trips the number back (\fN) so it survives
  save/reload; `importPDFScript()` also encodes page numbers (\f<pageIdx+1>)
  when importing screenplay PDFs directly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 22:09:32 +02:00
65e2784d2d Preserve audiobook pagination when saving to Rehearser (v1.9.2)
audiobookScopeText now records PDF page boundaries as character offsets in the
scope text; audiobookBuildScript realigns each segment against the source and
emits \f page-break markers at the nearest boundary. Saved/opened cast scripts
keep the book's pagination instead of collapsing to one flow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 21:49:51 +02:00
e62abbcd1d Fix character-sheet LLM URL + audiobook preview; Stage font controls (v1.9.1)
- Character sheets: stop sending the dead localhost:11434 default; fall back to
  the server's configured llm_url so extraction uses the same working LLM.
- Audiobook casting: hoist highlightText to module scope so the "Review & cast"
  manual-correction preview renders its segment rows again.
- Stage: unify narrator/dialog font size, add A-/A+ play text-size control
  (scales A4 + paginated views), and make the cast chip list collapsible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 21:44:30 +02:00
495550bf6a Release v1.9.0 — Character Library + richer character sheets
Add a persistent, book-scoped Character Library (new Characters section,
IndexedDB) that auto-fills from Character-sheet analysis with editable cards.
Enrich extraction with six narrative fields (backstory, relationships,
motivation, fears, mannerisms, voice/speech) plus the greyscale Good↔Evil
alignment bar, arc arrow, and 5-area Deep Analysis. Add ⋯ separators between
non-contiguous passages in Recast unknown, and harden dialogue attribution
against hallucination with same-language emotion tags.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 21:22:40 +02:00
18b4c1959c Release v1.8.1 2026-06-25 18:48:42 +02:00
3908f365e5 fix: Abort fetch when cancelling audiobook casting and close UI immediately 2026-06-22 17:36:05 +02:00
36437478a6 feat: Read Aloud reader, multi-voice audiobook casting, character sheets (v1.7.0)
Read Aloud (new "Vorlesen" tab):
- PDF (real page render + overlay highlight) / TXT reader with live word
  highlighting, voice + speed, per-sentence synthesis-state colours, zoom
  (fit-width/height, two-page, ±), resume, and a server-side book library
  (syncs across devices; per-unit MP3 audio fetched on demand).

Book -> multi-speaker audiobook:
- "Cast as audiobook" attributes dialogue to characters via the LLM
  (guillemet/quote-style aware, turn-taking, recent-context), with a
  deterministic speech-tag fallback. Editable preview, non-blocking live
  casting panel, then auto-saved as a reopenable Script Rehearser play.
- Audiobook export: synthesise every cast line -> one MP3 per chapter.

Character sheets:
- LLM-extracted, self-filling RPG-style sheets (with page+quote sources)
  in both Read Aloud and the Rehearser.

Also: MP3 storage + per-page/sentence export, voice-library "Precompute
embeddings" pre-warm, German "Vorlesen" i18n + flag language toggle,
large-PDF performance (lazy raster, buffer/canvas eviction, yielded parse),
and the Seed Finder changelog entry.

New: routes/reader.py, POST /api/attribute-dialogue, POST /api/character-sheets,
static/js/{reader,audiobook,character-sheets}.js, static/sections/s-reader.html.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:08:46 +02:00