diff --git a/src/pipecat/services/ai_services.py b/src/pipecat/services/ai_services.py index 7d49c5676..99fd05481 100644 --- a/src/pipecat/services/ai_services.py +++ b/src/pipecat/services/ai_services.py @@ -76,13 +76,13 @@ class AIService(FrameProcessor): ) for key, value in settings.items(): - print("Update request for:", key, value) + logger.debug("Update request for:", key, value) if key in self._settings: logger.info(f"Updating LLM setting {key} to: [{value}]") self._settings[key] = value elif key in SessionProperties.model_fields: - print("Attempting to update", key, value) + logger.debug("Attempting to update", key, value) try: from pipecat.services.openai_realtime_beta.events import ( @@ -213,6 +213,8 @@ class TTSService(AIService): push_silence_after_stop: bool = False, # if push_silence_after_stop is True, send this amount of audio silence silence_time_s: float = 2.0, + # if True, we will pause processing frames while we are receiving audio + pause_frame_processing: bool = False, # TTS output sample rate sample_rate: Optional[int] = None, text_filter: Optional[BaseTextFilter] = None, @@ -225,6 +227,7 @@ class TTSService(AIService): self._stop_frame_timeout_s: float = stop_frame_timeout_s self._push_silence_after_stop: bool = push_silence_after_stop self._silence_time_s: float = silence_time_s + self._pause_frame_processing: bool = pause_frame_processing self._init_sample_rate = sample_rate self._sample_rate = 0 self._voice_id: str = "" @@ -314,8 +317,7 @@ class TTSService(AIService): # We pause processing incoming frames if the LLM response included # text (it might be that it's only a function calling response). We # pause to avoid audio overlapping. - if self._processing_text: - await self.pause_processing_frames() + await self._maybe_pause_frame_processing() sentence = self._current_sentence self._current_sentence = "" @@ -327,16 +329,16 @@ class TTSService(AIService): else: await self.push_frame(frame, direction) elif isinstance(frame, TTSSpeakFrame): + await self._push_tts_frames(frame.text) # We pause processing incoming frames because we are sending data to # the TTS. We pause to avoid audio overlapping. - await self.pause_processing_frames() - await self._push_tts_frames(frame.text) + await self._maybe_pause_frame_processing() await self.flush_audio() self._processing_text = False elif isinstance(frame, TTSUpdateSettingsFrame): await self._update_settings(frame.settings) elif isinstance(frame, BotStoppedSpeakingFrame): - await self.resume_processing_frames() + await self._maybe_resume_frame_processing() else: await self.push_frame(frame, direction) @@ -367,6 +369,14 @@ class TTSService(AIService): self._text_filter.handle_interruption() await self.push_frame(frame, direction) + async def _maybe_pause_frame_processing(self): + if self._processing_text and self._pause_frame_processing: + await self.pause_processing_frames() + + async def _maybe_resume_frame_processing(self): + if self._pause_frame_processing: + await self.resume_processing_frames() + async def _process_text_frame(self, frame: TextFrame): text: Optional[str] = None if not self._aggregate_sentences: diff --git a/src/pipecat/services/cartesia.py b/src/pipecat/services/cartesia.py index becd39f79..67fc67ebf 100644 --- a/src/pipecat/services/cartesia.py +++ b/src/pipecat/services/cartesia.py @@ -109,6 +109,7 @@ class CartesiaTTSService(AudioContextWordTTSService, WebsocketService): self, aggregate_sentences=True, push_text_frames=False, + pause_frame_processing=True, sample_rate=sample_rate, **kwargs, ) diff --git a/src/pipecat/services/elevenlabs.py b/src/pipecat/services/elevenlabs.py index d8acedd6c..3c8cbb3ed 100644 --- a/src/pipecat/services/elevenlabs.py +++ b/src/pipecat/services/elevenlabs.py @@ -192,6 +192,7 @@ class ElevenLabsTTSService(WordTTSService, WebsocketService): push_text_frames=False, push_stop_frames=True, stop_frame_timeout_s=2.0, + pause_frame_processing=True, sample_rate=sample_rate, **kwargs, ) diff --git a/src/pipecat/services/fish.py b/src/pipecat/services/fish.py index e36eaf497..94475aca7 100644 --- a/src/pipecat/services/fish.py +++ b/src/pipecat/services/fish.py @@ -60,7 +60,7 @@ class FishAudioTTSService(TTSService, WebsocketService): params: InputParams = InputParams(), **kwargs, ): - super().__init__(sample_rate=sample_rate, **kwargs) + super().__init__(pause_frame_processing=True, sample_rate=sample_rate, **kwargs) self._api_key = api_key self._base_url = "wss://api.fish.audio/v1/tts/live" diff --git a/src/pipecat/services/lmnt.py b/src/pipecat/services/lmnt.py index 645494cc1..0272690e8 100644 --- a/src/pipecat/services/lmnt.py +++ b/src/pipecat/services/lmnt.py @@ -73,6 +73,7 @@ class LmntTTSService(TTSService, WebsocketService): TTSService.__init__( self, push_stop_frames=True, + pause_frame_processing=True, sample_rate=sample_rate, **kwargs, ) diff --git a/src/pipecat/services/playht.py b/src/pipecat/services/playht.py index 3196c306d..297e802d3 100644 --- a/src/pipecat/services/playht.py +++ b/src/pipecat/services/playht.py @@ -120,6 +120,7 @@ class PlayHTTTSService(TTSService, WebsocketService): ): TTSService.__init__( self, + pause_frame_processing=True, sample_rate=sample_rate, **kwargs, ) diff --git a/src/pipecat/services/rime.py b/src/pipecat/services/rime.py index 79e557f48..f87405a63 100644 --- a/src/pipecat/services/rime.py +++ b/src/pipecat/services/rime.py @@ -101,6 +101,7 @@ class RimeTTSService(AudioContextWordTTSService, WebsocketService): push_text_frames=False, push_stop_frames=True, stop_frame_timeout_s=2.0, + pause_frame_processing=True, sample_rate=sample_rate, **kwargs, )