Commit Graph

23 Commits

Author SHA1 Message Date
c7a1e35539 Security audit, modular refactor, and container-name field
Security fixes:
- Block /proc /sys /dev /run /boot in /api/browse-dirs (path traversal)
- Verify yt-dlp output stays inside TEMP_DIR before registration
- Remove Access-Control-Allow-Origin: * from /api/proxy-audio
- TTL-based temp file registry (default 2h) to prevent disk fill

Performance:
- Cache settings + routing rules in memory (mtime-checked); eliminates
  per-request disk reads on every TTS call

UI:
- Add container name (optional) field to Docker stack TTS/STT engine
  cards (Qwen3 Voice Clone, Voice Design, Custom Voice, Streaming,
  NVIDIA Magpie, Parakeet) — enables Stop/Start/Restart buttons on
  all engine cards, matching the existing Other Local TTS/STT cards

Refactor — backend:
- server.py: 5560 lines → 43-line entry point
- core/ package: constants, registry, validation, docker_client,
  config, routing, audio, voice, presets, tts_helpers
- routes/ package: admin, settings, library, stt, sources, docker,
  tts, conversation (FastAPI APIRouter modules)
- Dockerfile + docker-compose.yml updated to include core/ and routes/

Refactor — frontend:
- static/app.js: 8744 lines → 16 modules in static/js/
  utils, voice-inspector, voice-sources, integrations, routing,
  settings, voice-clone, voice-library, tts-preview, benchmark,
  stt, init, engines, ai-backends, generation, conversation
- static/loader.js updated to load modules sequentially

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 12:13:07 +02:00
77a54b848f Add inline STT test panel and fix whisperx pyannote auth error message
- 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>
2026-05-28 09:27:59 +02:00
27a949f1ff Convert conversation audio to 16kHz for STT (fixes whisperx alignment crash)
STT models (Whisper, WhisperX VAD, wav2vec2 alignment) all expect 16kHz.
Sending 24kHz caused whisperx's VAD to miss speech segments, leaving
alignment with None inputs → 'NoneType has no attribute to' crash.

Added _to_wav_16k() and use it in conversation/turn and transcribe-bytes
endpoints. Health check probe also uses 16kHz silence for consistency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 09:13:12 +02:00
d16be50cc9 Fix STT health check incorrectly marking Open WebUI as whisper.cpp
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>
2026-05-28 09:03:21 +02:00
8f9060d025 Detect broken STT backends via real transcription probe in health check
_stt_backend_health now sends a minimal WAV to the transcription endpoint
after passing /health. A 500 response marks the backend unavailable,
catching containers that pass health checks but crash on model load (e.g.
CTranslate2 built without CUDA support).

Error messages from _transcribe_audio now include the backend URL and
replace generic 'Internal Server Error' with an actionable explanation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 08:31:28 +02:00
28361f2db6 Surface real STT error detail instead of raw HTTP noise
_transcribe_audio now extracts the response body on HTTP errors so the
actual cause (e.g. 'CTranslate2 not compiled with CUDA support') reaches
the user instead of '500 Server Error for url: ...'. Conversation panel
also strips the 'HTTP 500:' prefix to show only the meaningful part.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 08:23:05 +02:00
d2fe6790ee Fix Connect button scope error and add custom STT cards to conversation dropdown
cardType() was defined inside initLlmsSection() IIFE but called from
renderLocalContainers() which is outside that scope, causing a silent
ReferenceError that reset every Connect click to failure. Moved cardType
to module scope.

Custom STT cards (e.g. whisperx-gpu) are now included in /api/stt-backends
and appear in the Conversation STT dropdown. Added _normalize_service_url()
so 0.0.0.0 URLs in stored cards are rewritten to host.docker.internal for
server-side health checks. _transcribe_audio() tries /transcribe as fallback
for custom backends that don't expose /v1/audio/transcriptions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 02:35:38 +02:00
214f2c61cf Make Connect button actually verify the API, not just TCP reachability
probe-url now accepts a type param (llm/stt/tts) and checks service-
specific endpoints: LLM → /v1/models with data[] key, STT → /health
then /v1/models, TTS → /health then /voices endpoints. Random websites
and wrong services are now rejected. Connect passes the card's section
type; success toast shows which endpoint responded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 02:06:07 +02:00
838445ba07 Show all STT/TTS backends with ✓/✗ status in conversation dropdowns
Replaces the filter-to-available-only approach with full lists that
include unavailable backends (disabled, marked ✗) so users can see
what's broken. Also extends STT retry fallback to cover HTTP 500 from
wrong model names (fixes faster-whisper CTranslate2 CUDA build issue).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 01:59:36 +02:00
239bf0dad6 Persist engine URLs and custom cards server-side (survive browser restarts)
Engine URL inputs (Ollama, vLLM, faster-whisper, etc.), custom engine
cards, and the refinement/conversation LLM URLs were stored only in
localStorage and lost on browser data clear. All four are now synced
to settings.json via _patchSettings() with localStorage as fast
initial fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 01:31:46 +02:00
916123f3b4 Fix engine RAM chips with real nvidia-smi GPU memory measurements
Replace all estimated VRAM values with actual per-process GPU memory
from nvidia-smi --query-compute-apps: Magpie TTS ~10 GB, Qwen3-TTS
clone ~6 GB / others ~5 GB, XTTS ~5 GB, VibeVoice ~4 GB, Parakeet
~3 GB, nemotron-asr-streaming ~11 GB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:03:11 +02:00
49e48eb4e3 Update engine RAM metric chips to measured values from docker stats
Parakeet RNNT NIM measured at 550–605 MB (unified RAM), Magpie TTS at
982 MB, and Qwen3-TTS model at 4.3 GB on disk — replacing the placeholder
estimates that were too high across the board.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 23:51:15 +02:00
6a78be7a28 Add Conversation Playground + XTTS v2 backend + VibeVoice voice fix
Conversation Playground (new section):
- WhatsApp-style chat UI with user/assistant speech bubbles
- Click-to-record mic button using MediaRecorder API
- STT → LLM streaming → TTS pipeline via SSE (POST /api/conversation/turn)
- LLM tokens stream into assistant bubble in real time
- Audio auto-plays when TTS synthesises the reply
- Right-side stats panel: STT / LLM TTFT / LLM total / TTS / Total with bar chart
- Turn history list with per-turn total time and pass/fail indicator
- Configurable: STT backend, LLM URL + model, TTS backend + voice, system prompt
- Conversation history maintained across turns (last 20 messages sent to LLM)
- GET /api/conversation/llm-models proxies model list from any OpenAI-compatible LLM

XTTS v2 backend:
- Registers xtts as a first-class TTS backend (xtts_url setting, display name,
  capabilities, health/voice discovery, OpenAI-compatible generation)
- Added XTTS URL field to Settings → Connections
- Use-as-TTS button now saves to xtts_url (not tts_url)
- Batch benchmark backend select now refreshes alongside perf/preview selectors

VibeVoice fix:
- Added /voices to _TTS_VOICE_ENDPOINTS so VibeVoice voices are discovered

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 23:27:57 +02:00
6808db3c59 Rename LLMs to Engines with LLM/STT/TTS sub-page nav, collapsible integration cards, equal-width card grids
- 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>
2026-05-27 21:05:51 +02:00
dc47aa0431 Add Benchmark page, MCP snippets, Captures settings, and history tracking
- New s-performance section: dedicated Benchmark nav entry with run form,
  per-session results table, RTF trend badge (faster/slower/stable), SVG
  sparkline chart, and a History card backed by localStorage (last 50 sessions)
- Performance tab removed from Try It Out; element IDs unchanged so JS works
- renderIntegrationSnippets: adds Python MCP server + Claude Code .mcp.json
  config snippets to the Connect Apps page (integration-card-wide styling)
- Save handler: persists all Captures settings fields (stt_language,
  stt_preferred_backend, auto_refine, refine_model, refine_* toggles,
  captures_default_voice) alongside existing settings
- CSS: integration-card-wide accent border, benchmark history rows, trend
  badges, sparkline wrapper, bench-history-toolbar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 09:57:55 +02:00
cd770801dc Add settings nav tree, Logs viewer, and About page (Voicebox-style hierarchy)
- Sidebar: Settings → nav-tree-head with sub-items (General, Connections,
  Playback, Payloads, Storage, API Keys, Backup, Logs, About)
- nav.js: navSettingsCat() scrolls to section, expands tree on activate
- General: theme select synced with applyTheme, surfaces dark/light toggle
- Logs: /api/logs endpoint (300-entry circular buffer), refresh/clear/
  auto-refresh every 3 s, level filters (All/Error/Warning/Info)
- About: backend availability chips from _ttsBackends, tech stack tags
- server.py: _BufferHandler attaches to root logger, /api/logs GET+DELETE
- Fix duplicate toast on save, guard removed settings-btn reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 03:05:15 +02:00
21a219f816 Add Voicebox-inspired features: effects, history, chunked TTS, playlist, persona, STT refinement
- Audio effects panel (reverb, compressor, chorus, pitch shift via Spotify pedalboard)
  with presets (Studio, Broadcast, Telephone, Warm, Radio) — /api/audio/effects endpoint
- Generation history: last 20 sessions, play/reuse/add to playlist
- Chunked TTS: sentence-boundary splitting for unlimited-length text + WAV merge
- Playlist: ordered clip queue with up/down reorder + Export merged WAV
- LLM STT refinement: clean transcripts with local LLM (remove fillers/repetitions/corrections)
  — /api/refine-text endpoint, configurable toggles, restore-original button
- Voice persona: character description stored in voice meta.json, shown in inspector,
  "Rewrite with persona" button in TryOut via /api/rewrite-with-persona endpoint
- Voices export/import: ZIP backup+restore via /api/voices/export + /api/voices/import
- More whitespace, cleaner UI throughout all new panels

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 02:01:31 +02:00
08a63ef2d9 Add Kokoro TTS + faster-whisper/whisper.cpp/Groq STT backends with metrics
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>
2026-05-27 00:16:43 +02:00
90cc7b7eb1 AI Backends: local service connect/disconnect, Docker container management, 0.0.0.0 probe fix
- 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>
2026-05-26 22:35:42 +02:00
9c47b1998d Add container filesystem folder browser to empty voice state
- /api/browse-dirs endpoint lists subdirectories at any container path
- '📁 Browse' button next to the path input toggles an inline dir browser
- Breadcrumb navigation lets users click up/down through the filesystem
- 'Use this folder' confirms the selection back into the path input
- Existing 'Set & reload' flow unchanged

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 13:21:21 +02:00
ff783a8ab9 Add ElevenLabs Voice Library browser to Get Voices Online
- Backend proxy at /api/elevenlabs/voices forwarding to ElevenLabs shared-voices API
- elevenlabs_api_key added to settings (free key unlocks 12 000+ voices; 3 without key)
- Category pills: All, Featured, Professional, Narration, Conversational, News, Characters, Meditation, Gaming, Training
- Language filter with most common European languages + Arabic/Hindi/ZH/JA/KO
- Gender and age filters, debounced search, pagination (prev/next)
- Voice cards: colored avatar, name, language/gender/age/use-case tags, description, ▶ Play and ↓ Clone buttons
- Play button streams preview MP3 directly; Clone imports the audio into the Clone a Voice flow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 13:14:40 +02:00
8f06971aaf Update port to 7890 and rename image/container/volume to -2
- docker-compose.yml: port 7890:7890, image/container/volume all renamed to tts-voice-creator-clone-and-design-2
- Dockerfile: EXPOSE 7890
- server.py: uvicorn binds to port 7890

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 20:07:47 +02:00
631ca16290 Studio Notebook redesign: warm cream theme, sidebar, multi-file static structure
- New light UI: fixed 220px sidebar, single scrolling page, 8 named sections
- Static files split by concern: style.css, app.js, loader.js, nav.js
- Each page section is its own partial in static/sections/s-*.html
- loader.js fetches all section partials in parallel, then loads app.js and nav.js
- All original functionality, element IDs, and API endpoints preserved

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 19:53:01 +02:00