Frontend: - Add pill-shaped text input + send button (→) to the left of the mic button - Enter key or → click sends text directly without recording audio - Input is disabled while a turn is processing; cleared on submit - Welcome message updated to mention both input methods - New CSS: .conv-input-bar, .conv-text-row, .conv-text-inp, .conv-send-btn, .conv-divider (visual separator between text and mic sections) Backend: - /api/conversation/turn: audio is now optional (UploadFile | None) - New text form field — when provided, STT step is skipped and text is used as the transcript directly; SSE emits transcript event with stt_ms=null - Raises 400 if neither audio nor text is supplied Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
173 lines
9.4 KiB
Markdown
173 lines
9.4 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to TTS Voice Creator — Clone and Design are documented here.
|
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
|
---
|
|
|
|
## [Unreleased] — 2026-05-29
|
|
|
|
### Added
|
|
|
|
- **Text input in Conversation Playground** — a pill-shaped text field and send
|
|
button (→) now sit left of the mic button. Typing a message and pressing Enter
|
|
or → skips STT entirely and sends text directly through LLM → TTS. Makes the
|
|
playground fully usable without a microphone (HTTP context, no mic permission,
|
|
remote access). Backend `/api/conversation/turn` now accepts an optional `text`
|
|
form field; when set, the STT step is skipped and the STT latency row shows `—`.
|
|
|
|
- **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-network` icon) and toggles back
|
|
on click, persisting state in `localStorage`.
|
|
|
|
- **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-row` below 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 `.active` class
|
|
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 via `margin-left: auto`.
|
|
|
|
- **Static engine cards** (`initStaticDockerManagement`) — rebuilt to use the
|
|
same `dc-controls-row` structure as the dynamic Docker stack cards. The
|
|
existing `.llm-local-ping` button is moved from inside the URL row into the
|
|
controls row at initialisation time.
|
|
|
|
### Fixed
|
|
|
|
- **`chrome://flags/…` URL unreadable in microphone-blocked warning** —
|
|
the global `code { 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_BLOCKED` blocklist
|
|
(`/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_DIR` with `.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`** — The `Access-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** — `_registry` is now a
|
|
`dict[str, tuple[Path, float]]` storing each entry with a creation timestamp.
|
|
`_registry_gc()` evicts entries older than `TEMP_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.
|