diff --git a/diagnostic/server.js b/diagnostic/server.js index ffd6b17..c3935a3 100644 --- a/diagnostic/server.js +++ b/diagnostic/server.js @@ -1439,19 +1439,14 @@ wss.on("connection", (ws) => { xttsVoice: msg.xttsVoice || "", }; if (msg.whisperModel !== undefined) voiceConfig.whisperModel = msg.whisperModel; - // F5-TTS Tuning-Felder — leere Strings entfernen damit der Default greift - if (msg.f5ttsModel !== undefined) { - if (msg.f5ttsModel) voiceConfig.f5ttsModel = msg.f5ttsModel; - else delete voiceConfig.f5ttsModel; - } - if (msg.f5ttsCkptFile !== undefined) { - if (msg.f5ttsCkptFile) voiceConfig.f5ttsCkptFile = msg.f5ttsCkptFile; - else delete voiceConfig.f5ttsCkptFile; - } - if (msg.f5ttsVocabFile !== undefined) { - if (msg.f5ttsVocabFile) voiceConfig.f5ttsVocabFile = msg.f5ttsVocabFile; - else delete voiceConfig.f5ttsVocabFile; - } + // F5-TTS Tuning-Felder — immer mit dem vom User gesendeten Wert setzen, + // auch leeren String. Leer = "reset auf Hard-Default". Sonst merkt die + // Bridge nicht dass der User den Wert loeschen wollte (absent key war + // vorher 'keep current' semantik → BigVGAN blieb drin obwohl User + // leer eingetragen hatte). + if (msg.f5ttsModel !== undefined) voiceConfig.f5ttsModel = msg.f5ttsModel || ""; + if (msg.f5ttsCkptFile !== undefined) voiceConfig.f5ttsCkptFile = msg.f5ttsCkptFile || ""; + if (msg.f5ttsVocabFile !== undefined) voiceConfig.f5ttsVocabFile = msg.f5ttsVocabFile || ""; if (msg.f5ttsCfgStrength !== undefined && !isNaN(msg.f5ttsCfgStrength)) { voiceConfig.f5ttsCfgStrength = msg.f5ttsCfgStrength; } diff --git a/xtts/f5tts/bridge.py b/xtts/f5tts/bridge.py index 3553e68..f9e1ae1 100644 --- a/xtts/f5tts/bridge.py +++ b/xtts/f5tts/bridge.py @@ -175,10 +175,31 @@ class F5Runner: async def update_config(self, payload: dict) -> None: """Liest f5tts*-Felder aus einem config-Broadcast. - Bei Modell-relevantem Wechsel wird neu geladen.""" - new_model = (payload.get("f5ttsModel") or "").strip() or self.model_id - new_ckpt = payload.get("f5ttsCkptFile", self.ckpt_file) or "" - new_vocab = payload.get("f5ttsVocabFile", self.vocab_file) or "" + Bei Modell-relevantem Wechsel wird neu geladen. + + Semantik: + - key fehlt in payload → aktuellen Wert behalten + - key da, nicht-leerer str → diesen Wert nehmen + - key da, leerer string → RESET auf Hard-Default (User hat Feld + in Diagnostic geleert und Apply geklickt) + """ + if "f5ttsModel" in payload: + v = (payload.get("f5ttsModel") or "").strip() + new_model = v if v else DEFAULT_F5TTS_MODEL + else: + new_model = self.model_id + + if "f5ttsCkptFile" in payload: + v = payload.get("f5ttsCkptFile") or "" + new_ckpt = v.strip() if isinstance(v, str) else "" + else: + new_ckpt = self.ckpt_file + + if "f5ttsVocabFile" in payload: + v = payload.get("f5ttsVocabFile") or "" + new_vocab = v.strip() if isinstance(v, str) else "" + else: + new_vocab = self.vocab_file try: new_cfg = float(payload.get("f5ttsCfgStrength", self.cfg_strength)) except (TypeError, ValueError):