App-Pendant zum Diagnostic-Banner. Wenn die Gamebox-Bridges (F5-TTS /
Whisper) ihren Lade-Status broadcasten, zeigt die App oben unter der
Verbindungs-Statusleiste ein farbiges Banner:
Gelb = irgendwas laedt (NICHT wegtippbar)
Gruen = alles bereit (tippbar zum Schliessen)
Rot = Fehler
Banner aggregiert beide Services in einer Kachel. Dismiss-State wird
zurueckgesetzt sobald irgendein Service wieder in 'loading' geht
(z.B. Modell-Wechsel via Diagnostic).
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>
@picovoice/porcupine-react-native deklariert minSdkVersion 24, dadurch
schlug der Manifest-Merger fehl wenn die App weiter auf 23 stand.
Android 7.0 ist eh das pragmatische Minimum (Geraete <7.0 sind <1% Markt).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.0.6 war geraten und gibt's nicht im npm Registry. Aktuelle stabile 3.x
ist 3.0.5; 4.0.0 hat Breaking Changes. Beide Picovoice-Packages auf
exakte Version gepinnt damit keine Auto-Bumps fies werden.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cleanup-windows.ps1:
- Defensive Set-ExecutionPolicy Bypass am Anfang
- Self-Elevation: wenn nicht als Admin gestartet, relauncht das Script
sich selbst als Admin mit -ExecutionPolicy Bypass + Original-Args.
User muss nur einmal UAC bestaetigen, kein extra Befehl mehr noetig.
cleanup-windows.bat:
- Wrapper der powershell.exe mit -ExecutionPolicy Bypass aufruft.
- Funktioniert auch wenn Windows die .ps1 direkt blockt (z.B. unsignierte
Scripts global gesperrt).
- Aufruf: cleanup-windows.bat stefan [-SkipPrune] [-PruneOnly]
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ein Script das auf der Gamebox (Windows + Docker Desktop + WSL2) alle
.vhdx Files findet und via diskpart compactet. Gibt den Speicherplatz
zurueck den man IN den Distros/Containern geloescht hat aber von der
VHDX bisher nicht freigegeben wurde.
Nutzung (PowerShell als ADMIN):
.\cleanup-windows.ps1 stefan
.\cleanup-windows.ps1 -User stefan -SkipPrune # nur compacten
.\cleanup-windows.ps1 -User stefan -PruneOnly # nur prune
Default-Flow:
1. docker system prune -a --volumes -f + builder prune
2. wsl --shutdown
3. Alle gefundenen ext4.vhdx (Docker Desktop + WSL-Distros) compacten
via diskpart 'compact vdisk' (kein Hyper-V noetig)
Zeigt fuer jedes File "vor → nach (gespart X GB)" und am Ende eine
Gesamt-Summary.
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>
Bug-Root: voice_upload schrieb "Das ist ein Referenz Audio." als Platzhalter
wenn die whisper-bridge nicht erreichbar war. F5-TTS bekam dann diesen Text
als Sprach-Anker, sah aber im WAV ganz andere Worte → verwirrtes Modell,
halluziniert in beliebiger Sprache (z.B. Spanisch).
Fixes:
- handle_voice_upload: schreibt KEINE Platzhalter-.txt mehr. Bei Failure
bleibt die .txt weg → naechste TTS-Nutzung zieht via on-the-fly retry
nach.
- _do_tts: Legacy-Platzhalter wird beim Render erkannt und geloescht,
Transkription on-the-fly neu angezogen. Bestehende kaputte voices
reparieren sich automatisch beim ersten Render.
UI-Aufraeumung: F5-TTS hat keine "Standard"-Stimme — der Eintrag ist raus
in App SettingsScreen + Diagnostic. Diagnostic-Dropdown hat jetzt einen
disabled-Hinweis "(keine Stimme gewaehlt)".
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>
Der Gespraechsmodus war bisher ein Endless-Loop: Mikro hat sich nach
jeder ARIA-Antwort wieder geoeffnet bis MAX_RECORDING_MS, danach Speech-
Gate verworfen und neu starten. Das Ohr blieb ewig an.
Neue Logik:
audio.ts: startRecording(autoStop, noSpeechTimeoutMs?) — wenn der User
innerhalb des Timeouts nicht anfaengt zu sprechen, wird Stille
gemeldet → stopRecording → Speech-Gate verwirft → result=null.
wakeword.ts: drei States off/armed/conversing. start() geht direkt in
'conversing' (kein Wake-Word verfuegbar; Stub fuer spaetere Porcupine-
Integration). endConversation() bei No-Speech.
ChatScreen: Aufnahme bekommt das Window aus AsyncStorage durchgereicht.
Bei null-Result → endConversation, UI-State synchron.
Settings: neuer +/- Block "Konversations-Fenster" 3-20s (Default 8).
Mit dem Stub ist die Architektur bereit fuer Porcupine: dann geht
endConversation auf 'armed' statt 'off' und der Wake-Word-Detector
laeuft passiv weiter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Neuer +/- Block in SettingsScreen → Spracheingabe → "Stille-Toleranz",
1.0-8.0s, Default 2.8s. Wert in AsyncStorage (aria_vad_silence_sec).
audio.ts liest den Wert beim Aufnahme-Start und nutzt ihn fuer den
VAD-Auto-Stop-Schwellwert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AudioFocus.requestDuck nutzt jetzt AUDIOFOCUS_GAIN_TRANSIENT (statt
TRANSIENT_MAY_DUCK) — Spotify/YouTube pausieren komplett solange ARIA
spricht und kommen nicht mitten drin wieder hoch.
PcmStreamPlayer.end() resolved jetzt erst wenn der native Writer-Thread
wirklich fertig ist (alle Samples aus dem Pre-Roll-Puffer ausgespielt).
audio.ts wartet entsprechend, bevor AudioFocus.release() gerufen wird —
behebt das "Musik dreht hoch waehrend Antwort noch laeuft"-Problem.
Mic-Aufnahme: VAD_SILENCE_DURATION_MS 1800 → 2800ms (mehr Toleranz fuer
Sprechpausen), MAX_RECORDING_MS 30s → 120s (laengere Erklaerungen
moeglich, Notbremse bleibt).
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>
XTTS-Bridge:
- empfaengt neuen voice_preload Type, rendert stumm "ja." fuer die Stimme
via TTS-Queue (damit kein Konflikt mit echtem TTS)
- horcht zusaetzlich auf config-Broadcasts: wenn Diagnostic global die
Stimme wechselt, wird auto-preloaded
- broadcastet voice_ready mit Dauer (loadMs) oder error
RVS: voice_preload + voice_ready zur ALLOWED_TYPES-Liste.
App (SettingsScreen): beim Wechsel senden wir voice_preload, zeigen einen
Spinner in der Voice-Row und einen Toast mit "Stimme X bereit (Ns)".
App (ChatScreen): Toast auch hier — falls User gerade nicht in Settings ist.
Diagnostic (server+UI): voice_ready wird an Browser durchgereicht, ein
Status-Text unter dem Voice-Dropdown zeigt "wird geladen" → "bereit".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
XTTS-Bridge: im daswer123 local-Mode erwartet der Server speaker_wav als
Basename (z.B. "Maia"), nicht als Pfad. Wir haben bisher "/voices/Maia.wav"
geschickt, was der Server stumm verwirft und Default nimmt. Jetzt: speaker
name pur senden + Warnlog wenn File fehlt.
App: ChatScreen + SettingsScreen horchen auf type "config" vom RVS —
wenn in Diagnostic die globale XTTS-Voice gewechselt wird, werden alle
Apps auf den neuen Wert zurueckgesetzt (wie vom User gewuenscht).
Lokale App-Wahl bleibt sonst intakt und gewinnt pro Request.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nach der expliziten _UNIT_WORDS-Liste greift eine Fallback-Regel:
alle verbleibenden 2-5-Zeichen-Grossbuchstaben-Woerter werden
buchstabiert. XTTS → X T T S, USB → U S B, DNS → D N S, JSON → J S O N.
Spezielle Faelle (WLAN, NATO — als Wort gesprochen) koennen bei
Bedarf in _UNIT_WORDS explizit ueberschrieben werden.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Kotlin start() nimmt jetzt prerollSeconds als dritten Parameter
(1.0-6.0s geclampt, Fallback 3.5s bei ungueltigem Wert)
- audio.ts liest Wert aus AsyncStorage vor jedem Stream-Start,
exportiert Default/Min/Max/Key als Konstanten
- SettingsScreen: +/- Buttons direkt unter dem TTS-Toggle,
Default auf 3.5s (von 2.5s) angehoben
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
XTTS daswer123 hat am Anfang jedes Renders Warmup-Artefakte — die
ersten autoregressiv generierten Tokens haben wenig Kontext und klingen
verzerrt. Ein 120ms Linear-Fade-In auf den ersten ausgehenden PCM-Chunk
blendet das sanft auf und versteckt die Glitches, ohne dass das echte
Audio danach leiser klingt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
XTTS daswer123 erzeugt an Chunk-Grenzen oft Glitches in den Worten
die ueber die Grenze gehen. 100 → 250 = weniger Grenzen pro Satz =
sauberere Sprachausgabe. Erste-Audio-Latenz steigt um ein paar Sekunden,
was aber OK ist seit die App Pre-Roll gepuffert ist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- aria_bridge clean_text_for_tts: "0.1" / "0,5" / "1,25" wird jetzt als
"null komma eins" / "null komma fuenf" / "eins komma zwei fuenf"
ausgeschrieben. Lookahead verhindert Match auf IP-artige Strings.
- PcmStreamPlayer: 200ms Stille am Stream-Anfang, damit AudioTrack
sauber anfaehrt und die ersten Worte nicht verschluckt werden.
(XTTS-Warmup + play()-Startup-Latenz)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AudioTrack.stop() + release() direkt nach dem letzten write() killt die
letzten Sekunden Audio — die Samples sind zwar im Buffer, aber noch
nicht durch die Hardware rausgespielt. Deshalb brach die Sprachausgabe
mitten im Satz ab (z.B. bei "diesmal").
Fix: Writer-Thread wartet im finally-Block bis playbackHeadPosition die
Anzahl geschriebener Frames erreicht, dann erst stop()/release().
Safety: 2s Stall-Detection, falls AudioTrack haengen bleibt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User-Diagnose: Erneutes Abspielen aus Cache funktioniert komplett, aber
Live-Stream bricht ab. Bedeutet: PCM kommt an, Cache ist okay — Problem
ist Buffer-Underrun im AudioTrack wenn XTTS (RTF 1.48 auf RTX 3060)
langsamer rendert als Echtzeit-Playback konsumiert.
Fix: AudioTrack.play() wird NICHT mehr sofort beim start() aufgerufen.
Stattdessen:
- start() baut AudioTrack, Writer-Thread startet, spielt aber noch nicht
- writeChunk() fuellt queue, Writer schreibt in AudioTrack-internen Buffer
(blocked wenn der voll ist)
- Sobald bytesBuffered >= 2.5s Audio im Buffer: play() aufrufen
- Falls end() kommt bevor Pre-Roll erreicht (kurze Texte): trotzdem play()
Das gibt dem Stream Zeit Vorrat aufzubauen. XTTS kann dann pausieren
zwischen Text-Chunks ohne dass Playback stottert.
Pre-Roll 2.5s reicht fuer typische Render-Pausen zwischen Chunks.
Buffer groesse = 2x Pre-Roll damit wir auch extrem bursty Delivery
puffern koennen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mit RTF 1.48 (RTX 3060) rechnet XTTS fuer 200 chars ca. 6s bis erster
PCM-Chunk rauskommt — User wartet nach ARIA-Antwort 6s auf Sprachausgabe.
stream_chunk_size=100: Erster Chunk in ~3s bereit, reduziert
Initial-Latenz um ~50%. 100 chars sind auch noch gross genug dass
der AudioTrack-Buffer (128KB ≈ 2.7s Audio) zwischen Render-Chunks
nicht leerlaeuft → kein mid-sentence Abbruch wie bei 40.
Falls bei bestimmten Texten doch Gaps: stream_chunk_size zurueck auf
150, oder pre-roll im Android PcmStreamPlayer einbauen (nur starten
wenn X ms gepuffert sind).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bei stream_chunk_size=40 teilte XTTS Text in ~40-char Batches.
Zwischen Batches pausiert XTTS (RTF 1.48 auf RTX 3060 → langsamer
als Realtime-Wiedergabe). AudioTrack-Buffer lief leer, Track
stoppte, nachkommender PCM kam zu spaet → Audio bricht mid-sentence
ab (User-Bug: bei 73-char Text Abbruch nach Wort 'diesmal' was genau
an der 40-char Grenze lag).
stream_chunk_size=200:
- Kurze Saetze (<200 chars) komplett in einem Render → kein Abbruch
- Laengere Texte: groessere Chunks, laenger Audio pro Chunk als
Render-Pause → Buffer bleibt gefuellt
- Kompromiss: first-audio-latency etwas hoeher, aber keine Abbrueche
Wenn spaeter Audio-Abbrueche bei langen Texten: stream_chunk_size
noch groesser setzen ODER einen "pre-roll" Buffer in der App.
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-Server (daswer123) im API-Modus antwortet auf /tts_stream mit:
HTTP 400: "HTTP Streaming is only supported for local models"
Das Feature braucht MODE=local in der XTTS-Config (Modell direkt im
Server-Prozess). Userbetreibt im Remote-Modus → kein Streaming.
Der try /tts_stream + fallback /tts_to_audio Ansatz war reine Ver-
schwendung: jeder Request wartete 6ms auf 400, bevor der Fallback
griff. Jetzt geht's direkt an /tts_to_audio/.
Kein echtes Streaming, aber:
- Queue sorgt fuer sequentielle Verarbeitung (kein Overlap mehr)
- 32x AudioTrack-Buffer faengt den bursty Response ab
- aria-bridge spiegelt audio_pcm nicht mehr (kein Doppel-Audio)
Wenn User spaeter /tts_stream haben will:
XTTS-Server mit MODE=local oder --streaming-mode starten,
dann kann man /tts_stream als primary einfuehren.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
XTTS-Server (daswer123) markiert speaker_wav als required Pydantic-Feld.
Mein 'if (speakerWav) qs.set(...)' hat den Key bei default-voice
weggelassen → HTTP 422 'Field required, input: null' → Fallback auf
/tts_to_audio/ hat gegriffen, aber Streaming nie gefunden.
Log-Beweis vom User:
XTTS /tts_stream 422: {"detail":[{"type":"missing","loc":["query",
"speaker_wav"],"msg":"Field required","input":null}]}
Fix: Key immer setzen, leerer String bei default-voice. POST-Variante
(/tts_to_audio/ JSON-Body) hat das auch so akzeptiert — GET-Query nun
gleiches Verhalten.
Ab jetzt sollte /tts_stream endlich greifen und echte Streaming-Latenz
(~300-500ms) zeigen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Problem: /tts_stream hat bei User nicht funktioniert → keine
Sprachausgabe mehr. Server hatte vorher 405 fuer POST geantwortet,
meine Umstellung auf GET scheint aber einen anderen Fehler zu
produzieren der nicht geloggt wurde.
Fix:
- streamXTTSAsPCM() = /tts_stream (GET, Streaming) mit ausfuehrlichem
Error-Logging bei non-200 Response
- streamXTTSBatch() = /tts_to_audio/ (POST, Batch) als Fallback
- handleTTSRequest versucht Stream zuerst, bei Exception Fallback
auf Batch — so gibt's IMMER Audio, auch wenn /tts_stream kaputt ist
- Log zeigt welcher Pfad benutzt wurde
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>