Engine cards (all TTS + STT, dynamic Docker stack + static):
- Container name field now always visible on every card (was hidden for
absent/not-installed containers)
- Connect button moved out of URL row into a dedicated dc-controls-row;
restyled as solid blue primary CTA
- Connect now toggles to Disconnect (green) when reachable, persists state
- On successful connect, URL is auto-applied to Settings so the backend
appears in TTS/STT dropdowns immediately — no separate "Use as" click needed
- "Use as TTS/STT" button updated: larger, teal "apply" style, tooltip,
gains .active highlight once applied, right-aligned as the trailing action
- Unified control order on every card: [Connect/Disconnect] [Stop|Start|Restart] [Use as →]
- initStaticDockerManagement rebuilt to use the same dc-controls-row layout
as dynamic cards, moving .llm-local-ping from URL row at init time
Conversation section:
- Fix chrome://flags URL being white-on-grey inside the mic-blocked warning
box (global code{background:var(--panel)} overrode the inherited white text)
- Inline-styled the <code> element with a dark translucent background
- Added a Copy button so users can copy the URL without selecting invisible text
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8.9 KiB
Changelog
All notable changes to TTS Voice Creator — Clone and Design are documented here. Format follows Keep a Changelog.
[Unreleased] — 2026-05-29
Added
-
Container name field on all engine cards — every TTS and STT engine card (Docker stack cards and static "Other Local" cards) now always shows the Docker container name input row. Previously absent/not-installed cards hid it; now it is always visible so the container can be pre-configured before starting.
-
Connect / Disconnect toggle — the Connect button now shows "Disconnect" when already connected (with a green
check-networkicon) and toggles back on click, persisting state inlocalStorage. -
Auto-apply on Connect — when a successful connection probe is completed the URL is automatically saved to Settings and the backend becomes available in the TTS / STT dropdown menus immediately, without requiring the user to also click "Use as TTS/STT". The manual "Use as" button still exists for overrides and shows an active highlight once applied.
Changed
-
Connect button — moved out of the URL input row into a dedicated
dc-controls-rowbelow the URL and container-name inputs. Restyled as a solid blue primary CTA button (was a small teal outline button). -
"Use as TTS / STT" — made visually distinct as a teal "apply" action (larger padding, bolder border, chevron icon). Tooltip explains it sets the URL in Settings and enables the backend in dropdowns. Gains
.activeclass once the URL has been applied. -
Unified controls row layout — all engine cards now follow the same left-to-right order:
[Connect/Disconnect][Stop | Start | Restart][Use as →]. Docker action buttons are hidden until a container name is entered; the Use-as button is right-aligned viamargin-left: auto. -
Static engine cards (
initStaticDockerManagement) — rebuilt to use the samedc-controls-rowstructure as the dynamic Docker stack cards. The existing.llm-local-pingbutton is moved from inside the URL row into the controls row at initialisation time.
Fixed
chrome://flags/…URL unreadable in microphone-blocked warning — the globalcode { background: var(--panel) }rule caused the URL text to render as white-on-light-grey inside the red warning box. Fixed by applying inline styles (background: rgba(0,0,0,.35); color: #fff) directly on the<code>element and adding a "Copy" button so users can copy the URL without having to manually select invisible text.
[Unreleased] — 2026-05-29
Security
-
Fixed path traversal in
/api/browse-dirs— Added a_BROWSE_BLOCKEDblocklist (/proc,/sys,/dev,/run,/boot). Requests for paths under these directories now return HTTP 403 instead of listing kernel/system files. -
Hardened yt-dlp output path — After a YouTube download completes the resolved output path is verified to be inside
TEMP_DIRwith.relative_to(). A file written outside the temp directory is rejected with an SSE error event and never registered. -
Removed CORS wildcard on
/api/proxy-audio— TheAccess-Control-Allow-Origin: *header was unnecessary (all callers are same-origin) and exposed proxied audio to arbitrary cross-origin requests. Header removed. -
Temp file registry now enforces a TTL —
_registryis now adict[str, tuple[Path, float]]storing each entry with a creation timestamp._registry_gc()evicts entries older thanTEMP_FILE_TTL_SECONDS(default 2 hours, configurable via env var) and unlinks their files, preventing unbounded disk growth.
Performance
- Settings and routing rules cached in memory —
_load_settings()and_load_tts_routes()previously read from disk on every API request. Both now use mtime-checked in-memory caches (_settings_cache,_routes_cache) that are invalidated automatically on write. Eliminates dozens of redundant file reads per TTS synthesis call.
Added
- Container name field on Docker stack TTS/STT cards — The engine cards rendered
dynamically in the Engines → Text to Speech and Engines → Speech to Text sections
(Qwen3 Voice Clone, Voice Design, Custom Voice, Streaming, NVIDIA Magpie, Parakeet ASR)
now show the same container name (optional) input row that the Other Local TTS/STT
cards already had. Typing a container name immediately enables Stop / Start / Restart
buttons wired to the Docker API. The static STT cards (faster-whisper-server,
whisper.cpp) received the same treatment via
initStaticDockerManagement().
Refactored
Backend — server.py split into core/ + routes/ packages
server.py went from 5,560 lines to a 43-line entry point that creates the
FastAPI app, registers routers, and mounts static files. All logic was extracted into
single-responsibility modules:
core/ — pure utilities (no FastAPI decorators)
| Module | Responsibility |
|---|---|
constants.py |
Boot-time env defaults, CONFIG_DIR/CONFIG_FILE/STATIC_DIR paths, in-memory log buffer |
registry.py |
TEMP_DIR, TTL-based temp file registry (_registry_put/get/gc) |
validation.py |
_validate_http_url, _normalize_service_url, _copy_limited, _safe_child_path |
docker_client.py |
Raw Unix-socket Docker HTTP client (_docker_get_json, _docker_post) |
config.py |
Settings load/save/normalize, TTS stability helpers, backend URL resolution |
routing.py |
TTS route rules load/save/resolve, language detection, routing log |
audio.py |
_to_wav_24k/16k, _trim, _duration, _normalize_segment, auto-trim scoring |
voice.py |
Voice metadata helpers, backup management, benchmark helpers |
presets.py |
Voice Design preset load/save, virtual voice resolution |
tts_helpers.py |
TTS request helpers, streaming, NVIDIA/VibeVoice/XTTS backends, audio proxy |
routes/ — FastAPI APIRouter modules
| Module | Routes |
|---|---|
admin.py |
GET /, GET /favicon.ico, GET /api/browse-dirs, GET /robots.txt |
settings.py |
/api/settings, /api/tts-routes, /api/tts-routing-log, /api/logs, /api/voice-design-presets |
library.py |
All /api/voice* and /api/voices*, /api/save, /api/upload, /api/route-sounds*, /api/audio/{fid}, /api/auto-trim, /api/process |
stt.py |
/api/stt-backends, /api/transcribe, /api/transcribe-bytes |
sources.py |
/api/voice-sources, /api/import-source-audio, /api/proxy-audio, /api/quick-import-voice, /api/download-yt, /api/elevenlabs/voices |
docker.py |
/api/local-containers/*, /api/probe-url |
tts.py |
/api/tts-preview, /api/tts-style-variation, /api/tts-stream-*, /api/voice-design, /v1/*, /api/tts-voices, /api/tts-backends, restart endpoints |
conversation.py |
/api/refine-text, /api/rewrite-with-persona, /api/audio/effects, /api/voices/export, /api/voices/import, /speak*, /mcp, /api/conversation/* |
Dockerfile updated to COPY core/ core/ and COPY routes/ routes/.
docker-compose.yml updated to mount ./core:/app/core:ro and ./routes:/app/routes:ro.
Frontend — static/app.js split into static/js/ modules
app.js (8,744 lines) split into 16 focused modules totalling the same 8,744 lines.
static/loader.js updated to load them sequentially in dependency order.
| Module | Lines | Responsibility |
|---|---|---|
utils.js |
364 | $, toast, escHtml, debounce, theme, language/flag helpers, searchable picker, tab helpers |
voice-inspector.js |
397 | 3-pane voice workbench (selectVoice, updateInspector) |
voice-sources.js |
277 | External voice source scraping UI (loadGetVoices, renderGetVoices) |
integrations.js |
211 | Code snippet generation for SillyTavern, Open WebUI, HA, curl, MCP |
routing.js |
542 | TTS routing rules editor |
settings.js |
385 | loadSettings, applyAndSaveSettings, settings panel |
voice-clone.js |
774 | WaveSurfer waveform, drop zone, microphone, trim UI, voice design dialog |
voice-library.js |
2654 | Full voice library: list, row rendering, operations (save, rename, delete, normalize, benchmark) |
tts-preview.js |
528 | fetchTtsPreviewBlob, createTtsAudioSource, preview panel |
benchmark.js |
218 | Batch benchmark section |
stt.js |
287 | STT→TTS playground, refreshSttBackends |
init.js |
49 | App bootstrap (calls loadSettings, syncs UI state) |
engines.js |
625 | ElevenLabs browser, custom engine cards, Docker container management |
ai-backends.js |
520 | AI backend cards, LLM snippet collapse, initStaticDockerManagement, collapsible cards |
generation.js |
393 | WAV merge, chunked TTS, generation history, playlist, audio effects, LLM refinement |
conversation.js |
520 | Settings logs/about, voices import, conversation playground |
Earlier history
See git log for the full commit history prior to this release.