feat: F5-TTS Tuning ueber Diagnostic statt .env
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>
This commit is contained in:
+53
-5
@@ -496,6 +496,7 @@ class ARIABridge:
|
||||
# Komponenten (TTS: immer XTTS remote, Piper wurde entfernt)
|
||||
self.tts_enabled = True
|
||||
self.xtts_voice = ""
|
||||
self._f5tts_config: dict = {}
|
||||
vc: dict = {}
|
||||
# Gespeicherte Voice-Config laden
|
||||
try:
|
||||
@@ -505,7 +506,16 @@ class ARIABridge:
|
||||
vc = json.load(f)
|
||||
self.tts_enabled = vc.get("ttsEnabled", True)
|
||||
self.xtts_voice = vc.get("xttsVoice", "")
|
||||
logger.info("Voice-Config geladen: tts=%s voice=%s", self.tts_enabled, self.xtts_voice or "default")
|
||||
# F5-TTS-Felder aufsammeln (werden spaeter via RVS rebroadcastet,
|
||||
# damit die f5tts-bridge auf der Gamebox die Settings auch nach
|
||||
# Restart wiederbekommt — sonst stuende sie auf Hard-Defaults)
|
||||
for k in ("f5ttsModel", "f5ttsCkptFile", "f5ttsVocabFile",
|
||||
"f5ttsCfgStrength", "f5ttsNfeStep"):
|
||||
if k in vc:
|
||||
self._f5tts_config[k] = vc[k]
|
||||
logger.info("Voice-Config geladen: tts=%s voice=%s f5tts=%s",
|
||||
self.tts_enabled, self.xtts_voice or "default",
|
||||
self._f5tts_config or "defaults")
|
||||
except Exception as e:
|
||||
logger.warning("Voice-Config laden fehlgeschlagen: %s", e)
|
||||
# Whisper-Modell: Config hat Vorrang, dann env/Default (medium)
|
||||
@@ -963,6 +973,29 @@ class ARIABridge:
|
||||
except Exception as e:
|
||||
logger.debug("[mode] Broadcast fehlgeschlagen: %s", e)
|
||||
|
||||
async def _broadcast_persisted_config(self) -> None:
|
||||
"""Broadcastet die aktuelle voice_config.json einmalig nach RVS-Connect.
|
||||
|
||||
Damit bekommen frisch verbundene Bridges (insbesondere die f5tts-bridge
|
||||
auf der Gamebox nach Container-Restart) die zuletzt in Diagnostic
|
||||
gewaehlten Settings — ohne dass der User in Diagnostic was klicken muss.
|
||||
"""
|
||||
try:
|
||||
payload = {
|
||||
"ttsEnabled": getattr(self, "tts_enabled", True),
|
||||
"xttsVoice": getattr(self, "xtts_voice", ""),
|
||||
"whisperModel": self.stt_engine.model_size,
|
||||
}
|
||||
payload.update(getattr(self, "_f5tts_config", {}) or {})
|
||||
await self._send_to_rvs({
|
||||
"type": "config",
|
||||
"payload": payload,
|
||||
"timestamp": int(asyncio.get_event_loop().time() * 1000),
|
||||
})
|
||||
logger.info("[rvs] Persistierte Config broadcastet: %s", payload)
|
||||
except Exception as e:
|
||||
logger.debug("[rvs] Config-Broadcast fehlgeschlagen: %s", e)
|
||||
|
||||
def _fetch_active_session(self) -> None:
|
||||
"""Holt die aktive Session vom Diagnostic-Endpoint."""
|
||||
try:
|
||||
@@ -1032,6 +1065,12 @@ class ARIABridge:
|
||||
# ihren UI-State sofort syncen koennen
|
||||
await self._broadcast_current_mode()
|
||||
|
||||
# Persistierte Voice-Config broadcasten — die f5tts-bridge auf
|
||||
# der Gamebox bekommt damit nach Restart die zuletzt in
|
||||
# Diagnostic gewaehlten Settings wieder (sonst stuende sie auf
|
||||
# ihren Hard-Defaults).
|
||||
asyncio.create_task(self._broadcast_persisted_config())
|
||||
|
||||
# Heartbeat senden (RVS erwartet Ping alle 30s)
|
||||
heartbeat_task = asyncio.create_task(self._rvs_heartbeat())
|
||||
|
||||
@@ -1195,7 +1234,10 @@ class ARIABridge:
|
||||
return
|
||||
|
||||
elif msg_type == "config":
|
||||
# Konfiguration von App/Diagnostic empfangen + persistent speichern
|
||||
# Konfiguration von App/Diagnostic empfangen + persistent speichern.
|
||||
# Felder die nicht direkt zur aria-bridge gehoeren (f5tts*) werden
|
||||
# nur persistiert; die f5tts-bridge auf der Gamebox empfaengt den
|
||||
# gleichen RVS-Broadcast und reagiert selber.
|
||||
changed = False
|
||||
if "ttsEnabled" in payload:
|
||||
self.tts_enabled = bool(payload["ttsEnabled"])
|
||||
@@ -1209,14 +1251,19 @@ class ARIABridge:
|
||||
new_model = payload["whisperModel"]
|
||||
allowed = {"tiny", "base", "small", "medium", "large-v3"}
|
||||
if new_model in allowed and new_model != self.stt_engine.model_size:
|
||||
# Merken und mitschicken an whisper-bridge (Gamebox).
|
||||
# Lokales Modell wird NICHT geladen — nur das Fallback braucht's,
|
||||
# und das passiert erst on-demand wenn Remote nicht antwortet.
|
||||
logger.info("[rvs] Whisper-Modell → %s (nur Config; Modell laedt Gamebox)",
|
||||
new_model)
|
||||
self.stt_engine.model_size = new_model
|
||||
self.stt_engine.model = None
|
||||
changed = True
|
||||
# F5-TTS-Felder: einfach persistieren, f5tts-bridge applied selber.
|
||||
for k in ("f5ttsModel", "f5ttsCkptFile", "f5ttsVocabFile",
|
||||
"f5ttsCfgStrength", "f5ttsNfeStep"):
|
||||
if k in payload:
|
||||
if not hasattr(self, "_f5tts_config"):
|
||||
self._f5tts_config = {}
|
||||
self._f5tts_config[k] = payload[k]
|
||||
changed = True
|
||||
# Persistent speichern in Shared Volume
|
||||
if changed:
|
||||
try:
|
||||
@@ -1226,6 +1273,7 @@ class ARIABridge:
|
||||
"xttsVoice": getattr(self, "xtts_voice", ""),
|
||||
"whisperModel": self.stt_engine.model_size,
|
||||
}
|
||||
config_data.update(getattr(self, "_f5tts_config", {}))
|
||||
with open("/shared/config/voice_config.json", "w") as f:
|
||||
json.dump(config_data, f, indent=2)
|
||||
logger.info("[rvs] Voice-Config gespeichert: %s", config_data)
|
||||
|
||||
Reference in New Issue
Block a user