-
Notifications
You must be signed in to change notification settings - Fork 0
Release Notes v1.4.0
dudarenok-maker edited this page Jul 5, 2026
·
4 revisions
Released 2026-05-22. View on GitHub.
The largest round since the v1.3.1 listening overhaul. The app now drives on phone + tablet over LAN HTTPS, chapter audio is loudness-normalised against EBU R128 with a per-chapter drift report card, AAC/M4A and Opus join MP3 as first-class codecs, the analyzer pipelines a two-model split that nearly doubles quota, and generation parallelises across chapters.
A six-wave round bringing the app to phone + tablet (plan 81).
-
One-command LAN bootstrap —
mkcertdrops a local root CA on every dev box;npm run install:cert-mobileprints LAN URL + QR + per-OS steps;dev:lan/start:lanserve HMR Vite + Node athttps://0.0.0.0:5173/:8443. -
Three viewport tiers —
<640pxphone (single-column, drawers + bottom sheets, full-screen modals),640–1024pxtablet (two-column, dialog modals, right drawer),≥1024pxdesktop (three-pane). Every view re-laid out. -
Touch-equivalence rule — every desktop drag / hover affordance ships a tap replacement (tap-to-assign voice pills, PointerEvent manuscript boundaries covering mouse + touch + pen); hover labels stay faintly visible via a new
coarse-pointer:Tailwind variant; controls ≥ 44×44 px per WCAG 2.5.5.
-
Two-pass
loudnormtargeting -16 LUFS / 11 LU / -1.5 dBTP on every newly-rendered chapter (AUDIO_LOUDNORM_ENABLED), surfaced as a colour-coded per-row drift pill + an expandable report card with sparkline (plans 71, 77). -
AAC/M4A + Opus join MP3 as first-class chapter codecs via
BookStateJson.audioFormat, with matching export shapes (plan 72).
-
Phase 0 (cast detection,
gemma-4-31b-it) and Phase 1 (attribution,gemini-3.1-flash-lite) run in parallel with a configurable min-lag; the two phases hit independent rate-limit buckets, so effective quota nearly doubles. Legacy single-model path preserved verbatim when unset (plan 88).
-
Library search + table view — debounced title / author search, a tag-chip filter row (tags persist on
BookStateJson.tags), and a card↔table view toggle with a series-grouped dense table (plans 73, 76). -
Portable book bundle —
GET /export/portablestreams a single.zip(state + manuscript + audio + cover + change-log + MANIFEST);POST /import/portableaccepts it with rename / replace / skip conflict modes (plan 75). - Manuscript re-upload diff — a side-by-side sentence-level diff gates re-upload before any state mutation, warning when chapter title overrides won't match the new content (plans 74, 84).
-
Per-chapter rename — a pencil affordance on every chapter row, persisted with a sticky
titleOverriddenflag that survives heuristic refresh-titles passes (plan 78). -
Low-confidence triage polish — J / K jump to next / previous misattribution and auto-open the inspector; a typeahead picker materialises a missing series-mate from the prior roster via
POST /cast/add-from-roster(plan 90).
-
Drift modal collapses ~300 events into ~6–18 cards — one card per
(book × character × snapshot)instead of one per event (~7,200 DOM nodes → ~200), with bulk Regen-all / Dismiss-all / Auto-regen-all (plan 91). -
Background drift polling — a bulk
GET /api/revisions?bookIds=...+ a two-tier poller (30s active, 120s background) surfaces Book B's drift in Book A's modal within ~2 min, active-book latency unchanged (plan 83).
-
Bounded worker pool over chapters via
GEN_CHAPTER_CONCURRENCY(default 2), with per-chapter SSE tracks kept isolated (plan 87). - Export queue Retry + Download wired — failed rows re-fire the original POST; done rows without a signed URL stream directly (plan 82).
- Kokoro stop pill in the top bar frees ~1 GB VRAM for an XTTS warm or a heavier analyzer model without restarting the sidecar.
- Edited speaker reassignments / split sentences were silently dropped on regenerate — the analyser cache wasn't rebuilt after a manuscript edit. Now regenerate applies the manuscript-edits overlay before synth (plan 80).
- Chapters had no audible boundary and titles weren't spoken — players cross-faded straight from one into the next. Now each chapter opens with its title voiced in the narrator voice + a baked-in inter-chapter silence (plan 101).
- Force-regen on a range re-ran the catch-up replay against the just-chosen chapters, racing the new run. Now the replay skips in-scope chapters so the user-selected scope wins.
- The generation pill froze at its last snapshot and never drained after completion. Now it drains to zero across excluded + idle gaps.
- Two tabs on one workspace fanned out idle cross-tab updates. Now the broadcast layer diffs snapshots before posting and debounces phase progress.
-
Frontend perf pass — broadcast-middleware shallow-diffs
activeStream, shallow-equality selector wraps, and route-levelReact.lazydrop the main bundle 410 → 345 kB (gzip 108 → 91 kB) (plan 89); manuscript / confirm-cast / listen lists virtualise via@tanstack/react-virtualabove their cutoffs (plans 92, 93). -
Exports moved out of the hidden jail to
<bookDir>/exports/<slug>.<ext>, with a sync-folder "Test" probe and widened rename retries for Drive / OneDrive (plan 79). -
CI Node 20 → 22 → 24;
scripts/wt-merge.mjsreconciliation helper (plan 85); dev-only worktree dashboard at#/worktrees(plan 86); ~14 new e2e specs + the responsive harness; LAN-cert bootstrap scripts + Playwright mobile / tablet projects.
Full changelog: v1.3.1...v1.4.0
- Home
- Getting Started
- Installing Castwright
- Uploading a Book
- Manuscript Management
- Analysis & the Analyzer
- Reviewing Low-Confidence Speaker Tags
- Generating Audio
- The Quality Gate
- Listening & Revising
- Exporting