Mit ONNX Runtime fuer das Wake-Word kommen Native-Libs fuer alle 4
Architekturen rein (arm64-v8a, armeabi-v7a, x86, x86_64). Das
sprengt sowohl den Gitea-Upload (nginx-Limit) als auch unnoetig die
Auto-Update-Downloads aufs Phone. Per ABI-Split jetzt nur noch
arm64-v8a — deckt jedes Android-Phone seit 2017 ab.
build.sh greift den neuen APK-Pfad (app-arm64-v8a-release.apk),
faellt auf app-release.apk zurueck falls die Splits in build.gradle
deaktiviert werden.
versionCode 606 / versionName 0.0.6.6 (vom Linter mitgehoben).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AudioFocus wird jetzt mit 800ms Verzoegerung freigegeben — wenn ARIA
direkt eine zweite Antwort hinterherschickt oder das Recording ins TTS
uebergeht, wird das Release abgebrochen. Spotify/YouTube haben damit
keine Mikro-Sekunden-Luecke mehr zum Hochkommen waehrend ARIA spricht.
README: neue Sektion zur Wake-Word-Einrichtung mit Picovoice
(7-Tage-Trial, Console-Link, Anleitung fuer eigene Keywords) und
veraltete Wake-Word-Limitation entfernt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Damit man am Logfile schwarz auf weiss sieht ob der Wert wirklich an
die Library geht — falls bei Stefan speed=0.30 ankommt aber Maia
trotzdem schnell, ist's F5-TTS-Verhalten, nicht Pipeline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Android-Eigenheit: bei nested Text-Komponenten muss selectable=true
auch an die Kinder; der Wert auf dem Parent erbt sich nicht zuverlaessig.
Plus: dataDetectorType="all" als Fallback fuer System-Linkifizierung,
falls unsere Regex einen Match verpasst.
suppressHighlighting=false damit Long-Press auf den Link-Texten den
Selection-Mode nicht blockt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stefan's Verwirrung: Ohr-Button + KEIN Porcupine = Direkt-Aufnahme,
nicht passives Lauschen. Wenn er lange wartet, schnappt das Mikro
Hintergrundgeraeusche/Sprache auf, sendet ab, Ohr aus. Sah aus wie
"Wake-Word triggerte" — war aber stinknormales Recording.
Fixes fuer klares Feedback:
- Toast bei jedem State-Wechsel:
* Direkt-Aufnahme (kein Porcupine): "Wake-Word nicht aktiv —
direkte Aufnahme startet (Mikro hoert mit)"
* armed: "Lausche auf X..."
* Wake erkannt: "Wake-Word X erkannt — sprich jetzt"
* endConversation: "Lausche wieder auf X" oder "Mikro aus"
- Ohr-Button-Icon zeigt drei States:
🔇 off
👂 armed (Porcupine lauscht passiv)
🎙️ conversing (aktive Aufnahme laeuft)
- ChatScreen subscribed wakeWordService.onStateChange fuer Live-
Updates des Icons.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bug 2: STT-Result ueberschrieb beide noch unaufgeloeste Audio-Bubbles
mit gleichem Text. Fix: nur die ERSTE matchende Bubble aktualisieren
(findIndex + index-Update statt map). Reihenfolge ist FIFO weil Whisper
sequenziell verarbeitet.
Bug 3: Speed-Param wird nun in jedem Hop geloggt:
- ChatScreen: "[Chat] sende mit voice=X speed=Y"
- aria-bridge: "XTTS-Request gesendet (voice=X, speed=Y.YYx)"
- f5tts-bridge: "F5-TTS: N Satz(e), voice=X, speed=Y.YYx"
Damit kann man im logcat/docker-logs eindeutig sehen wo speed evtl.
verloren geht oder ob die Stimme einfach von Natur aus schnell ist.
Bug 4: VAD-Trigger-Reason mit Schwelle: "VAD NNN ms Stille (Schwelle=NNN ms)".
Plus startRecording loggt jetzt VAD-Stille + MAX-Recording.
Bug 1 (Porcupine): mehr Debug + Toast-Meldungen.
- init failure: err.name/code/stack ins Log
- start() ohne Porcupine: Toast "Access Key in Settings setzen"
- start() Fehler: Toast mit Fehlermeldung
- configure(): Toast wenn init scheitert
- Erfolgreiches arming: Toast "Lausche auf X"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bei kurzen Saetzen (nur ein paar Chunks + sofort final) konnten die
async handlePcmChunk-Calls parallel laufen. Der final-Chunk konnte
native end() aufrufen BEVOR der vorherige Chunk seinen native start()
abgeschlossen hatte. Der Writer-Thread startete dann mit endRequested
bereits true, verarbeitete keine Chunks sauber → Audio ging verloren.
Fix: Wrapper chaint alle Chunk-Calls an eine Promise-Queue:
_pcmChunkQueue = Promise.resolve()
handlePcmChunk → _pcmChunkQueue.then(() => _handlePcmChunkImpl(p))
So werden start/writeChunk/end garantiert in der richtigen Reihenfolge
verarbeitet. Der API-Contract bleibt (gleiches return-Promise).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Die heruntergeladenen Update-APKs (~20-30MB pro Release) landeten in
CachesDirectoryPath und wurden nie geloescht. Bei regelmaessigen
Updates sammelt sich das auf mehrere 100MB an.
Fix: cleanupOldApks() wird gerufen
- einmal beim App-Start (Constructor) — alte APKs sind sowieso nicht
mehr relevant, die aktuelle Version laeuft ja aus dem System
- vor jedem neuen Download — falls jemand zwei Updates in einer
Session zieht
Loescht alle *.apk Dateien im CachesDirectoryPath und loggt die
freigemachte Groesse pro Datei.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Zwei Bugs die zusammen dafuer sorgen dass Worte "verschluckt" werden:
1) play() wurde bei preroll=0 erst beim ersten echten Chunk aufgerufen
— nicht schon nach der Leading-Silence. Dadurch musste AudioTrack
gleichzeitig Startup UND Audio abspielen, die Hardware-Anfahr-Latenz
schluckt die ersten Samples.
Fix: Bei prerollBytes==0 direkt nach dem silence-write play() rufen.
AudioTrack haelt den Play-State und wartet auf mehr Samples — die
naechsten Chunks kommen in den bereits laufenden Stream rein.
2) Nach letztem Chunk ging der Writer via return@Thread in den finally-
Block. Der wartete zwar auf playbackHeadPosition >= totalFrames, aber
Android's Hardware-Pipeline puffert oft noch ein paar Samples nach —
stop() kam, Samples futsch.
Fix: 300ms TRAILING_SILENCE am Ende schreiben. playbackHeadPosition
erreicht echt bis zum Ende der echten Samples bevor die Stille abspielt.
Loop umgeschrieben auf mainLoop-Label (break statt return@Thread) damit
Trailing-Silence garantiert laeuft.
LEADING_SILENCE auf 300ms erhoeht fuer bessere AudioTrack-Warmup-Toleranz.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
F5-TTS ist schnell genug dass der Puffer bei kurzen Saetzen eher
schadet als nuetzt — er verzoegert den play()-Start fuer Sekunden die
dann als Wartezeit auffallen.
Aenderungen:
- audio.ts: TTS_PREROLL_MIN_SEC 1.0 → 0 (Einstellbar in Settings)
- PcmStreamPlayerModule.kt: MIN_PREROLL_SECONDS auf 0.0, Fallback-
Logic respektiert jetzt 0 als gueltigen Wert (vorher hat der
.let { if (it > 0) it else DEFAULT } 0 zu 3.5s umgebogen).
Bei preroll=0 greift der Leading-Silence von 200ms immer noch, d.h.
AudioTrack-Startup bleibt sauber. play() wird dann beim allerersten
echten PCM-Chunk aufgerufen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Neue −0.1 / +0.1 Buttons im Preview-Modal mit aktuellem Wert-Label.
Bei jedem Oeffnen wird der Speed auf 1.0 zurueckgesetzt (bewusst kein
persist — nur zum Experimentieren waehrend das Modal offen ist).
- Range 0.1-5.0, gleiche wie in App-Settings
- Wird beim Play an f5tts-bridge als speed-Param mitgegeben
- Server clampt auf 0.1-5.0, Fallback 1.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TTS_SPEED_MIN 0.5 → 0.1, TTS_SPEED_MAX 2.0 → 5.0.
Bridge-seitige Validierungen (aria_bridge.py + f5tts/bridge.py) mit-
gezogen auf den gleichen Bereich.
Hinweis: Extremwerte (unter 0.5 oder ueber 2.0) koennen bei F5-TTS
verzerrte Ausgaben produzieren — Stefan bekommt die Freiheit zum
Experimentieren.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drei zusammenhaengende Bugs:
1. VAD-Timer feuerte im 200ms setInterval WEITER nachdem die Stille-
Schwelle erreicht war — listeners wurden pro Aufnahme bis zu 5x
getriggert. Parallel laufende stopRecording()-Calls lieferten
audio-recorder-player's nativen Layer OOM / Crash.
Fix: silenceFired-Latch + Timer-Clear SOFORT beim ersten Feuer
(fireSilenceOnce-Helper). Gleiche Logik fuer Max-Dauer + Conv-Window.
2. VoiceButton silence-listener re-registrierte bei jedem isRecording-
Flip (deps [isRecording, onRecordingComplete]). Closure-State war
stale, und bei schnellen flips gabs register/unregister-Races.
Fix: empty deps, state direkt vom audioService via getRecordingState()
lesen. onRecordingComplete via Ref (damit der Callback aktuell bleibt
ohne re-register).
3. handleTap las den Button-State aus React (isRecording), der bei
schnellen Taps stale sein konnte — "erst zweiter Tap geht" Symptom.
Fix: audioService.getRecordingState() als Source-of-Truth, plus
tapBusy-Ref als Anti-Doppel-Tap-Guard waehrend asyncer start/stop.
'processing'-State wird korrekt ignoriert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stefan hat aufgeklaert: Auto-Playback geht nur bei LANGEN Saetzen, bei
kurzen nicht. Das passt zur Pre-Roll-Logik: wenn weniger als pre-roll
Bytes gepuffert werden, soll eigentlich der Fallback in end() greifen,
der nach queue-Timeout play() aufruft.
Neuer Log-Eintrag zeigt ob der Fallback ausgeloest wurde:
"Playback gestartet VOR Pre-Roll (kurzer Text, NNNNB gepuffert)"
Beim naechsten Test mit adb logcat sehen wir direkt:
* Fallback-Log kommt → play() wurde aufgerufen, Problem liegt woanders
* Fallback-Log kommt NICHT → endRequested wird nicht rechtzeitig
erkannt oder Race mit concurrent handlePcmChunk-Calls
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stefan berichtet dass Auto-Playback trotz Closure-Fix nicht greift.
Zwei neue Log-Zeilen die beim naechsten Test direkt zeigen was schief
laeuft:
- ChatScreen: "[Chat] audio-msg canPlay=X (enabled=Y muted=Z)"
- audio.ts: "[Audio] PCM-Stream start: silent=X messageId=Y ..."
Ausreichend um zu unterscheiden:
* canPlay=false trotz Mund-an → ttsMuted bleibt im State haengen
* canPlay=true aber silent=true in audio.ts → Ref-Bug oder race
* silent=false aber nichts hoerbar → native-module oder audio-routing
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
War doppelt gelistet: einmal als erledigter Filter und einmal als
offener "wird als NO angezeigt"-Bug. Der Filter in aria-bridge verwirft
NO_REPLY-Antworten heute still, der Anzeige-Bug ist damit praktisch weg.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Offene Bugs auf 3 reduziert (NO_REPLY-Anzeige, Porcupine-Jarvis,
Porcupine-Crash — die zwei letzten abhaengig vom ADB-Logcat-Test).
App-Features-Backlog auf 2 (History-Race, Background-Audio) weil
Text-Auswahl/Autolink/Speed-Setting/Voice-Preview jetzt fertig sind.
Diagnostic Features-Abschnitt leer → geloescht.
Erledigt-Liste um ~18 Punkte ergaenzt (F5-TTS Pre-processing, deutsches
Fine-Tune, maxPayload-Fix, service_status, config_request, Conversation-
Window, Porcupine, HF-Cache Bind-Mount, cleanup-windows, Mute-Bug,
Zombie-Recording, Autolink, Speed-Setting, Preview-Modal).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Audio-Normalisierung: nie aufgefallen, bei Bedarf zurueck
- F5-TTS Streaming-Inferenz: Upstream-Feature, nicht unseres
- Deepspeed: premature optimization, Render ist durch Pre-Roll
kaschiert schnell genug
- BigVGAN-Support: obsolet seit Vocos + aihpi German Fine-Tune laeuft
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bugs:
- App Mute-/Auto-Playback: onMessage-Closure hielt stale ttsDeviceEnabled/
ttsMuted → Mute wurde ignoriert + AsyncStorage-Load kam nicht durch.
Fix via ttsCanPlayRef (live gespiegelt) statt Closure-Variablen.
- App Zombie-Recording: toggleWakeWord hat die laufende Aufnahme nicht
gestoppt → audioService.recordingState blieb 'recording' → normaler
Aufnahme-Button wirkungslos. Fix: await stopRecording() vor stop().
- Porcupine robuster: BuiltInKeywords-Enum Mapping mit String-Fallback,
errorCallback fuer Runtime-Crashes (state zurueck auf off statt
App-Crash), mehr Logging damit man beim naechsten Issue debuggen kann.
App-Features:
- MessageText Komponente: Text ist durchgehend selektierbar, erkennt
URLs (http/https), E-Mails, Telefonnummern und macht sie anklickbar
(oeffnet Browser / Mail-App / Android-Dialer via Linking).
- TTS-Wiedergabegeschwindigkeit pro Geraet einstellbar (Settings ->
"Sprechgeschwindigkeit", 0.5-2.0 in 0.1-Schritten, Default 1.0).
Wird als speed-Param an die F5-TTS-Bridge durchgereicht.
Bridge-Durchreichen:
- ChatScreen: speed aus AsyncStorage via ttsSpeedRef, an chat/audio/
tts_request mitgeschickt
- aria-bridge: _next_speed_override wie voice_override, an xtts_request
weitergereicht
- f5tts-bridge: speed-Param an F5TTS.infer() durchgereicht
Diagnostic-Feature:
- Voice-Preview-Button (Play-Icon) vor dem Delete-X in der Stimmen-Liste
- Modal mit Textfeld (Default-Beispieltext wird bei jedem Oeffnen neu
gesetzt) und Play-Button
- Server sammelt audio_pcm Frames der Preview-Anfrage, baut WAV,
schickt base64 zurueck, Browser spielt im <audio>-Tag ab
- 60s Timeout-Safety-Net
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bug: User leert "Custom Checkpoint" in Diagnostic, klickt Anwenden, aber
die Bridge behielt den alten Wert weiter (z.B. BigVGAN-Pfad). Ursache:
- Server loeschte den Key bei leerem String aus voice_config.json
- Bridge's update_config sah key absent → "keep current" Semantik
- Resultat: kein Reset, alter Pfad blieb aktiv, NaN-Output blieb
Fix auf beiden Seiten:
- diagnostic/server.js: Keys werden immer mit dem Wert gesetzt (auch "")
statt geloescht. "" landet jetzt explizit in der config.json.
- f5tts/bridge.py: update_config unterscheidet jetzt:
* key fehlt in payload → current behalten (unveraendert)
* key da + leer → RESET auf DEFAULT_F5TTS_* (User-Wunsch)
* key da + Wert → neuen Wert nehmen
Damit kann der User in Diagnostic ein Feld leeren + Anwenden und die
Bridge schaltet wirklich auf Hard-Default zurueck.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f5tts/bridge.py: das hardcoded model="small" in request_transcription war
ein Fehler — whisper-bridge hat dadurch stumm zwischen Modellen geswappt.
Wenn User large-v3 in Diagnostic eingestellt hatte:
- f5tts Voice-Transkribierung triggerte Swap zu "small" (+~500MB Laden)
- Danach aria-bridge schickte naechsten stt_request mit large-v3
(+~3GB Laden weil small jetzt im RAM war)
Doppelter Load, unnoetiger Traffic.
Fix:
- f5tts: kein model mehr im payload, whisper-bridge entscheidet
- whisper: wenn kein payload.model UND bereits ein Modell geladen →
das behalten. Nur wenn gar nichts da ist fallback auf WHISPER_MODEL
env default.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Die BigVGAN-Variante des aihpi F5-TTS Checkpoints ist nicht einfach ein
"optional besser" Fallback — sie ist mit dem Default-Vocos-Vocoder den die
f5-tts Library laedt inkompatibel. Output wird NaN, App bleibt stumm.
Stefan hat das probiert, App stumm, 10 Minuten Debugging. README war zu
locker formuliert ("Meist hoehere Quali") — jetzt klar als "funktioniert
AKTUELL NICHT" gekennzeichnet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
F5-TTS generiert gelegentlich NaN/Inf samples — ohne sanitize lief der
int16-Cast in undefined behavior (RuntimeWarning + kaputter Sound in den
entsprechenden Stellen). Jetzt: nan_to_num vor clip, plus Warnung wie
viele samples betroffen waren.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Konfig-Tabelle mit den konkreten Diagnostic-Werten fuer das deutsche
Fine-Tune von aihpi/F5-TTS-German — Modell-Architektur, hf:// Pfade,
empfohlene cfg_strength / nfe_step. Plus Hinweis auf die BigVGAN-
Variante als Alternative.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
_resolve_hf_path wandelt hf://user/repo/path → lokaler Download via
huggingface_hub.hf_hub_download. So kann man in Diagnostic einfach die
HF-Pfade fuer custom Modelle reinschreiben, ohne erst manuell zu
downloaden + zu mounten.
Format: hf://aihpi/F5-TTS-German/F5TTS_Base/model_365000.safetensors
hf://aihpi/F5-TTS-German/vocab.txt
Diagnostic UI: Placeholders + Labels angepasst mit Beispiel-HF-Pfaden
und Hinweis dass fuer Fine-Tunes "F5TTS_Base" statt "F5TTS_v1_Base"
als Architektur-Name gesetzt werden muss.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
F5-TTS reagiert empfindlich auf leise / verrauschte / zerhackte
Referenzen — wir haben bisher nur auf 24kHz mono + 10s geclipped.
Jetzt zusaetzlich:
- silenceremove am Anfang (bis Speech einsetzt, <-50dB)
- silenceremove am Ende (0.5s Stille nach letzter Speech = Cutoff)
- loudnorm -16 LUFS (EBU R128) fuer konsistente Amplitude
Damit sieht das Modell saubere, konstant laute Referenz-Audios statt
kaputter Clips mit Ausklang oder leiser Aufnahme. Besonders bei Deutsch
(wo F5TTS_v1_Base schwach ist) hilft jede Input-Konsistenz der Quali.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
F5-TTS hat ein Hard-Limit von 12s fuer das Referenz-Audio — laengere
WAVs werden intern abgeschnitten, aber unser ref_text war das komplette
Transkript. Text und Audio wurden dadurch unaligned, Render-Qualitaet
leidet und der initial Warmup-Render dauerte 57s statt 5s.
Fix:
- normalize_ref_wav(max_seconds=10): ffmpeg schneidet auf 10s + 24kHz
mono, gibt was_modified zurueck damit Caller den txt invalidieren kann
- handle_voice_upload: clippt VOR der Transkription, Whisper sieht also
nur die 10s → txt passt garantiert zum Audio
- _do_tts: checkt vor jedem Render die WAV-Dauer. WAVs > 10.5s werden
geclippt, .txt geloescht → on-the-fly Neu-Transkription beim Render
Bestehende kaputte Voices (wie MAIA mit 600+ Worten txt zu einem 20s
Audio) werden beim naechsten Render automatisch gefixt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Beim user kommt nach 'RVS verbunden' nichts mehr — Modell-Download
startet nicht, banner aktualisiert sich nicht. Vermutung: alter Code
laeuft noch (kein neu gebauter Container) ODER der Initial-Handshake
crashed silent (asyncio.create_task ohne await schluckt Exceptions).
- whisper + f5tts: Initial-Handshake mit logger.info Zeilen, damit
man sieht ob er ueberhaupt ausgefuehrt wird
- f5tts: zusaetzlich exception-Catch + fehler-broadcast falls der
Modell-Load crashed
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>
aria-bridge horcht jetzt auf service_status fuer den Service 'whisper'.
Solange whisper-bridge im 'loading' steckt (Erst-Download large-v3 kann
1-2 Min dauern), gilt fuer stt_request ein Timeout von 300s statt 45s.
Sobald 'ready', zurueck auf 45s — reicht selbst fuer lange Audios.
Symptom vorher: Beim ersten Sprechen nach Container-Restart hat aria-
bridge nach 45s aufgegeben und lokal gefallback waehrend whisper-bridge
noch fleissig den Download laufen hatte. Damit wurde der Sinn der
Auslagerung kaputt gemacht.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Symptom: aria-whisper-bridge bekam beim ersten internen stt_request
(via voice_upload mit WAV als base64, ~2.4MB) den Frame zu Gesicht,
default ws-max ist 1MB → mit Close-Code 1009 abgewiesen → Verbindung
tot → naechster stt_request lief in Timeout → lokales Fallback.
Fixes:
- whisper-bridge: max_size=50*1024*1024 in websockets.connect()
(gleicher Wert wie f5tts-bridge schon hat)
- RVS-Server: maxPayload=50*1024*1024 in WebSocketServer-Optionen,
damit der Server die Frames nicht selbst auf 1MB cappt bevor er
sie an die Bridge weiterleitet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vorher: Container-Start lud erst 'small' (env default), dann nochmal
das in Diagnostic konfigurierte Modell (z.B. large-v3) wenn die
config-Broadcast vom aria-bridge ankam. Doppelter Download, doppelte
Wartezeit, doppelter VRAM-Peak.
Jetzt:
- Initial wird NICHTS geladen
- aria-bridge sendet die persistierte voice_config.json kurz nach
RVS-Connect → whisper-bridge sieht den richtigen Modellnamen
- config-Handler erkennt: noch nichts geladen ODER Wechsel
→ loading-Broadcast → ensure_loaded → ready-Broadcast
- stt_request-Handler: gleicher Status-Broadcast falls Race-Condition
(Spracheingabe in den ersten 1-2s nach Container-Start)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>