wait for finish tts

This commit is contained in:
duffyduck 2025-12-28 17:11:13 +01:00
parent 892639d626
commit b830388d9f
1 changed files with 39 additions and 27 deletions

View File

@ -136,6 +136,12 @@ class ClaudesEyesAudioBridge:
self._speaking = threading.Event()
self._speaking.clear() # Anfangs nicht am Sprechen
# Awaiting-TTS-Flag: Wird gesetzt wenn Nachricht gesendet wurde
# und wir auf TTS warten. Erst clearen wenn TTS komplett fertig ist.
# So wartet Heartbeat auch während gTTS das Audio generiert.
self._awaiting_tts = threading.Event()
self._awaiting_tts.clear() # Anfangs nicht wartend
# Mute-Flag: Wenn True, ignoriert STT alle Eingaben
# Startet gemutet um ungewollte Aufnahmen zu vermeiden
self._muted = True
@ -642,19 +648,21 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
break
# ════════════════════════════════════════════════════════════════
# WICHTIG: Nach dem Claude fertig getippt hat, warte kurz damit
# TTS die Nachricht finden und mit Sprechen beginnen kann.
# Dann warte bis TTS fertig ist.
# WICHTIG: Warte bis TTS komplett fertig ist!
# _awaiting_tts wurde beim Senden gesetzt und wird erst
# gelöscht wenn TTS die Nachricht vorgelesen hat (oder wenn
# es nichts vorzulesen gab).
# ════════════════════════════════════════════════════════════════
logger.debug("Claude fertig mit Tippen, warte auf TTS...")
time.sleep(1.5) # Kurz warten bis TTS die Nachricht findet
if self._awaiting_tts.is_set():
logger.info("Heartbeat: Warte auf TTS (Nachricht wurde gesendet)...")
# Jetzt warte bis TTS fertig ist mit Sprechen
if self._speaking.is_set():
logger.debug("Claude spricht (TTS), warte bis fertig...")
while self.running and self._speaking.is_set():
# Warte bis TTS komplett fertig ist (kein Timeout!)
while self.running and self._awaiting_tts.is_set():
if self._speaking.is_set():
logger.debug("Heartbeat: Claude spricht gerade...")
time.sleep(0.5)
logger.debug("Claude fertig mit Sprechen")
logger.info("Heartbeat: TTS fertig, fahre fort")
if not self.running:
break
@ -708,6 +716,10 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
stefan_message = f"Stefan sagt: {stefan_text}"
console.print(f"[green]🎤 Stefan:[/green] {stefan_text[:100]}{'...' if len(stefan_text) > 100 else ''}")
# WICHTIG: Signalisiere dass wir auf TTS warten
self._awaiting_tts.set()
logger.debug("_awaiting_tts gesetzt (Stefan-Nachricht)")
self.chat.send_message(stefan_message)
self.stats.ticks_sent += 1
self.consecutive_errors = 0
@ -745,6 +757,10 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
tick_message = "[TICK]"
console.print("[dim]→ TICK[/dim]")
# WICHTIG: Signalisiere dass wir auf TTS warten
self._awaiting_tts.set()
logger.debug("_awaiting_tts gesetzt (TICK)")
success = self.chat.send_message(tick_message)
if success:
@ -840,15 +856,7 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
if self._current_chat_id:
self._save_tts_state(self._current_chat_id, msg.id)
# ════════════════════════════════════════════════════════════════
# WICHTIG: Nachrichten mit Steuercodes werden NICHT vorgelesen!
# Diese sind reine Roboter-Befehle, keine Sprache für Stefan.
# ════════════════════════════════════════════════════════════════
if self._contains_control_codes(msg.text):
logger.debug(f"TTS: Nachricht enthält Steuercodes, übersprungen")
continue
# Text für Sprache aufbereiten
# Text für Sprache aufbereiten (Steuercodes etc. entfernen)
speech_text = self._clean_for_speech(msg.text)
logger.debug(f"TTS: Original: '{msg.text[:100]}...'")
logger.debug(f"TTS: Nach Bereinigung: '{speech_text[:100] if speech_text else ''}' ({len(speech_text) if speech_text else 0} Zeichen)")
@ -859,10 +867,13 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
tts_text = tts_text[12:].strip()
logger.debug(f"TTS: 'Claude sagt:' entfernt, Rest: '{tts_text}' ({len(tts_text)} Zeichen)")
# Prüfe ob nach Entfernen noch Text übrig ist
# Prüfe ob nach Entfernen noch sprechbarer Text übrig ist
# Kein Mindestlänge-Check damit auch kurze Antworten wie "Ja!" gesprochen werden
if not tts_text:
logger.info(f"TTS: Nach Prefix-Entfernung kein Text übrig, übersprungen (Original: '{msg.text[:50]}')")
if not tts_text or not tts_text.strip():
logger.info(f"TTS: Nach Bereinigung kein sprechbarer Text übrig, übersprungen (Original: '{msg.text[:80]}')")
# Trotzdem _awaiting_tts clearen - die Nachricht wurde verarbeitet!
self._awaiting_tts.clear()
logger.debug("TTS: _awaiting_tts.clear() (kein sprechbarer Text)")
continue
# In Konsole anzeigen (ohne Prefix)
@ -872,14 +883,15 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
# Vorlesen (ohne "Claude sagt:" - das ist ja klar)
# WICHTIG: Speaking-Flag setzen damit Heartbeat wartet!
logger.info(f"TTS: Spreche {len(tts_text)} Zeichen...")
logger.info(f"TTS: _speaking.set() - Spreche {len(tts_text)} Zeichen: '{tts_text[:50]}...'")
self._speaking.set() # Signalisiere: Claude spricht!
try:
self.tts.speak(tts_text)
finally:
self._speaking.clear() # Fertig mit Sprechen
self._awaiting_tts.clear() # TTS komplett fertig!
logger.info("TTS: _speaking.clear() + _awaiting_tts.clear() - Fertig mit Sprechen")
self.stats.messages_spoken += 1
logger.debug("TTS: Sprechen beendet")
else:
logger.debug(f"TTS: Nachricht ist nicht von Claude, übersprungen")
@ -922,10 +934,10 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
time.sleep(0.5)
continue
# WICHTIG: Wenn Claude spricht (TTS), nicht aufzeichnen!
# WICHTIG: Wenn Claude spricht (TTS) oder wir auf TTS warten, nicht aufzeichnen!
# Das verhindert Echo (Mikrofon nimmt TTS auf) und
# überlappende Gespräche - wir lassen Claude ausreden.
if self._speaking.is_set():
if self._speaking.is_set() or self._awaiting_tts.is_set():
# Falls wir mitten in einer Aufnahme waren, diese beenden
if self._recording.is_set():
self._finalize_recording(current_session_texts)
@ -937,7 +949,7 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
result = self.stt.listen_once(timeout=1)
# Nochmal prüfen nach dem Hören (falls zwischendurch gemutet oder Claude spricht)
if self.is_muted() or self._speaking.is_set():
if self.is_muted() or self._speaking.is_set() or self._awaiting_tts.is_set():
continue
if result and result.text and len(result.text) > 2: