Modell-Katalog → ⚙ llama.cpp zeigt je LLM-Box die installierte Version,
sucht nach Updates (Pruefsumme des Image-Tags in der Registry + letztes
llama-swap-Release) und aktualisiert auf Knopfdruck: altes Image sichern,
neues ziehen, Container per Compose neu anlegen, Selbsttest (llama.cpp
sieht die Karten, vorgeladene Modelle wieder bereit) — sonst automatisch
zurueck. Zuruecksetzen auf die Vorversion per Knopf.
Docker-Zugriff hat nur der neue llm-updater (feste Aktionen fuer
aria-llama-swap, kein Port nach aussen, Token in /models). Der llm-adapter
reicht llm_runtime weiter und meldet den Fortschritt. RVS-Allow-List um
llm_runtime/_result/_progress ergaenzt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die Box meldet bei jedem Download-Fortschritt ihre Netzwerkkarten (echte
Karten, die "up" sind) mit Tempo. Der Container sieht nur sein eigenes
eth0, darum liest er das /sys des Rechners (neu: /sys:/hostsys:ro im
llm-adapter). Das Download-Fenster zeigt pro Download z.B.
"🔌 enp5s0 100 Mbit/s (max. ~12 MB/s — Kabel/Port prüfen)" — orange unter
1 Gbit/s. Anlass: ki-box hing an einem 100-Mbit-Port, 8 Verbindungen
brachten darum nichts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Das NVIDIA-Container-Toolkit ersetzt NVIDIA_VISIBLE_DEVICES im Prozess durch
"void" — whisper/f5tts/voxtral meldeten das als GPU. Die Compose gibt die
Karte jetzt zusaetzlich als ARIA_GPU mit (nur Anzeige).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Zwei Ursachen, beide auf der KI-Box nachgewiesen:
1. llama.cpp fand auch mit Treiber 615 keine Karte ("unsupported display
driver / cuda driver combination"). Das llama-swap-Image traegt in seiner
ld.so.conf die eigene CUDA-Kompatibilitaets-libcuda (575) VOR dem vom
Container-Toolkit eingehaengten Host-Treiber (615) ein. Die Kompatibilitaets-
bibliothek hilft nur Rechenzentrumskarten; bei GeForce scheitert llama.cpp
damit — mit aelterem Treiber ("forward compatibility …") wie mit neuerem —
und rechnet still auf der CPU. Jetzt LD_LIBRARY_PATH mit dem Host-Treiber
zuerst. Auf der Box getestet: llama.cpp sieht CUDA0 + CUDA1. Whisper und
F5-TTS (andere Images) sehen ihre Karte mit 615 ohnehin.
2. Nach dem Reboot erreichte kein Container den RVS ("Temporary failure in name
resolution"). Debian traegt die Netzwerkkarte als allow-hotplug ein; darauf
wartet network-online.target nicht. Docker startete die Container 2 s nach
"online", bevor DHCP den DNS-Server lieferte ("DNS resolver has no external
nameservers"), und die Container behalten diesen leeren Stand. Passiert bei
jedem Reboot. bootstrap.sh legt jetzt ein systemd-Drop-in an: Docker wartet
vor dem Start bis zu 90 s auf einen Nameserver in /etc/resolv.conf, dann
startet es trotzdem. Netzkonfiguration bleibt unangetastet. Escaping und
beide Pfade (DNS da / nicht da) in einer echten systemd-Unit getestet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bisher konnte jeder Client per Modellname llama-swap zum Wechseln bringen —
ein Fremdprogramm haette ARIA das Modell unter den Fuessen weggetauscht.
Jetzt:
- Jede LLM-Karte einer Box (LLM_GPUS=1,2, alt LLM_GPU=1) haelt GENAU ein
Modell, dauerhaft. Welches, legt nur die Diagnostic fest. Karten, die nicht
fuers LLM vorgesehen sind, tauchen beim LLM nicht auf und werden als Ziel
abgelehnt.
- Clients (ARIA, Fremdprogramme ueber RVS, OpenHands ueber den OpenAI-Port)
sehen nur die geladenen Modelle und laden nie: Anfrage fuer ein anderes →
model_not_loaded mit Liste des Geladenen (RVS) bzw. HTTP 404 (OpenAI-Port).
Nichts wird verdraengt.
- Mehrere Clients koennen dasselbe Modell gleichzeitig nutzen.
llm-adapter: Belegung in /models/aria_slots.json. Die llama-swap-Config
enthaelt nur belegte Karten: pro Modell CUDA_VISIBLE_DEVICES=<Karte>, ttl 0,
groups.swap=false, hooks.on_startup.preload. Alles gegen llama-swap
ausprobiert (zwei Modelle gleichzeitig ready, keins verdraengt, Unbekanntes
404, env kommt beim jeweiligen llama-server an). llama-swap laeuft mit
--watch-config; die frueher aufgerufenen Reload-Endpunkte (/reload,
/api/config/reload) gibt es nicht (404). Neu: llm_unload_model (Karte leeren),
llm_models_request → llm_models (Erkundung, jede Box antwortet einzeln).
Fehlgeschlagenes Laden setzt die Karte auf ihr vorheriges Modell zurueck,
sonst risse jedes Neuladen die anderen Karten mit. Uebernahme: ohne
Belegungsdatei landet LLM_MODEL auf der ersten LLM-Karte.
Compose: llama-swap sieht alle Karten (NVIDIA_VISIBLE_DEVICES=all) und
zaehlt sie wie nvidia-smi (CUDA_DEVICE_ORDER=PCI_BUS_ID); das Pinnen pro
Modell macht der Adapter.
Bridge: uebernimmt models/slots auch aus worker_ping (nach "Entladen" sonst
30 s veraltet) und sagt sofort ab, wenn das Modell auf keiner Box liegt,
statt per Broadcast in den Timeout zu laufen.
Diagnostic: Flotte zeigt pro LLM-Karte Modell + Zustand + "Entladen";
Katalog waehlt eine Ziel-KARTE (leere vorausgewaehlt, Ersetzen mit
Rueckfrage); Download-Fenster nennt Karte und was ersetzt wird.
RVS: llm_unload_model, llm_models_request, llm_models freigegeben.
docs/LLM-SCHNITTSTELLE.md: Schnittstelle fuer Drittprogramme (RVS + OpenAI-
Port), Fehlercodes, Gleichzeitigkeit, Python-Beispiel.
Tests: 23 gegen llama-swap (Adapter direkt) + Ende-zu-Ende ueber den echten
RVS mit dem Adapter als Prozess: Laden per RVS mit Fortschritt, das
Doku-Beispiel unveraendert (nur Adresse) findet beide Karten und bekommt eine
Antwort, Absage/Schweigen wie dokumentiert, zwei Clients parallel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eigentlicher Fehler zuerst: llm_provision_model/_result und llm_remove_model
standen nie in der RVS-Allow-List. Der RVS verwirft unbekannte Typen mit einem
stillen return — jeder Klick auf "Laden" im Modell-Katalog ist seit Stage D
(19.09.) an dieser Liste gestorben, die Box hat nie davon erfahren. Laden
liessen sich nur die Modelle aus der Basis-Config der Box.
Gefunden, weil grep rvs/server.js fuer eine Binaerdatei hielt und still
uebersprang: in Zeile 164 stand seit a7998bcd ein ECHTES Nullbyte im
Template-String statt eines Escapes. Node stoert das nicht, aber git zeigte
fuer jede Aenderung am RVS nur noch "Binary files differ". Jetzt \u0000 —
zur Laufzeit derselbe String.
Fortschritt: llama.cpp zieht das GGUF per -hf selbst und meldet nichts. Der
llm-adapter fragt vorab bei Hugging Face, welche Dateien (Groesse, sha256)
kommen, und misst genau diese im HF-Cache-Layout, das llama.cpp verwendet:
/models/models--org--repo/blobs/<sha256>.downloadInProgress (waechst)
/models/models--org--repo/blobs/<sha256> (fertig)
Layout gegen den echten llama.cpp-Server ausprobiert, nicht angenommen. Geht
auch bei gesplitteten Modellen und zwei Downloads gleichzeitig; Fallback fuer
aeltere Layouts ueber alle *.downloadInProgress. Phasen: queued → start →
download (%, MB/s, Restzeit) → load ("laedt in die Karte") → ready ("in Karte
N geladen", Name + VRAM aus nvidia-smi) bzw. error.
Mitgefixt: der Warmup wartete LLM_TIMEOUT_SEC (Default 60 s). Ein Modell mit
mehreren GB meldete deshalb "Fehler", waehrend llama-swap weiterlud. Jetzt
LLM_WARMUP_TIMEOUT_S (1900 s, ueber llama-swaps healthCheckTimeout).
Diagnostic: Knopf "⬇ Downloads" neben "Von HuggingFace aktualisieren" mit
Zaehler fuer laufende; "Laden" oeffnet das Fenster direkt. Der Server merkt
sich den Stand pro (Box, Modell), ein spaeter geoeffneter Tab sieht laufende
Downloads. Antwortet die Box nicht, steht nach 30 s eine Warnung da statt
nichts.
Compose (KI-Box): llm-adapter bekommt LLM_GPU (Karte fuer die Meldung) und
HF_TOKEN (Dateiliste gesperrter Repos).
Test: Fortschritt gegen einen echten llama.cpp-Download (Qwen2.5-0.5B Q8,
676 MB): Prozent steigend 0 → 91.6, dann load; zweiter Lauf aus dem Cache
direkt load mit cached=true.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
llama-swap ist bereits OpenAI-kompatibel, war aber nur im Compose-Netz erreichbar
(kein ports-Mapping). Jetzt nutzbar fuer OpenHands, Continue, Open WebUI & Co.
- compose: llama-swap veroeffentlicht 8080 als
${LLM_OPENAI_BIND:-127.0.0.1}:${LLM_OPENAI_PORT:-8081} — sicher per Default
(nur localhost), fuer LAN bewusst BIND=0.0.0.0 setzen.
- llm-adapter: API-Key wird in JEDEN llama-server-Befehl der generierten
llama-swap-Config eingehaengt (--api-key, shlex-gequotet). Quelle: .env
(Vorrang) sonst /models/openai_key.json (0600). Neuer Handler
llm_openai_config setzt ihn zur Laufzeit und lehnt bei .env-Vorrang ab.
worker_hello meldet Port/Bind/keySet/envLocked — den Key NIE (Broadcast!).
- Diagnostic: pro LLM-Box Endpunkt-Zeile mit Base-URL, Key-Status und Eingabe.
Bei .env-Vorrang ist das Feld schreibgeschuetzt (🔒). Warnung, wenn im LAN
offen ohne Key. Der PORT wird nur ANGEZEIGT: er ist ein Docker-Port-Mapping
und steht beim Container-Start fest — dafuer ist die .env zustaendig.
- rvs: llm_openai_config(_result) in ALLOWED_TYPES (sonst still verworfen).
- Neues Profil 'openhands' (COMPOSE_PROFILES=llm,openhands) mit Port/Bind/Modell
aus der .env, lokales LLM vorbelegt. Ohne Profil aendert sich nichts.
- .env.example + README: alle Variablen, Sicherheitshinweise (offener Endpunkt,
Docker-Socket bei OpenHands), curl-Test und wann der Key greift.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pro Box ein "Auslastung"-Button in der Compute-Flotte → Modal mit live
nvidia-smi (1s), Graphen (GPU-Auslastung + Tokens/Intervall) und Besen-Reset.
Historie liegt auf der Box, Diagnostic holt sie via RVS.
- node_stats.py (identisch in allen 4 Worker-Build-Contexts): Sampler alle 15s
(nvidia-smi + Token-Delta → Ringpuffer ~500 Punkte, persistent als JSON auf
der Box), Live-Stream (node_stats, 1s, Auto-Stop 300s), History-Request,
Reset. nvidia-smi via async subprocess, fail-safe ohne GPU.
- Worker-Wiring (f5tts/whisper/voxtral/llm-adapter): Import, Sampler-Task,
_stats.handle() nach dem targetInstance-Filter. llm-adapter zaehlt Tokens
(usage.total_tokens) → Token-Graph nur bei LLM-Boxen. Dockerfiles kopieren
node_stats.py.
- compose: llm-adapter bekommt runtime:nvidia + NVIDIA_VISIBLE_DEVICES=all +
DRIVER_CAPABILITIES=utility (nur nvidia-smi, KEIN VRAM/Compute).
- diagnostic/server.js: relay node_stats_* (Browser→Box) + forward (Box→Browser).
- diagnostic/index.html: Auslastung-Button pro Node (Ziel bevorzugt llm-Instanz),
Modal mit live nvidia-smi + Inline-SVG-Sparklines, Besen-Reset.
Reporter-Wahl bevorzugt die llm-Instanz (sieht alle GPUs + Tokens); GPU-Worker
sehen ihre gepinnte Karte. Gitignored Historie stoert git-Baum der Box nicht.
Deploy: diagnostic + GPU-Boxen neu bauen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rein terminologisch: die feste "Gamebox" ist konzeptuell zu beliebig vielen
AI-Boxen geworden (Multi-Node-Compute-Fleet). Wort-Sweep ueber Code-Kommentare,
Strings, README, docs, .env.example, CHANGELOG — keine Identifier/Keys betroffen
(Gamebox kam nirgends in Variablennamen vor). Casing erhalten: Gamebox→AI-Box,
gamebox→ai-box. NODE_NAME-Default gamebox→ai-box, Instanz-IDs f5tts@ai-box.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die feste "Gamebox" wird zu beliebig vielen Compute-Nodes. Jeder Node startet
ueber COMPOSE_PROFILES nur die Dienste, die er anbieten soll, und pinnt sie per
*_GPU auf bestimmte Grafikkarten.
- xtts/docker-compose.yml: jeder GPU-Dienst hinter einem Profil
(voxtral/whisper/f5tts/llm); deploy.devices-Block ersetzt durch
runtime: nvidia + NVIDIA_VISIBLE_DEVICES=${SVC_GPU} (erlaubt auch "0,1");
NODE_NAME an alle RVS-Dienste.
- xtts/.env.example: COMPOSE_PROFILES, NODE_NAME, VOXTRAL/WHISPER/F5TTS/LLM_GPU
mit Beschreibungen; Beispiele STT-Box / TTS-Box / LLM-Box / All-in-One.
- README: "Gamebox-Stack" → "Compute-Nodes"; Diagramm, Deploy-Tabelle und
Setup-Abschnitt auf Multi-Node umgeschrieben.
Stage 1 von 3 (Aufteilung+Config+Docs). Reine Config/Docs, kein Verhaltens-
Risiko: Single-Node mit COMPOSE_PROFILES=voxtral,f5tts,llm laeuft wie bisher.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Voxtral hatte 0 Speaker-Filter (mit Voxtral reagierte ARIA auf JEDE Stimme). Jetzt portiert aus der whisper-Bridge: speaker_id.py (ECAPA/speechbrain) kopiert, Einmal-Check auf die ersten 1.5s (fremde Stimme → leeres stt_endpoint reason=speaker_mismatch, kein Transcribe/Brain), voice_id_enroll/status/delete-RVS-Handler + voiceIdThreshold-config. voice-id-Volume gemountet, speechbrain in requirements. Ohne Enrollment fail-open.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Profile getauscht: voxtral-bridge laeuft jetzt bei jedem 'docker compose up', whisper-bridge nur noch mit --profile whisper. Loest das 'nach down/up startet whisper statt voxtral'-Problem. Immer nur EIN STT gleichzeitig (sonst stt_*-Kollision).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Modell laedt knapp nicht (12GB-Karte hatte 3.13GB durch Fremdprozess belegt). Anti-Fragmentierungs-Schalter reduziert den Peak-Bedarf beim Warmup; zusaetzlich muss GPU 1 frei sein (whisper stoppen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Backports brachte keinen neueren Treiber (bleibt 550/CUDA 12.4). Statt Upgrade: Voxtral-Mini-3B-2507 via Transformers mit torch 2.6.0+cu124 (F5-Trick) — laeuft auf 550, ~9 GB bf16 auf GPU 1. Chunked wie whisper mit dem adaptiven M0.1-Endpointer, RVS-Protokoll identisch (drop-in). Ersetzt den vLLM-Realtime-4B-Ansatz (der brauchte 16 GB). Compose: ein Container, GPU-1-gepinnt, Profil 'voxtral'. Transformers-API in einer Methode gekapselt (verify-on-run).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die zwei 3060 sind ungleich (GPU0=8GB, GPU1=12GB), nicht 12+12. Groesstes Modell (STT, spaeter Voxtral-STT-3B ~9GB) muss auf die 12GB-Karte: whisper->GPU1. TTS(F5)+LLM auf die 8GB-Karte: ->GPU0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer xtts/voxtral-Container (RVS<->vLLM-Realtime-WS, adaptiver Endpointer), hinter Compose-Profil 'voxtral' (braucht >=16GB VRAM, startet nicht im Default). Bestehende Satelliten auf die zwei 3060 gepinnt: whisper->GPU0, f5tts->GPU1, llama-swap->GPU0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mehrere lokale Modelle, on-demand geladen/geswappt, in Diagnostic waehlbar.
Design: das Brain schickt den Modellnamen (aus local_llm.json) im llm_request
mit -> Adapter -> llama-swap laedt/swappt. Keine separate Gamebox-Config noetig.
- xtts: `llama`-Container -> `llama-swap` (unified-cuda), config.yaml mit
qwen3-8b (Standard) + qwen3-4b; Auto-Download via -hf, Cache /models geteilt
(qwen3-8b schon da). Adapter -> llama-swap:8080, Timeout 600s (Erst-Download).
- adapter: `model` aus dem Request an llama-swap durchreichen (Fallback env).
- brain: router.load_config liest localLlmModel; local_llm_chat(model=...);
agent gibt cfg-Modell mit; bridge reicht model durch (_local_llm + Route).
- diagnostic: /api/local-models-list (aus /shared/config/local_models.json,
seeded), local-llm-config um localLlmModel erweitert; Dropdown "Lokales
Modell" im Settings-Block + Erst-Download-Hinweis.
BLIND gebaut (Gamebox nicht testbar hier): llama-swap CLI/Config-Pfad beim
ersten Start via `docker logs aria-llama-swap` pruefen. Live-Lade-Status
(Adapter->Diagnostic) ist B0.5-2 (Folgeschritt).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Statt einer manuell abgelegten Datei zieht llama.cpp das Modell beim ersten
Start selbst von Hugging Face (-hf Qwen/Qwen3-8B-GGUF:Q4_K_M, offizielles
Repo verifiziert) und cached es unter xtts/models (persistent). Modell/Quant
via LLM_HF_REPO/LLM_HF_QUANT in der .env wechselbar, kein Code.
Diagnostic-Modellauswahl (on-demand laden/aktivieren mehrerer Modelle) als
Folge-Baustein B0.5 via llama-swap ins Plan-Doc aufgenommen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Plan B, Phase B0 (Provider): lokales Qwen3-8B auf der Gamebox, angebunden
per RVS wie f5tts/whisper (kein IP-Pflegen, nur URL+Token).
- xtts/llm-adapter/: RVS-Client (spiegelt whisper-bridge: TLS+ws-Fallback,
Reconnect-Backoff), nimmt llm_request, ruft llama.cpp /v1/chat/completions
lokal, antwortet llm_response (korreliert per requestId). Nicht-streamend
in B0; llm_partial fuer B2 reserviert.
- xtts/docker-compose.yml: neue Services `llama` (llama.cpp server-cuda,
GGUF via ./models, OpenAI-API auf :8081) + `llm-adapter`.
- rvs/server.js: ALLOWED_TYPES += llm_request/llm_response/llm_partial.
- GGUF (mehrere GB) via .gitignore aus dem Repo; xtts/models/ mit .gitkeep.
Topologie-Hinweis: Gamebox@home, ARIA@RZ -> Bounce ueber Internet ist
unvermeidbar (Voice macht's schon so); Router faellt bei Nichterreichbarkeit
per Escalation auf Claude zurueck. Consumer-Seite (Bridge-Relay + Brain-
Client + Router) kommt als naechstes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eigener Compose-Stack im /flux Verzeichnis (kann auf separater Maschine
laufen). aria-bridge routet flux_request via RVS, ARIA referenziert das
fertige PNG im Reply mit [FILE: ...]-Marker. Brain-Tool flux_generate
mit Caps fuer steps/dimension.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vier Bugs in einem Aufwasch:
1. HF-Cache als Bind-Mount zurueck
xtts/hf-cache:/root/.cache/huggingface fuer beide Bridges. War vorher
raus, dadurch jedes Container-Restart = ~3GB Whisper-Download +
~1GB F5-TTS-Download. User dachte 5min ist einmalig — ist aber bei
jedem Restart. Jetzt: einmal pro Maschine geladen, fertig.
2. Banner zeigte stale "ready"
whisper-bridge sendete beim Connect nur dann Status wenn Modell schon
geladen war. Sonst blieb der App/Diagnostic Banner auf dem alten
"ready" State von vor dem Restart haengen — User sah "bereit" obwohl
gerade gar nichts geladen war. Jetzt wird IMMER ein Status broadcast:
ready oder loading.
3. config_request Pattern
aria-bridge wusste nicht wann Gamebox-Bridges sich (re)connecten.
Wenn die nach aria-bridge kamen, verpassten sie den Config-Broadcast
und blieben mit Hard-Defaults stehen.
Jetzt: whisper- und f5tts-bridge senden beim Connect ein
config_request, aria-bridge antwortet mit der persistierten Config
(whisperModel, xttsVoice, f5tts*-Felder).
4. RVS ALLOWED_TYPES um config_request erweitert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stefan akzeptiert die ~5min Modell-Download-Zeit nach jedem Container-
Start, dafuer keine 50GB Cache-Bloat mehr und kein Bind-Mount-Verzeichnis
zu pflegen.
- xtts/docker-compose.yml: hf-cache Bind-Mount entfernt fuer beide
Bridges. Modelle werden im writable Container-Layer abgelegt und mit
jedem `docker compose down` automatisch weggeraeumt.
- xtts/.gitignore: hf-cache/ Eintrag raus
- RVS ALLOWED_TYPES: service_status hinzu
Bridges broadcasten Lade-Status:
- f5tts-bridge: bei Connect 'loading' -> ensure_loaded -> 'ready'.
Auch bei config-getriggertem Modell-Wechsel: erst 'loading' Broadcast,
dann reload, dann 'ready'.
- whisper-bridge: gleiches Pattern. Modell wird jetzt erst nach
RVS-Connect geladen damit der loading-Broadcast tatsaechlich rausgeht.
Diagnostic:
- server.js: service_status wird an Browser durchgereicht
- index.html: neues Banner unten rechts (fixed position) zeigt Status
fuer beide Services. Aggregiert: Icon ist Lupe waehrend Loading,
Check wenn alles ready, X bei Error.
- Wenn alles ready: X-Button erscheint (manuell schliessen) +
nach 8s automatisches Fade-Out.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Beide Bridges teilen sich jetzt einen Bind-Mount ./hf-cache:/root/.cache/
huggingface. Vorher waren das zwei getrennte Named Volumes
(f5tts-models + whisper-models), die unter Docker Desktop / Windows
in der docker-desktop-data.vhdx gelandet sind und die VHDX nie wieder
freigegeben haben — auch nach docker volume rm bleibt der belegte Platz
in der VHDX bis zum Factory Reset.
Bind-Mount loest beides:
- Files direkt im xtts/hf-cache/ sichtbar, einfach im Explorer zu loeschen
- Kein VHDX-Bloat mehr
- Beide Container teilen sich den Cache (HF-Struktur identisch, keine
Konflikte da andere Modelle)
Cleanup von vorhandenen 50GB:
docker compose down
docker volume rm xtts_f5tts-models xtts_whisper-models (oder via
Docker Desktop UI)
Anschliessend in Docker Desktop: Settings -> Resources -> Disk image
location -> Disk usage -> "Clean up" / Reset wenn die VHDX nicht
schrumpft.
xtts/.gitignore: hf-cache/ + voices/ + .env
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Folgt der "keine neuen Settings in .env" Regel.
f5tts/bridge.py:
- F5TTS_MODEL/CKPT_FILE/VOCAB_FILE/CFG_STRENGTH/NFE_STEP ENV-Vars raus
- Hard-coded Defaults im Code (DEFAULT_F5TTS_*)
- F5Runner besitzt Live-Settings als Instance-Vars + update_config()
- config-Broadcast triggert Modell-Reload nur wenn Modell-relevantes
sich aendert (cfg_strength/nfe_step ohne Reload)
- F5TTS_DEVICE bleibt ENV (Hardware-Bootstrap)
xtts/docker-compose.yml: F5TTS_* ENV-Vars rausgenommen, Kommentar
verweist auf Diagnostic-Config.
aria-bridge: nimmt f5tts*-Felder im config-Handler entgegen, persistiert
sie in voice_config.json. Beim RVS-Connect broadcastet die Bridge die
persistierte Config einmalig — damit die f5tts-bridge nach Container-
Restart automatisch die zuletzt gewaehlten Settings bekommt, ohne dass
der User in Diagnostic was klicken muss.
Diagnostic UI:
- Neuer aufklappbarer "F5-TTS Modell-Tuning (advanced)" Bereich
- Felder: Modell-ID, Custom-Checkpoint, Vocab, cfg_strength, nfe_step
- voice_config beim Laden: Felder werden zurueck in die UI gesetzt
- sendVoiceConfig schickt die neuen Felder mit
- Server: send_voice_config persistiert die Felder, leere Strings
werden geloescht damit die Hard-Defaults greifen
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
F5TTS_v1_Base ist hauptsaechlich auf Englisch+Chinesisch trainiert; bei
Deutsch (oder anderen Romance/Germanic-Sprachen) schwimmt der Generator
ohne starkes Conditioning gerne in eine andere Sprache.
- cfg_strength 2.0 → 2.5 (per ENV F5TTS_CFG_STRENGTH ueberschreibbar)
- nfe_step bleibt 32 (per ENV ueberschreibbar)
- F5TTS_CKPT_FILE / F5TTS_VOCAB_FILE als ENV — damit man eine Community-
German-Checkpoint einhaengen kann ohne Code-Aenderung
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Neuer aria-f5tts-bridge Container:
- Python-Service, laedt F5TTS_v1_Base beim Start
- Empfaengt xtts_request via RVS, synthetisiert mit Voice-Cloning,
streamt PCM-Chunks (audio_pcm, 16-bit s16le) wie zuvor die XTTS-Bridge
- Teilt lange Texte an Satzgrenzen, streamt satzweise
- Fade-In auf erstem Chunk, Queue gegen parallel-Render
Voice-Management:
- Speicherort weiterhin /voices/, aber jetzt als Paar
{name}.wav + {name}.txt (F5-TTS braucht Referenz-Transkription)
- voice_upload: WAV speichern, intern stt_request an whisper-bridge
senden, Transkription als .txt ablegen → user muss nichts eintippen
- On-the-fly Transkribierung: wenn eine WAV ohne .txt liegt, wird
bei erstem Render/Preload nachgezogen
- Bestehende RVS-Messages (voice_upload/xtts_list_voices/... etc.)
bleiben unveraendert → keine App/Diagnostic-Aenderung noetig
Gaming-PC docker-compose:
- xtts + xtts-bridge Services entfernt
- f5tts-bridge + whisper-bridge bleiben/kommen rein
- Volume xtts-models → f5tts-models
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Neuer Container aria-whisper-bridge auf der Gamebox — faster-whisper
CUDA mit float16. Der Container verbindet sich per WebSocket an den RVS,
nimmt stt_request entgegen, laeuft ffmpeg+Whisper, antwortet mit
stt_response. Hoert zusaetzlich auf config-Broadcasts und lädt das
Modell hot-swap bei Diagnostic-Wechsel.
aria-bridge ruft jetzt primaer die Gamebox an; nur wenn die nicht binnen
45s antwortet, faellt auf lokales Whisper (CPU) zurueck. Das lokale
Modell wird lazy geladen, spart RAM auf der VM.
RVS: stt_request/stt_response zur ALLOWED_TYPES-Liste.
Diagnostic-Voice-Config (whisperModel-Feld) bleibt unveraendert —
die Auswahl wird an die Gamebox durchgereicht.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Das Image-Default-CMD liest Konfig aus ENV Variablen:
CMD: ... -ms \${MODEL_SOURCE:-"apiManual"}
Also reicht MODEL_SOURCE=local — command bleibt Image-Default und wir
sparen uns den brueckigen Override der schief ging (python nicht da,
flag-Namen raten, etc.).
Zusaetzlich: EXAMPLE_FOLDER=/voices damit der Speaker-Folder auf unser
gemountetes /voices zeigt (sonst /app/example was nur die Demo-Voices
enthaelt).
Kein command override mehr noetig — das Image macht alles wie vorher,
nur mit local-Mode.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Image hat nur /usr/bin/python3, kein 'python'-Symlink.
Vorher ging's weil kein command override — das Image-Default CMD
lief durch. Wir ueberschreiben nur damit wir -ms local setzen koennen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NVIDIA-Entrypoint fuehrt 'exec \$@' aus — erstes Arg muss ein
ausfuehrbares sein. Nur Flags zu geben ('--listen') fuehrt zu
'exec: --: invalid option'.
Fix: command=['python','-m','xtts_api_server','-ms','local',...]
Damit wird der xtts_api_server Python-Modul gestartet und im
local-Mode konfiguriert.
Ob die Flag-Namen exakt stimmen (-hs/-p/-ms/-o/-mf/-sf) — falls
nicht, poppt ein klarer Python-Fehler im Log.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root cause der langen Render-Zeiten und /tts_stream 400-Errors:
daswer123 default ist apiManual/api-Mode — Modell wird pro Request
gefetched/reloaded, Streaming unsupported.
Fix in xtts/docker-compose.yml:
command: ['--listen', '-p', '8020', '-t', 'http://0.0.0.0:8020',
'-ms', 'local',
'-o', '/app/output', '-mf', '/app/xtts_models', '-sf', '/voices']
-ms local:
- Modell dauerhaft im GPU-VRAM (~2GB, passt auf RTX 3060 mit 12GB)
- Render startet sofort, kein per-Request-Load mehr
- /tts_stream unterstuetzt → echtes progressive streaming
- time-to-first-audio ~500ms statt 8-11s
xtts/bridge.js:
/tts_stream primary, /tts_to_audio/ als Fallback wenn Stream fehlt.
Robust: wenn User spaeter den Mode wieder umstellt, fallback greift.
Erste Ladung nach dem Wechsel dauert einmalig laenger (Modell ins VRAM
laden). Danach: schnell + streaming.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- XTTS API runs on port 8020 (not 8000)
- Bridge waits up to 5min for model download (30x10s)
- Health check uses / instead of /docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>