From f7ec6befe1ac138b4143294df8b08984ec115a59 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 26 Mar 2026 10:14:21 -0300 Subject: [PATCH] Invoking superclass method when audio context is interrupted or completed. --- src/pipecat/services/asyncai/tts.py | 2 ++ src/pipecat/services/cartesia/tts.py | 3 ++- src/pipecat/services/deepgram/sagemaker/tts.py | 1 + src/pipecat/services/deepgram/tts.py | 1 + src/pipecat/services/elevenlabs/tts.py | 2 ++ src/pipecat/services/fish/tts.py | 1 + src/pipecat/services/gradium/tts.py | 3 ++- src/pipecat/services/inworld/tts.py | 1 + src/pipecat/services/resembleai/tts.py | 3 ++- src/pipecat/services/rime/tts.py | 2 ++ 10 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/pipecat/services/asyncai/tts.py b/src/pipecat/services/asyncai/tts.py index d2ac74445..0f140281d 100644 --- a/src/pipecat/services/asyncai/tts.py +++ b/src/pipecat/services/asyncai/tts.py @@ -435,6 +435,7 @@ class AsyncAITTSService(WebsocketTTSService): async def on_audio_context_interrupted(self, context_id: str): """Close the Async AI context when the bot is interrupted.""" await self._close_context(context_id) + await super().on_audio_context_interrupted(context_id) async def on_audio_context_completed(self, context_id: str): """Close the Async AI context after all audio has been played. @@ -444,6 +445,7 @@ class AsyncAITTSService(WebsocketTTSService): ``close_context: True`` to free server-side resources. """ await self._close_context(context_id) + await super().on_audio_context_completed(context_id) @traced_tts async def run_tts(self, text: str, context_id: str) -> AsyncGenerator[Frame, None]: diff --git a/src/pipecat/services/cartesia/tts.py b/src/pipecat/services/cartesia/tts.py index 9e6073b57..d879ff694 100644 --- a/src/pipecat/services/cartesia/tts.py +++ b/src/pipecat/services/cartesia/tts.py @@ -574,6 +574,7 @@ class CartesiaTTSService(WebsocketTTSService): if context_id: cancel_msg = json.dumps({"context_id": context_id, "cancel": True}) await self._get_websocket().send(cancel_msg) + await super().on_audio_context_interrupted(context_id) async def on_audio_context_completed(self, context_id: str): """Close the Cartesia context after all audio has been played. @@ -582,7 +583,7 @@ class CartesiaTTSService(WebsocketTTSService): done once it has sent its ``done`` message, which is handled in ``_process_messages``. """ - pass + await super().on_audio_context_completed(context_id) async def flush_audio(self, context_id: Optional[str] = None): """Flush any pending audio and finalize the current context. diff --git a/src/pipecat/services/deepgram/sagemaker/tts.py b/src/pipecat/services/deepgram/sagemaker/tts.py index 36541b4be..6f43475dc 100644 --- a/src/pipecat/services/deepgram/sagemaker/tts.py +++ b/src/pipecat/services/deepgram/sagemaker/tts.py @@ -309,6 +309,7 @@ class DeepgramSageMakerTTSService(TTSService): await self._client.send_json({"type": "Clear"}) except Exception as e: logger.error(f"{self} error sending Clear message: {e}") + await super().on_audio_context_interrupted(context_id) async def flush_audio(self, context_id: Optional[str] = None): """Flush any pending audio synthesis by sending Flush command. diff --git a/src/pipecat/services/deepgram/tts.py b/src/pipecat/services/deepgram/tts.py index 9f2dc3976..3b5d04202 100644 --- a/src/pipecat/services/deepgram/tts.py +++ b/src/pipecat/services/deepgram/tts.py @@ -277,6 +277,7 @@ class DeepgramTTSService(WebsocketTTSService): await self._websocket.send(json.dumps({"type": "Clear"})) except Exception as e: logger.error(f"{self} error sending Clear message: {e}") + await super().on_audio_context_interrupted(context_id) async def _receive_messages(self): """Receive and process messages from Deepgram WebSocket.""" diff --git a/src/pipecat/services/elevenlabs/tts.py b/src/pipecat/services/elevenlabs/tts.py index 32da01c81..44126a7a7 100644 --- a/src/pipecat/services/elevenlabs/tts.py +++ b/src/pipecat/services/elevenlabs/tts.py @@ -731,6 +731,7 @@ class ElevenLabsTTSService(WebsocketTTSService): async def on_audio_context_interrupted(self, context_id: str): """Close the ElevenLabs context when the bot is interrupted.""" await self._close_context(context_id) + await super().on_audio_context_interrupted(context_id) async def on_audio_context_completed(self, context_id: str): """Close the ElevenLabs context after all audio has been played. @@ -740,6 +741,7 @@ class ElevenLabsTTSService(WebsocketTTSService): ``close_context: True`` to free server-side resources. """ await self._close_context(context_id) + await super().on_audio_context_completed(context_id) async def _receive_messages(self): """Handle incoming WebSocket messages from ElevenLabs.""" diff --git a/src/pipecat/services/fish/tts.py b/src/pipecat/services/fish/tts.py index ab57522d4..6333ac1c4 100644 --- a/src/pipecat/services/fish/tts.py +++ b/src/pipecat/services/fish/tts.py @@ -363,6 +363,7 @@ class FishAudioTTSService(InterruptibleTTSService): async def on_audio_context_interrupted(self, context_id: str): """Stop all metrics when audio context is interrupted.""" await self.stop_all_metrics() + await super().on_audio_context_interrupted(context_id) async def _receive_messages(self): async for message in self._get_websocket(): diff --git a/src/pipecat/services/gradium/tts.py b/src/pipecat/services/gradium/tts.py index 1c80a2ece..e8d69a7da 100644 --- a/src/pipecat/services/gradium/tts.py +++ b/src/pipecat/services/gradium/tts.py @@ -301,6 +301,7 @@ class GradiumTTSService(WebsocketTTSService): audio context no longer exists. """ await self.stop_all_metrics() + await super().on_audio_context_interrupted(context_id) async def on_audio_context_completed(self, context_id: str): """Called after an audio context has finished playing all of its audio. @@ -309,7 +310,7 @@ class GradiumTTSService(WebsocketTTSService): ``end_of_stream`` message (handled in ``_receive_messages``), after which the server-side context is already closed. """ - pass + await super().on_audio_context_completed(context_id) async def _receive_messages(self): """Process incoming websocket messages, demultiplexing by client_req_id.""" diff --git a/src/pipecat/services/inworld/tts.py b/src/pipecat/services/inworld/tts.py index 44361ebd7..a47308d39 100644 --- a/src/pipecat/services/inworld/tts.py +++ b/src/pipecat/services/inworld/tts.py @@ -800,6 +800,7 @@ class InworldTTSService(WebsocketTTSService): async def on_audio_context_interrupted(self, context_id: str): """Callback invoked when an audio context has been interrupted.""" await self._close_context(context_id) + await super().on_audio_context_interrupted(context_id) def _get_websocket(self): """Get the websocket for the Inworld WebSocket TTS service. diff --git a/src/pipecat/services/resembleai/tts.py b/src/pipecat/services/resembleai/tts.py index f9fd6549e..d4bb77fb0 100644 --- a/src/pipecat/services/resembleai/tts.py +++ b/src/pipecat/services/resembleai/tts.py @@ -258,6 +258,7 @@ class ResembleAITTSService(WebsocketTTSService): async def on_audio_context_interrupted(self, context_id: str): """Stop metrics when the bot is interrupted.""" await self.stop_all_metrics() + await super().on_audio_context_interrupted(context_id) async def on_audio_context_completed(self, context_id: str): """Stop metrics after the Resemble AI context finishes playing. @@ -266,7 +267,7 @@ class ResembleAITTSService(WebsocketTTSService): ``audio_end`` message (handled in ``_process_messages``), after which the server-side context is already closed. """ - pass + await super().on_audio_context_completed(context_id) async def flush_audio(self, context_id: Optional[str] = None): """Flush any pending audio and finalize the current context.""" diff --git a/src/pipecat/services/rime/tts.py b/src/pipecat/services/rime/tts.py index a359986b6..e02933e26 100644 --- a/src/pipecat/services/rime/tts.py +++ b/src/pipecat/services/rime/tts.py @@ -516,6 +516,7 @@ class RimeTTSService(WebsocketTTSService): async def on_audio_context_interrupted(self, context_id: str): """Clear the Rime speech queue and stop metrics when the bot is interrupted.""" await self._close_context(context_id) + await super().on_audio_context_interrupted(context_id) async def on_audio_context_completed(self, context_id: str): """Clear server-side state and stop metrics after the Rime context finishes playing. @@ -525,6 +526,7 @@ class RimeTTSService(WebsocketTTSService): any residual server-side state once all audio has been delivered. """ await self._close_context(context_id) + await super().on_audio_context_completed(context_id) def _calculate_word_times(self, words: list, starts: list, ends: list) -> list: """Calculate word timing pairs with proper spacing and punctuation.