From 23a0b914fab7c74b6720783f71f25e0e2684c5fb Mon Sep 17 00:00:00 2001 From: scott Date: Sun, 5 Apr 2026 17:10:32 -0400 Subject: [PATCH] Add per-event logging and top-level exception catching Log every event type on arrival and wrap handle_event in try/except so silent crashes are visible. Helps diagnose the streaming protocol hang where no logs appear after supports_synthesize_streaming=True. Co-Authored-By: Claude Sonnet 4.6 --- wyoming_handler.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/wyoming_handler.py b/wyoming_handler.py index 5c47ea9..2cb2f0c 100644 --- a/wyoming_handler.py +++ b/wyoming_handler.py @@ -63,6 +63,14 @@ class ChatterboxWyomingHandler(AsyncEventHandler): self._streaming_voice: Optional[str] = None async def handle_event(self, event: Event) -> bool: + logger.info(f"Event received: {event.type}") + try: + return await self._handle_event(event) + except Exception: + logger.exception(f"Unhandled exception in handle_event for {event.type}") + return True + + async def _handle_event(self, event: Event) -> bool: if Describe.is_type(event.type): await self.write_event(self._info.event()) return True @@ -72,6 +80,7 @@ class ChatterboxWyomingHandler(AsyncEventHandler): self._streaming = True self._streaming_text = "" self._streaming_voice = start.voice.name if start.voice else None + logger.info(f"Streaming started, voice='{self._streaming_voice}'") return True if SynthesizeChunk.is_type(event.type): @@ -81,6 +90,7 @@ class ChatterboxWyomingHandler(AsyncEventHandler): return True if SynthesizeStop.is_type(event.type): + logger.info(f"SynthesizeStop — text: {self._streaming_text!r}") if self._streaming and self._streaming_text: await self._synthesize_and_stream( self._streaming_text, @@ -95,14 +105,17 @@ class ChatterboxWyomingHandler(AsyncEventHandler): if Synthesize.is_type(event.type): if self._streaming: # Ignore duplicate Synthesize events sent alongside streaming protocol + logger.info("Ignoring Synthesize (streaming protocol active)") return True synth = Synthesize.from_event(event) voice_name = synth.voice.name if synth.voice else None + logger.info(f"Synthesize — voice='{voice_name}', text: {synth.text!r}") await self._synthesize_and_stream(synth.text, voice_name) # NOTE: SynthesizeStopped is NOT sent here — it belongs only to the # streaming protocol (SynthesizeStop path). Sending it here confuses HA. return True + logger.warning(f"Unhandled event type: {event.type}") return True async def _synthesize_and_stream(self, text: str, voice_name: Optional[str]) -> None: