My Voices
- Top bar with search, filter toggle (active-count badge), synth-source drawer, group and table buttons;
filters/sort in a collapsible labelled panel; one-line sort header with select-all/none checkbox
- Groups chip list is a collapsed accordion; bottom bar is Refresh/Sync/Import plus one Actions (N) menu
(Edit / Audio / Share / Danger), disabled until voices are checked; touch targets stay 44px
- Copy selected works again (copyText was no longer exported), shows "N voice names copied to clipboard"
and falls back to a copy dialog when the async clipboard is unavailable
TTS / engines
- Health probe works for /v1 card URLs and, behind a LiteLLM gateway, checks the selected model's own
upstream so stopped containers are not reported as available
- Unhiding a voice publishes a missing entry to the engine's voices.json (no more silent default-voice fallback)
- Status-bar TTS picker also drives the My Voices and STT-test selectors; Use as TTS refreshes the status bar
Includes the engine connect/disconnect, custom TTS, STT footer and magazine auth work that was already
in the working tree, with their tests.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Magazine P1:
- Images shown automatically during playback (assign_images_to_articles
links each figure to the article whose column it falls in; the client
shows the last image reached in reading order as playback advances).
- "Play all articles" queues every approved article and advances
automatically at the end of each rather than stopping.
- Word-level highlighting, explicitly documented as an ESTIMATE (no
forced-alignment/timestamp source exists): each word's share of the
sentence's real measured audio duration is proportional to its
character length. A checkbox turns it off; sentence highlighting
(measured, not estimated) is unaffected.
- Driving mode: full-screen overlay, two oversized controls, reuses
whatever is already playing/queued.
- Sidebars/pull-out boxes excluded from narration automatically
(mark_sidebars: an anomalously narrow column vs. the page's regular
grid). Fixed a real defect found while building this: a full-width
headline was left in the column-width analysis and could bridge two
genuinely separate columns into one, hiding a real sidebar column
entirely -- caught by a failing test before the fix.
Second OCR engine + fallback ladder:
- KDL Frontier Parser nano wired in via vision_ocr_page_chain (ordered
engine list, first usable result wins, tesseract last resort).
Confirmed live: ~3x faster than Baidu (~12s vs ~40s/page) but returns
plain text with NO coordinate markers, unlike Baidu's labeled regions.
_whole_page_region treats the whole response as one ambiguous
full-page block (gated by ocr_quality_score) rather than discarding
usable text just because it lacks layout structure.
OCR engines page + a real UI bug:
- The OCR & Document Parsing page had no .s-engines-page[data-page="ocr"]
markup at all -- renderLocalContainers already supported an OCR grid
generically, but $('dc-grid-ocr') was always null, so the card grid
silently never rendered. Added an Active OCR Engine panel mirroring
Active Language Model exactly, plus the Local grid -- both configured
engines now appear as ready-made cards, no "Add Custom" dialog needed.
- Fixed the audiobook pipeline's "Previous/Next" nav bar bleeding into
every .section-head in the document (confirmed live on the Engines
page: a "Cast Audiobook" button and "STEP 1/8" hint that made no sense
there). Changed from a blocklist (naming each unrelated section as
noticed) to an allowlist of the pipeline's three actual destinations.
Verified live end-to-end: play-all queue building and manual advance,
word-span markup, driving-mode toggle, OCR page showing both engines as
local cards, zero stray nav bars on the Engines page, no console errors.
20 new backend tests (156 total in the magazine module).
Co-Authored-By: Claude Sonnet 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>
Two unclosed <div class="card"> tags in the TTS settings markup left the
add-engine dialog nested inside the TTS panel's DOM subtree, so it
rendered at zero size whenever another Engines sub-tab (e.g. Speech
Recognition) was active. Also fixed a `let` declared after its first
use, which threw a ReferenceError on every Engines-tab page load.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- STT section now has a Quick test panel: select backend, hit mic button,
see transcript. Records via MediaRecorder, posts to /api/transcribe-bytes.
- _transcribe_audio detects the whisperx-gpu 'NoneType/to' error (caused by
pyannote/speaker-diarization-3.1 requiring a HuggingFace token) and
replaces it with an actionable message explaining how to fix it.
- _to_wav_16k added for STT audio conversion (Whisper/wav2vec2 expect 16kHz).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Port 8080 is Open WebUI — it passes /health + /v1/models checks but
returns 405 on POST /v1/audio/transcriptions. Updated probe logic to:
- treat 405 as 'endpoint missing, try next path'
- treat non-JSON 500 as broken, JSON-500 with detail as 'audio too short' (ok)
- use 500ms silence WAV instead of 1-frame (too tiny for alignment models)
Changed whisper.cpp default from :8080 to :8085 to avoid clash with
Open WebUI. Updated s-llms.html placeholder and code snippet accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix custom card dialog edit mode: save handler now updates existing card by id
instead of always creating a new one; cancel/backdrop also clear editId
- Add "Use as TTS" button to Piper TTS and XTTS v2 static cards
- Add VibeVoice GitHub project link to VibeVoice card
- Add Edit button to custom engine cards (pre-fills dialog for update flow)
- Add initStaticDockerManagement(): injects optional docker container name field
and Stop/Start/Restart buttons into all static llm-local-cards with no HTML changes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add URL input row to all docker container cards (defaulting to host.docker.internal:{port}), with Connect button, localStorage persistence, and green card border when reachable
- Map each docker container to its settings key (tts_url, nvidia_tts_url, nvidia_asr_url, tts_stream_url) via DC_USE_MAP; add "Use as TTS/STT" button that applies the URL to settings
- Add "+ Add Custom" button to LLM / STT / TTS sub-page headers, opening a dialog with Name, Role, URL, optional Docker container name, and Description fields
- Custom cards are saved to localStorage, rendered in dc-grid-llm/stt/tts alongside docker cards, have URL input + Use-as + Remove buttons; container name field enables Stop/Start/Restart
- Expose applyAndSaveSettings and probeUrl as window globals so docker card bindings can call them after renderLocalContainers
- Add dialog CSS and .dc-delete-btn red variant
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename "LLMs" section to "Engines" with brain icon
- Add three sub-pages (Language Models / Speech to Text / Text to Speech) following the same nav-tree pattern as Settings and My Voices
- Rewrite s-llms.html: three s-engines-page divs, docker container grids (dc-grid-tts, dc-grid-stt), VibeVoice card in TTS section, static cloud API cards per category
- Add navEnginesCat() and applyEnginesPage() to nav.js; engines tree open/close in showSection()
- Remove obsolete initLlmCatTabs IIFE; fix dc-refresh-btn from ID to class-based querySelectorAll
- Make integration cards in Connect Apps collapsible (collapsed by default) with favicon/icon prepended to h3
- Unify all Engines card grids to minmax(380px, 1fr) so local, docker, and cloud cards are the same width
- Add s-engines-page CSS (display:none / is-active:flex)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New TTS backend: Kokoro FastAPI (82M) — OpenAI-compatible, 11 built-in
voices, only shows when server is reachable (~300 MB CPU, ~0.1× RTF).
New STT backends in Transcribe dropdown: faster-whisper (CTranslate2 GPU,
~70× RT, 1.5 GB VRAM), whisper.cpp (CPU/CUDA, ~8–15× RT, ~1 GB RAM),
Groq Whisper (fastest cloud, free 2 000 req/day, key shared with Groq LLM).
Backend help panels now show ⚡ speed · ⏰ latency · ⭐ quality · 💾 RAM
metric chips for all TTS and STT backends.
Active Docker Stack cards also get per-container metric chips.
AI Backends section: "Use as STT" / "Use as TTS" one-click buttons on
faster-whisper, whisper.cpp, and Kokoro cards apply URLs to Settings
without leaving the page. Groq Whisper card notes the shared key path.
Settings: Kokoro URL in TTS cluster; faster-whisper URL, whisper.cpp URL,
Groq API key in STT cluster; quick-fill buttons for all local STT engines.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add initLlmsSection() IIFE to app.js: copy buttons, API key persistence with eye toggle
and saved badge, local service URL persistence, Connect/Disconnect toggle with server-side
probe via /api/probe-url (avoids CORS), card turns green on success / red on failure
- Substitute 0.0.0.0 → host.docker.internal before probing (0.0.0.0 not routable from Docker)
- Add /api/local-containers, /api/probe-url, start/stop/restart endpoints to server.py
- Rewrite AI Backends section into Local / Online API categories with Docker stack grid,
local service cards (LLM/STT/TTS) with icons and editable URL inputs, online cloud API cards
- Add bind mounts for static/ and server.py so changes take effect without image rebuild
- Add dc-grid, llm-local-grid CSS with uniform minmax(310px,1fr) card layout
- Fix VOICE_HOST_DIR default via .env so voice folders survive container recreation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inspector:
- Skinny 2-row header: 72px avatar + name/ID row / subtitle row / note row
- Searchable flag picker (dblclick flag icon) — filtered by voice language, falls back to ALL_FLAGS
- Searchable language picker (dblclick lang code) — shows full language names
- Tag reuse: entered tags persist to localStorage as datalist suggestions
- Compact active toggle (32×18px), slim save button (12px/4px padding)
- Show/hide eye toggle and "✓ Key saved" badge on API key fields
AI Backends (s-llms.html + style.css):
- Full CSS design: pill tabs with active accent, animated section transitions
- Service cards: icon bubbles, tier badges (Free/Demo/Paid), stat chips, endpoint rows, model tags
- Highlighted recommended card with accent border
- Dark code blocks for local service snippets with copy feedback
- Show/hide password toggle and auto-appearing "✓ Key saved" badge per card
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>