diff --git a/bridge/aria_bridge.py b/bridge/aria_bridge.py index 70a18d1..20cc7f9 100644 --- a/bridge/aria_bridge.py +++ b/bridge/aria_bridge.py @@ -457,6 +457,19 @@ class ARIABridge: # Komponenten self.voice_engine = VoiceEngine(VOICES_DIR) + self.tts_enabled = True + # Gespeicherte Voice-Config laden + try: + vc_path = "/shared/config/voice_config.json" + if os.path.exists(vc_path): + with open(vc_path) as f: + vc = json.load(f) + self.voice_engine.default_voice = vc.get("defaultVoice", "ramona") + self.voice_engine.highlight_voice = vc.get("highlightVoice", "thorsten") + self.tts_enabled = vc.get("ttsEnabled", True) + logger.info("Voice-Config geladen: %s", vc) + except Exception as e: + logger.warning("Voice-Config laden fehlgeschlagen: %s", e) self.stt_engine = STTEngine( model_size=self.config.get("WHISPER_MODEL", WHISPER_MODEL), language=self.config.get("WHISPER_LANGUAGE", WHISPER_LANGUAGE), @@ -963,20 +976,38 @@ class ARIABridge: return elif msg_type == "config": - # Konfiguration von App/Diagnostic empfangen + # Konfiguration von App/Diagnostic empfangen + persistent speichern + changed = False if "defaultVoice" in payload: new_voice = payload["defaultVoice"] if new_voice in self.voice_engine.voices: self.voice_engine.default_voice = new_voice logger.info("[rvs] Standard-Stimme gewechselt: %s", new_voice) + changed = True if "highlightVoice" in payload: new_voice = payload["highlightVoice"] if new_voice in self.voice_engine.voices: self.voice_engine.highlight_voice = new_voice logger.info("[rvs] Highlight-Stimme gewechselt: %s", new_voice) + changed = True if "ttsEnabled" in payload: self.tts_enabled = bool(payload["ttsEnabled"]) logger.info("[rvs] TTS %s", "aktiviert" if self.tts_enabled else "deaktiviert") + changed = True + # Persistent speichern in Shared Volume + if changed: + try: + os.makedirs("/shared/config", exist_ok=True) + config_data = { + "defaultVoice": self.voice_engine.default_voice, + "highlightVoice": self.voice_engine.highlight_voice, + "ttsEnabled": getattr(self, "tts_enabled", True), + } + 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) + except Exception as e: + logger.warning("[rvs] Config speichern fehlgeschlagen: %s", e) return text = payload.get("text", "") if text: diff --git a/diagnostic/index.html b/diagnostic/index.html index 44ff380..4190b4d 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -642,6 +642,13 @@ return; } + if (msg.type === 'voice_config') { + document.getElementById('diag-default-voice').value = msg.defaultVoice || 'ramona'; + document.getElementById('diag-highlight-voice').value = msg.highlightVoice || 'thorsten'; + document.getElementById('diag-tts-enabled').checked = msg.ttsEnabled !== false; + return; + } + if (msg.type === 'trigger_list') { const textarea = document.getElementById('highlight-triggers'); textarea.value = (msg.triggers || []).join('\n'); @@ -1587,8 +1594,11 @@ document.querySelectorAll('.main-nav-btn').forEach(b => { if (b.textContent.trim().toLowerCase().includes(tab === 'main' ? 'main' : 'einstellung')) b.classList.add('active'); }); - // Einstellungen: Trigger laden - if (tab === 'settings') loadHighlightTriggers(); + // Einstellungen: Config + Trigger laden + if (tab === 'settings') { + loadHighlightTriggers(); + send({ action: 'get_voice_config' }); + } } // ── Einstellungen: Tool-Berechtigungen ────────────────── diff --git a/diagnostic/server.js b/diagnostic/server.js index 5e3a8c2..8302142 100644 --- a/diagnostic/server.js +++ b/diagnostic/server.js @@ -1127,14 +1127,21 @@ wss.on("connection", (ws) => { if (ws._sshSock) ws._sshSock.write(msg.data); } else if (msg.action === "live_ssh_close") { if (ws._sshSock) { ws._sshSock.end(); ws._sshSock = null; } + } else if (msg.action === "get_voice_config") { + handleGetVoiceConfig(ws); } else if (msg.action === "send_voice_config") { - // Stimmen-Config an Bridge via RVS senden - sendToRVS_raw({ type: "config", payload: { - defaultVoice: msg.defaultVoice, - highlightVoice: msg.highlightVoice, - ttsEnabled: msg.ttsEnabled, - }, timestamp: Date.now() }); - log("info", "server", `Voice-Config gesendet: default=${msg.defaultVoice}, highlight=${msg.highlightVoice}, tts=${msg.ttsEnabled}`); + // Stimmen-Config persistent speichern + an Bridge via RVS senden + const voiceConfig = { + defaultVoice: msg.defaultVoice || "ramona", + highlightVoice: msg.highlightVoice || "thorsten", + ttsEnabled: msg.ttsEnabled !== false, + }; + try { + fs.mkdirSync("/shared/config", { recursive: true }); + fs.writeFileSync("/shared/config/voice_config.json", JSON.stringify(voiceConfig, null, 2)); + } catch {} + sendToRVS_raw({ type: "config", payload: voiceConfig, timestamp: Date.now() }); + log("info", "server", `Voice-Config gespeichert+gesendet: default=${voiceConfig.defaultVoice}, highlight=${voiceConfig.highlightVoice}, tts=${voiceConfig.ttsEnabled}`); } else if (msg.action === "get_triggers") { handleGetTriggers(ws); } else if (msg.action === "save_triggers") { @@ -1269,6 +1276,22 @@ function startLiveSSH(clientWs) { createReq.end(createBody); } +// ── Voice-Config laden ──────────────────────────────── + +function handleGetVoiceConfig(clientWs) { + try { + const configPath = "/shared/config/voice_config.json"; + if (fs.existsSync(configPath)) { + const config = JSON.parse(fs.readFileSync(configPath, "utf-8")); + clientWs.send(JSON.stringify({ type: "voice_config", ...config })); + } else { + clientWs.send(JSON.stringify({ type: "voice_config", defaultVoice: "ramona", highlightVoice: "thorsten", ttsEnabled: true })); + } + } catch (err) { + clientWs.send(JSON.stringify({ type: "voice_config", defaultVoice: "ramona", highlightVoice: "thorsten", ttsEnabled: true })); + } +} + // ── Highlight-Trigger ───────────────────────────────── const TRIGGERS_FILE = "/shared/config/highlight_triggers.json";