From 5b67dcd9e78d14d77797cbe172bfe9b83a70b483 Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Thu, 2 Apr 2026 11:31:29 -0400 Subject: [PATCH] Remove deprecated EmulateUser{Started,Stopped}SpeakingFrame and emulated field Remove EmulateUserStartedSpeakingFrame, EmulateUserStoppedSpeakingFrame (deprecated since v0.0.99), and the emulated field from UserStartedSpeakingFrame and UserStoppedSpeakingFrame. Clean up the handling code in base_input.py and a stale comment in nova_sonic/llm.py. --- src/pipecat/frames/frames.py | 68 +--------------------- src/pipecat/services/aws/nova_sonic/llm.py | 14 +---- src/pipecat/transports/base_input.py | 16 +---- 3 files changed, 7 insertions(+), 91 deletions(-) diff --git a/src/pipecat/frames/frames.py b/src/pipecat/frames/frames.py index 76ed58682..86a93825b 100644 --- a/src/pipecat/frames/frames.py +++ b/src/pipecat/frames/frames.py @@ -866,16 +866,9 @@ class UserStartedSpeakingFrame(SystemFrame): Emitted when the user turn starts, which usually means that some transcriptions are already available. - - Parameters: - emulated: Whether this event was emulated rather than detected by VAD. - - .. deprecated:: 0.0.99 - This field is deprecated and will be removed in a future version. - """ - emulated: bool = False + pass @dataclass @@ -884,16 +877,9 @@ class UserStoppedSpeakingFrame(SystemFrame): Emitted when the user turn ends. This usually coincides with the start of the bot turn. - - Parameters: - emulated: Whether this event was emulated rather than detected by VAD. - - .. deprecated:: 0.0.99 - This field is deprecated and will be removed in a future version. - """ - emulated: bool = False + pass @dataclass @@ -928,56 +914,6 @@ class UserSpeakingFrame(SystemFrame): pass -@dataclass -class EmulateUserStartedSpeakingFrame(SystemFrame): - """Frame to emulate user started speaking behavior. - - Emitted by internal processors upstream to emulate VAD behavior when a - user starts speaking. - - .. deprecated:: 0.0.99 - This frame is deprecated and will be removed in a future version. - """ - - def __post_init__(self): - super().__post_init__() - - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "EmulateUserStartedSpeakingFrame is deprecated and will be removed in a future version.", - DeprecationWarning, - stacklevel=2, - ) - - -@dataclass -class EmulateUserStoppedSpeakingFrame(SystemFrame): - """Frame to emulate user stopped speaking behavior. - - Emitted by internal processors upstream to emulate VAD behavior when a - user stops speaking. - - .. deprecated:: 0.0.99 - This frame is deprecated and will be removed in a future version. - """ - - def __post_init__(self): - super().__post_init__() - - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("always") - warnings.warn( - "EmulateUserStoppedSpeakingFrame is deprecated and will be removed in a future version.", - DeprecationWarning, - stacklevel=2, - ) - - @dataclass class VADUserStartedSpeakingFrame(SystemFrame): """Frame emitted when VAD definitively detects user started speaking. diff --git a/src/pipecat/services/aws/nova_sonic/llm.py b/src/pipecat/services/aws/nova_sonic/llm.py index 6f330babb..2465624f5 100644 --- a/src/pipecat/services/aws/nova_sonic/llm.py +++ b/src/pipecat/services/aws/nova_sonic/llm.py @@ -1281,18 +1281,8 @@ class AWSNovaSonicLLMService(LLMService): # HACK: Check if this transcription was triggered by our own # assistant response trigger. If so, we need to wrap it with # UserStarted/StoppedSpeakingFrames; otherwise the user aggregator - # would fire an EmulatedUserStartedSpeakingFrame, which would - # trigger an interruption, which would prevent us from writing the - # assistant response to context. - # - # Sending an EmulateUserStartedSpeakingFrame ourselves doesn't - # work: it just causes the interruption we're trying to avoid. - # - # Setting enable_emulated_vad_interruptions also doesn't work: at - # the time the user aggregator receives the TranscriptionFrame, it - # doesn't yet know the assistant has started responding, so it - # doesn't know that emulating the user starting to speak would - # cause an interruption. + # would trigger an interruption, which would prevent us from + # writing the assistant response to context. should_wrap_in_user_started_stopped_speaking_frames = ( self._waiting_for_trigger_transcription and self._user_text_buffer.strip().lower() == "ready" diff --git a/src/pipecat/transports/base_input.py b/src/pipecat/transports/base_input.py index 3d26925cb..d4adb74e1 100644 --- a/src/pipecat/transports/base_input.py +++ b/src/pipecat/transports/base_input.py @@ -25,8 +25,6 @@ from pipecat.frames.frames import ( BotStartedSpeakingFrame, BotStoppedSpeakingFrame, CancelFrame, - EmulateUserStartedSpeakingFrame, - EmulateUserStoppedSpeakingFrame, EndFrame, FilterUpdateSettingsFrame, Frame, @@ -313,12 +311,6 @@ class BaseInputTransport(FrameProcessor): elif isinstance(frame, BotStoppedSpeakingFrame): await self._deprecated_handle_bot_stopped_speaking(frame) await self.push_frame(frame, direction) - elif isinstance(frame, EmulateUserStartedSpeakingFrame): - logger.debug("Emulating user started speaking") - await self._deprecated_handle_user_interruption(VADState.SPEAKING, emulated=True) - elif isinstance(frame, EmulateUserStoppedSpeakingFrame): - logger.debug("Emulating user stopped speaking") - await self._deprecated_handle_user_interruption(VADState.QUIET, emulated=True) # All other system frames elif isinstance(frame, SystemFrame): await self.push_frame(frame, direction) @@ -500,15 +492,13 @@ class BaseInputTransport(FrameProcessor): """Update bot speaking state when bot stops speaking.""" self._bot_speaking = False - async def _deprecated_handle_user_interruption( - self, vad_state: VADState, emulated: bool = False - ): + async def _deprecated_handle_user_interruption(self, vad_state: VADState): """Handle user interruption events based on speaking state.""" if vad_state == VADState.SPEAKING: logger.debug("User started speaking") self._user_speaking = True - await self.broadcast_frame(UserStartedSpeakingFrame, emulated=emulated) + await self.broadcast_frame(UserStartedSpeakingFrame) # Make sure we notify about interruptions quickly out-of-band. await self.broadcast_interruption() @@ -516,7 +506,7 @@ class BaseInputTransport(FrameProcessor): logger.debug("User stopped speaking") self._user_speaking = False - await self.broadcast_frame(UserStoppedSpeakingFrame, emulated=emulated) + await self.broadcast_frame(UserStoppedSpeakingFrame) async def _deprecated_old_handle_vad( self, audio_frame: InputAudioRawFrame, vad_state: VADState