Merge pull request #2745 from pipecat-ai/aleix/transport-message-frames-deprecations

transport message frames deprecations
This commit is contained in:
Aleix Conchillo Flaqué
2025-10-01 16:05:55 -07:00
committed by GitHub
18 changed files with 332 additions and 86 deletions

View File

@@ -32,6 +32,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed an issue where local SmartTurn was not being ran in a separate thread. - Fixed an issue where local SmartTurn was not being ran in a separate thread.
### Deprecated
- `DailyTransportMessageFrame` and `DailyTransportMessageUrgentFrame` are
deprecated, use `DailyOutputTransportMessageFrame` and
`DailyOutputTransportMessageUrgentFrame` respectively instead.
- `LiveKitTransportMessageFrame` and `LiveKitTransportMessageUrgentFrame` are
deprecated, use `LiveKitOutputTransportMessageFrame` and
`LiveKitOutputTransportMessageUrgentFrame` respectively instead.
- `TransportMessageFrame` and `TransportMessageUrgentFrame` are deprecated, use
`OutputTransportMessageFrame` and `OutputTransportMessageUrgentFrame`
respectively instead.
- `InputTransportMessageUrgentFrame` is deprecated, use
`InputTransportMessageFrame` instead.
## [0.0.86] - 2025-09-24 ## [0.0.86] - 2025-09-24
### Added ### Added

View File

@@ -26,7 +26,11 @@ from pipecat.services.deepgram.stt import DeepgramSTTService
from pipecat.services.deepgram.tts import DeepgramTTSService from pipecat.services.deepgram.tts import DeepgramTTSService
from pipecat.services.openai.llm import OpenAILLMService from pipecat.services.openai.llm import OpenAILLMService
from pipecat.transports.base_transport import BaseTransport, TransportParams from pipecat.transports.base_transport import BaseTransport, TransportParams
from pipecat.transports.daily.transport import DailyParams, DailyTransportMessageFrame from pipecat.transports.daily.transport import (
DailyOutputTransportMessageFrame,
DailyOutputTransportMessageUrgentFrame,
DailyParams,
)
from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams
load_dotenv(override=True) load_dotenv(override=True)
@@ -128,14 +132,14 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments):
logger.debug(f"Received latency ping app message: {message}") logger.debug(f"Received latency ping app message: {message}")
ts = message["latency-ping"]["ts"] ts = message["latency-ping"]["ts"]
# Send immediately # Send immediately
transport.output().send_message( await task.queue_frame(
DailyTransportMessageFrame( DailyOutputTransportMessageUrgentFrame(
message={"latency-pong-msg-handler": {"ts": ts}}, participant_id=sender message={"latency-pong-msg-handler": {"ts": ts}}, participant_id=sender
) )
) )
# And push to the pipeline for the Daily transport.output to send # And push to the pipeline for the Daily transport.output to send
await task.queue_frame( await task.queue_frame(
DailyTransportMessageFrame( DailyOutputTransportMessageFrame(
message={"latency-pong-pipeline-delivery": {"ts": ts}}, message={"latency-pong-pipeline-delivery": {"ts": ts}},
participant_id=sender, participant_id=sender,
) )

View File

@@ -672,7 +672,7 @@ class TTSSpeakFrame(DataFrame):
@dataclass @dataclass
class TransportMessageFrame(DataFrame): class OutputTransportMessageFrame(DataFrame):
"""Frame containing transport-specific message data. """Frame containing transport-specific message data.
Parameters: Parameters:
@@ -685,6 +685,32 @@ class TransportMessageFrame(DataFrame):
return f"{self.name}(message: {self.message})" return f"{self.name}(message: {self.message})"
@dataclass
class TransportMessageFrame(OutputTransportMessageFrame):
"""Frame containing transport-specific message data.
.. deprecated:: 0.0.87
This frame is deprecated and will be removed in a future version.
Instead, use `OutputTransportMessageFrame`.
Parameters:
message: The transport message payload.
"""
def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"TransportMessageFrame is deprecated and will be removed in a future version. "
"Instead, use OutputTransportMessageFrame.",
DeprecationWarning,
stacklevel=2,
)
@dataclass @dataclass
class DTMFFrame: class DTMFFrame:
"""Base class for DTMF (Dual-Tone Multi-Frequency) keypad frames. """Base class for DTMF (Dual-Tone Multi-Frequency) keypad frames.
@@ -1092,8 +1118,8 @@ class STTMuteFrame(SystemFrame):
@dataclass @dataclass
class TransportMessageUrgentFrame(SystemFrame): class InputTransportMessageFrame(SystemFrame):
"""Frame for urgent transport messages that need immediate processing. """Frame for transport messages received from external sources.
Parameters: Parameters:
message: The urgent transport message payload. message: The urgent transport message payload.
@@ -1106,20 +1132,69 @@ class TransportMessageUrgentFrame(SystemFrame):
@dataclass @dataclass
class InputTransportMessageUrgentFrame(TransportMessageUrgentFrame): class InputTransportMessageUrgentFrame(InputTransportMessageFrame):
"""Frame for transport messages received from external sources. """Frame for transport messages received from external sources.
This frame wraps incoming transport messages to distinguish them from outgoing .. deprecated:: 0.0.87
urgent transport messages (TransportMessageUrgentFrame), preventing infinite This frame is deprecated and will be removed in a future version.
message loops in the transport layer. It inherits the message payload from Instead, use `InputTransportMessageFrame`.
TransportMessageFrame while marking the message as having been received
rather than generated locally.
Used by transport implementations to properly handle bidirectional message Parameters:
flow without creating feedback loops. message: The urgent transport message payload.
""" """
pass def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"InputTransportMessageUrgentFrame is deprecated and will be removed in a future version. "
"Instead, use InputTransportMessageFrame.",
DeprecationWarning,
stacklevel=2,
)
@dataclass
class OutputTransportMessageUrgentFrame(SystemFrame):
"""Frame for urgent transport messages that need to be sent immediately.
Parameters:
message: The urgent transport message payload.
"""
message: Any
def __str__(self):
return f"{self.name}(message: {self.message})"
@dataclass
class TransportMessageUrgentFrame(OutputTransportMessageUrgentFrame):
"""Frame for urgent transport messages that need to be sent immediately.
.. deprecated:: 0.0.87
This frame is deprecated and will be removed in a future version.
Instead, use `OutputTransportMessageUrgentFrame`.
Parameters:
message: The urgent transport message payload.
"""
def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"TransportMessageUrgentFrame is deprecated and will be removed in a future version. "
"Instead, use OutputTransportMessageFrame.",
DeprecationWarning,
stacklevel=2,
)
@dataclass @dataclass

View File

@@ -42,6 +42,7 @@ from pipecat.frames.frames import (
Frame, Frame,
FunctionCallResultFrame, FunctionCallResultFrame,
InputAudioRawFrame, InputAudioRawFrame,
InputTransportMessageUrgentFrame,
InterimTranscriptionFrame, InterimTranscriptionFrame,
LLMConfigureOutputFrame, LLMConfigureOutputFrame,
LLMContextFrame, LLMContextFrame,
@@ -50,10 +51,10 @@ from pipecat.frames.frames import (
LLMMessagesAppendFrame, LLMMessagesAppendFrame,
LLMTextFrame, LLMTextFrame,
MetricsFrame, MetricsFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
SystemFrame, SystemFrame,
TranscriptionFrame, TranscriptionFrame,
TransportMessageUrgentFrame,
TTSAudioRawFrame, TTSAudioRawFrame,
TTSStartedFrame, TTSStartedFrame,
TTSStoppedFrame, TTSStoppedFrame,
@@ -1345,7 +1346,9 @@ class RTVIProcessor(FrameProcessor):
async def push_transport_message(self, model: BaseModel, exclude_none: bool = True): async def push_transport_message(self, model: BaseModel, exclude_none: bool = True):
"""Push a transport message frame.""" """Push a transport message frame."""
frame = TransportMessageUrgentFrame(message=model.model_dump(exclude_none=exclude_none)) frame = OutputTransportMessageUrgentFrame(
message=model.model_dump(exclude_none=exclude_none)
)
await self.push_frame(frame) await self.push_frame(frame)
async def handle_message(self, message: RTVIMessage): async def handle_message(self, message: RTVIMessage):
@@ -1418,7 +1421,7 @@ class RTVIProcessor(FrameProcessor):
elif isinstance(frame, ErrorFrame): elif isinstance(frame, ErrorFrame):
await self._send_error_frame(frame) await self._send_error_frame(frame)
await self.push_frame(frame, direction) await self.push_frame(frame, direction)
elif isinstance(frame, TransportMessageUrgentFrame): elif isinstance(frame, InputTransportMessageUrgentFrame):
await self._handle_transport_message(frame) await self._handle_transport_message(frame)
# All other system frames # All other system frames
elif isinstance(frame, SystemFrame): elif isinstance(frame, SystemFrame):
@@ -1481,7 +1484,7 @@ class RTVIProcessor(FrameProcessor):
await self._handle_message(message) await self._handle_message(message)
self._message_queue.task_done() self._message_queue.task_done()
async def _handle_transport_message(self, frame: TransportMessageUrgentFrame): async def _handle_transport_message(self, frame: InputTransportMessageUrgentFrame):
"""Handle an incoming transport message frame.""" """Handle an incoming transport message frame."""
try: try:
transport_message = frame.message transport_message = frame.message

View File

@@ -15,7 +15,7 @@ from pipecat.frames.frames import (
Frame, Frame,
InputAudioRawFrame, InputAudioRawFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
TransportMessageFrame, UserSpeakingFrame,
) )
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
@@ -36,9 +36,9 @@ class FrameLogger(FrameProcessor):
color: Optional[str] = None, color: Optional[str] = None,
ignored_frame_types: Tuple[Type[Frame], ...] = ( ignored_frame_types: Tuple[Type[Frame], ...] = (
BotSpeakingFrame, BotSpeakingFrame,
UserSpeakingFrame,
InputAudioRawFrame, InputAudioRawFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
TransportMessageFrame,
), ),
): ):
"""Initialize the frame logger. """Initialize the frame logger.

View File

@@ -21,9 +21,9 @@ from pipecat.frames.frames import (
InputAudioRawFrame, InputAudioRawFrame,
InputDTMFFrame, InputDTMFFrame,
InterruptionFrame, InterruptionFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType
@@ -121,7 +121,7 @@ class ExotelFrameSerializer(FrameSerializer):
} }
return json.dumps(answer) return json.dumps(answer)
elif isinstance(frame, (TransportMessageFrame, TransportMessageUrgentFrame)): elif isinstance(frame, (OutputTransportMessageFrame, OutputTransportMessageUrgentFrame)):
return json.dumps(frame.message) return json.dumps(frame.message)
return None return None

View File

@@ -23,9 +23,9 @@ from pipecat.frames.frames import (
InputAudioRawFrame, InputAudioRawFrame,
InputDTMFFrame, InputDTMFFrame,
InterruptionFrame, InterruptionFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType
@@ -148,7 +148,7 @@ class PlivoFrameSerializer(FrameSerializer):
} }
return json.dumps(answer) return json.dumps(answer)
elif isinstance(frame, (TransportMessageFrame, TransportMessageUrgentFrame)): elif isinstance(frame, (OutputTransportMessageFrame, OutputTransportMessageUrgentFrame)):
return json.dumps(frame.message) return json.dumps(frame.message)
# Return None for unhandled frames # Return None for unhandled frames

View File

@@ -15,11 +15,12 @@ import pipecat.frames.protobufs.frames_pb2 as frame_protos
from pipecat.frames.frames import ( from pipecat.frames.frames import (
Frame, Frame,
InputAudioRawFrame, InputAudioRawFrame,
InputTransportMessageFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
TextFrame, TextFrame,
TranscriptionFrame, TranscriptionFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType
@@ -82,7 +83,7 @@ class ProtobufFrameSerializer(FrameSerializer):
Serialized frame as bytes, or None if frame type is not serializable. Serialized frame as bytes, or None if frame type is not serializable.
""" """
# Wrapping this messages as a JSONFrame to send # Wrapping this messages as a JSONFrame to send
if isinstance(frame, (TransportMessageFrame, TransportMessageUrgentFrame)): if isinstance(frame, (OutputTransportMessageFrame, OutputTransportMessageUrgentFrame)):
frame = MessageFrame( frame = MessageFrame(
data=json.dumps(frame.message), data=json.dumps(frame.message),
) )
@@ -134,11 +135,11 @@ class ProtobufFrameSerializer(FrameSerializer):
if "pts" in args_dict: if "pts" in args_dict:
del args_dict["pts"] del args_dict["pts"]
# Special handling for MessageFrame -> TransportMessageUrgentFrame # Special handling for MessageFrame -> OutputTransportMessageUrgentFrame
if class_name == MessageFrame: if class_name == MessageFrame:
try: try:
msg = json.loads(args_dict["data"]) msg = json.loads(args_dict["data"])
instance = TransportMessageUrgentFrame(message=msg) instance = InputTransportMessageFrame(message=msg)
logger.debug(f"ProtobufFrameSerializer: Transport message {instance}") logger.debug(f"ProtobufFrameSerializer: Transport message {instance}")
except Exception as e: except Exception as e:
logger.error(f"Error parsing MessageFrame data: {e}") logger.error(f"Error parsing MessageFrame data: {e}")

View File

@@ -23,9 +23,9 @@ from pipecat.frames.frames import (
InputAudioRawFrame, InputAudioRawFrame,
InputDTMFFrame, InputDTMFFrame,
InterruptionFrame, InterruptionFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType
@@ -175,7 +175,7 @@ class TwilioFrameSerializer(FrameSerializer):
} }
return json.dumps(answer) return json.dumps(answer)
elif isinstance(frame, (TransportMessageFrame, TransportMessageUrgentFrame)): elif isinstance(frame, (OutputTransportMessageFrame, OutputTransportMessageUrgentFrame)):
return json.dumps(frame.message) return json.dumps(frame.message)
# Return None for unhandled frames # Return None for unhandled frames

View File

@@ -29,20 +29,19 @@ from pipecat.frames.frames import (
CancelFrame, CancelFrame,
EndFrame, EndFrame,
Frame, Frame,
InputTransportMessageUrgentFrame,
InterruptionFrame, InterruptionFrame,
MixerControlFrame, MixerControlFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputDTMFFrame, OutputDTMFFrame,
OutputDTMFUrgentFrame, OutputDTMFUrgentFrame,
OutputImageRawFrame, OutputImageRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
OutputTransportReadyFrame, OutputTransportReadyFrame,
SpeechOutputAudioRawFrame, SpeechOutputAudioRawFrame,
SpriteFrame, SpriteFrame,
StartFrame, StartFrame,
SystemFrame, SystemFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
TTSAudioRawFrame, TTSAudioRawFrame,
) )
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor from pipecat.processors.frame_processor import FrameDirection, FrameProcessor
@@ -178,7 +177,9 @@ class BaseOutputTransport(FrameProcessor):
# Sending a frame indicating that the output transport is ready and able to receive frames. # Sending a frame indicating that the output transport is ready and able to receive frames.
await self.push_frame(OutputTransportReadyFrame(), FrameDirection.UPSTREAM) await self.push_frame(OutputTransportReadyFrame(), FrameDirection.UPSTREAM)
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a transport message. """Send a transport message.
Args: Args:
@@ -307,9 +308,7 @@ class BaseOutputTransport(FrameProcessor):
elif isinstance(frame, InterruptionFrame): elif isinstance(frame, InterruptionFrame):
await self.push_frame(frame, direction) await self.push_frame(frame, direction)
await self._handle_frame(frame) await self._handle_frame(frame)
elif isinstance(frame, TransportMessageUrgentFrame) and not isinstance( elif isinstance(frame, OutputTransportMessageUrgentFrame):
frame, InputTransportMessageUrgentFrame
):
await self.send_message(frame) await self.send_message(frame)
elif isinstance(frame, OutputDTMFUrgentFrame): elif isinstance(frame, OutputDTMFUrgentFrame):
await self.write_dtmf(frame) await self.write_dtmf(frame)
@@ -646,7 +645,7 @@ class BaseOutputTransport(FrameProcessor):
await self._set_video_image(frame) await self._set_video_image(frame)
elif isinstance(frame, SpriteFrame): elif isinstance(frame, SpriteFrame):
await self._set_video_images(frame.images) await self._set_video_images(frame.images)
elif isinstance(frame, TransportMessageFrame): elif isinstance(frame, OutputTransportMessageFrame):
await self._transport.send_message(frame) await self._transport.send_message(frame)
elif isinstance(frame, OutputDTMFFrame): elif isinstance(frame, OutputDTMFFrame):
await self._transport.write_dtmf(frame) await self._transport.write_dtmf(frame)

View File

@@ -30,15 +30,15 @@ from pipecat.frames.frames import (
ErrorFrame, ErrorFrame,
Frame, Frame,
InputAudioRawFrame, InputAudioRawFrame,
InputTransportMessageUrgentFrame, InputTransportMessageFrame,
InterimTranscriptionFrame, InterimTranscriptionFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputImageRawFrame, OutputImageRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
SpriteFrame, SpriteFrame,
StartFrame, StartFrame,
TranscriptionFrame, TranscriptionFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
UserAudioRawFrame, UserAudioRawFrame,
UserImageRawFrame, UserImageRawFrame,
UserImageRequestFrame, UserImageRequestFrame,
@@ -74,7 +74,7 @@ VAD_RESET_PERIOD_MS = 2000
@dataclass @dataclass
class DailyTransportMessageFrame(TransportMessageFrame): class DailyOutputTransportMessageFrame(OutputTransportMessageFrame):
"""Frame for transport messages in Daily calls. """Frame for transport messages in Daily calls.
Parameters: Parameters:
@@ -85,7 +85,7 @@ class DailyTransportMessageFrame(TransportMessageFrame):
@dataclass @dataclass
class DailyTransportMessageUrgentFrame(TransportMessageUrgentFrame): class DailyOutputTransportMessageUrgentFrame(OutputTransportMessageUrgentFrame):
"""Frame for urgent transport messages in Daily calls. """Frame for urgent transport messages in Daily calls.
Parameters: Parameters:
@@ -96,7 +96,59 @@ class DailyTransportMessageUrgentFrame(TransportMessageUrgentFrame):
@dataclass @dataclass
class DailyInputTransportMessageUrgentFrame(InputTransportMessageUrgentFrame): class DailyTransportMessageFrame(DailyOutputTransportMessageFrame):
"""Frame for transport messages in Daily calls.
.. deprecated:: 0.0.87
This frame is deprecated and will be removed in a future version.
Instead, use `DailyOutputTransportMessageFrame`.
Parameters:
participant_id: Optional ID of the participant this message is for/from.
"""
def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"DailyTransportMessageFrame is deprecated and will be removed in a future version. "
"Instead, use DailyOutputTransportMessageFrame.",
DeprecationWarning,
stacklevel=2,
)
@dataclass
class DailyTransportMessageUrgentFrame(DailyOutputTransportMessageUrgentFrame):
"""Frame for urgent transport messages in Daily calls.
.. deprecated:: 0.0.87
This frame is deprecated and will be removed in a future version.
Instead, use `DailyOutputTransportMessageUrgentFrame`.
Parameters:
participant_id: Optional ID of the participant this message is for/from.
"""
def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"DailyTransportMessageUrgentFrame is deprecated and will be removed in a future version. "
"Instead, use DailyOutputTransportMessageUrgentFrame.",
DeprecationWarning,
stacklevel=2,
)
@dataclass
class DailyInputTransportMessageFrame(InputTransportMessageFrame):
"""Frame for input urgent transport messages in Daily calls. """Frame for input urgent transport messages in Daily calls.
Parameters: Parameters:
@@ -106,6 +158,31 @@ class DailyInputTransportMessageUrgentFrame(InputTransportMessageUrgentFrame):
participant_id: Optional[str] = None participant_id: Optional[str] = None
class DailyInputTransportMessageUrgentFrame(DailyInputTransportMessageFrame):
"""Frame for input urgent transport messages in Daily calls.
.. deprecated:: 0.0.87
This frame is deprecated and will be removed in a future version.
Instead, use `DailyInputTransportMessageFrame`.
Parameters:
participant_id: Optional ID of the participant this message is for/from.
"""
def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"DailyInputTransportMessageUrgentFrame is deprecated and will be removed in a future version. "
"Instead, use DailyInputTransportMessageFrame.",
DeprecationWarning,
stacklevel=2,
)
@dataclass @dataclass
class DailyUpdateRemoteParticipantsFrame(ControlFrame): class DailyUpdateRemoteParticipantsFrame(ControlFrame):
"""Frame to update remote participants in Daily calls. """Frame to update remote participants in Daily calls.
@@ -474,7 +551,9 @@ class DailyTransportClient(EventHandler):
""" """
return self._out_sample_rate return self._out_sample_rate
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send an application message to participants. """Send an application message to participants.
Args: Args:
@@ -484,7 +563,9 @@ class DailyTransportClient(EventHandler):
return return
participant_id = None participant_id = None
if isinstance(frame, (DailyTransportMessageFrame, DailyTransportMessageUrgentFrame)): if isinstance(
frame, (DailyOutputTransportMessageFrame, DailyOutputTransportMessageUrgentFrame)
):
participant_id = frame.participant_id participant_id = frame.participant_id
future = self._get_event_loop().create_future() future = self._get_event_loop().create_future()
@@ -1621,7 +1702,7 @@ class DailyInputTransport(BaseInputTransport):
message: The message data to send. message: The message data to send.
sender: ID of the message sender. sender: ID of the message sender.
""" """
frame = DailyInputTransportMessageUrgentFrame(message=message, participant_id=sender) frame = DailyInputTransportMessageFrame(message=message, participant_id=sender)
await self.push_frame(frame) await self.push_frame(frame)
# #
@@ -1843,7 +1924,9 @@ class DailyOutputTransport(BaseOutputTransport):
if isinstance(frame, DailyUpdateRemoteParticipantsFrame): if isinstance(frame, DailyUpdateRemoteParticipantsFrame):
await self._client.update_remote_participants(frame.remote_participants) await self._client.update_remote_participants(frame.remote_participants)
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a transport message to participants. """Send a transport message to participants.
Args: Args:

View File

@@ -29,9 +29,9 @@ from pipecat.frames.frames import (
OutputAudioRawFrame, OutputAudioRawFrame,
OutputDTMFFrame, OutputDTMFFrame,
OutputDTMFUrgentFrame, OutputDTMFUrgentFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
UserAudioRawFrame, UserAudioRawFrame,
UserImageRawFrame, UserImageRawFrame,
) )
@@ -68,7 +68,7 @@ DTMF_CODE_MAP = {
@dataclass @dataclass
class LiveKitTransportMessageFrame(TransportMessageFrame): class LiveKitOutputTransportMessageFrame(OutputTransportMessageFrame):
"""Frame for transport messages in LiveKit rooms. """Frame for transport messages in LiveKit rooms.
Parameters: Parameters:
@@ -79,7 +79,7 @@ class LiveKitTransportMessageFrame(TransportMessageFrame):
@dataclass @dataclass
class LiveKitTransportMessageUrgentFrame(TransportMessageUrgentFrame): class LiveKitOutputTransportMessageUrgentFrame(OutputTransportMessageUrgentFrame):
"""Frame for urgent transport messages in LiveKit rooms. """Frame for urgent transport messages in LiveKit rooms.
Parameters: Parameters:
@@ -89,6 +89,50 @@ class LiveKitTransportMessageUrgentFrame(TransportMessageUrgentFrame):
participant_id: Optional[str] = None participant_id: Optional[str] = None
@dataclass
class LiveKitTransportMessageFrame(LiveKitOutputTransportMessageFrame):
"""Frame for transport messages in LiveKit rooms.
Parameters:
participant_id: Optional ID of the participant this message is for/from.
"""
def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"LiveKitTransportMessageFrame is deprecated and will be removed in a future version. "
"Instead, use LiveKitOutputTransportMessageFrame.",
DeprecationWarning,
stacklevel=2,
)
@dataclass
class LiveKitTransportMessageUrgentFrame(LiveKitOutputTransportMessageUrgentFrame):
"""Frame for urgent transport messages in LiveKit rooms.
Parameters:
participant_id: Optional ID of the participant this message is for/from.
"""
def __post_init__(self):
super().__post_init__()
import warnings
with warnings.catch_warnings():
warnings.simplefilter("always")
warnings.warn(
"LiveKitTransportMessageUrgentFrame is deprecated and will be removed in a future version. "
"Instead, use LiveKitOutputTransportMessageUrgentFrame.",
DeprecationWarning,
stacklevel=2,
)
class LiveKitParams(TransportParams): class LiveKitParams(TransportParams):
"""Configuration parameters for LiveKit transport. """Configuration parameters for LiveKit transport.
@@ -677,7 +721,7 @@ class LiveKitInputTransport(BaseInputTransport):
message: The message data to send. message: The message data to send.
sender: ID of the message sender. sender: ID of the message sender.
""" """
frame = LiveKitTransportMessageUrgentFrame(message=message, participant_id=sender) frame = LiveKitOutputTransportMessageUrgentFrame(message=message, participant_id=sender)
await self.push_frame(frame) await self.push_frame(frame)
async def _audio_in_task_handler(self): async def _audio_in_task_handler(self):
@@ -836,7 +880,9 @@ class LiveKitOutputTransport(BaseOutputTransport):
await super().cleanup() await super().cleanup()
await self._transport.cleanup() await self._transport.cleanup()
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a transport message to participants. """Send a transport message to participants.
Args: Args:
@@ -846,7 +892,9 @@ class LiveKitOutputTransport(BaseOutputTransport):
if isinstance(message, dict): if isinstance(message, dict):
# fix message encoding for dict-like messages, e.g. RTVI messages. # fix message encoding for dict-like messages, e.g. RTVI messages.
message = json.dumps(message, ensure_ascii=False) message = json.dumps(message, ensure_ascii=False)
if isinstance(frame, (LiveKitTransportMessageFrame, LiveKitTransportMessageUrgentFrame)): if isinstance(
frame, (LiveKitOutputTransportMessageFrame, LiveKitOutputTransportMessageUrgentFrame)
):
await self._client.send_data(message.encode(), frame.participant_id) await self._client.send_data(message.encode(), frame.participant_id)
else: else:
await self._client.send_data(message.encode()) await self._client.send_data(message.encode())
@@ -1105,7 +1153,9 @@ class LiveKitTransport(BaseTransport):
participant_id: Optional specific participant to send to. participant_id: Optional specific participant to send to.
""" """
if self._output: if self._output:
frame = LiveKitTransportMessageFrame(message=message, participant_id=participant_id) frame = LiveKitOutputTransportMessageFrame(
message=message, participant_id=participant_id
)
await self._output.send_message(frame) await self._output.send_message(frame)
async def send_message_urgent(self, message: str, participant_id: Optional[str] = None): async def send_message_urgent(self, message: str, participant_id: Optional[str] = None):
@@ -1116,7 +1166,7 @@ class LiveKitTransport(BaseTransport):
participant_id: Optional specific participant to send to. participant_id: Optional specific participant to send to.
""" """
if self._output: if self._output:
frame = LiveKitTransportMessageUrgentFrame( frame = LiveKitOutputTransportMessageUrgentFrame(
message=message, participant_id=participant_id message=message, participant_id=participant_id
) )
await self._output.send_message(frame) await self._output.send_message(frame)

View File

@@ -26,13 +26,13 @@ from pipecat.frames.frames import (
EndFrame, EndFrame,
Frame, Frame,
InputAudioRawFrame, InputAudioRawFrame,
InputTransportMessageUrgentFrame, InputTransportMessageFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputImageRawFrame, OutputImageRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
SpriteFrame, SpriteFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
UserImageRawFrame, UserImageRawFrame,
UserImageRequestFrame, UserImageRequestFrame,
) )
@@ -461,7 +461,9 @@ class SmallWebRTCClient:
await self._webrtc_connection.disconnect() await self._webrtc_connection.disconnect()
await self._handle_peer_disconnected() await self._handle_peer_disconnected()
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send an application message through the WebRTC connection. """Send an application message through the WebRTC connection.
Args: Args:
@@ -683,7 +685,7 @@ class SmallWebRTCInputTransport(BaseInputTransport):
message: The application message to process. message: The application message to process.
""" """
logger.debug(f"Received app message inside SmallWebRTCInputTransport {message}") logger.debug(f"Received app message inside SmallWebRTCInputTransport {message}")
frame = InputTransportMessageUrgentFrame(message=message) frame = InputTransportMessageFrame(message=message)
await self.push_frame(frame) await self.push_frame(frame)
# Add this method similar to DailyInputTransport.request_participant_image # Add this method similar to DailyInputTransport.request_participant_image
@@ -820,7 +822,9 @@ class SmallWebRTCOutputTransport(BaseOutputTransport):
await super().cancel(frame) await super().cancel(frame)
await self._client.disconnect() await self._client.disconnect()
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a transport message through the WebRTC connection. """Send a transport message through the WebRTC connection.
Args: Args:

View File

@@ -27,9 +27,9 @@ from pipecat.frames.frames import (
InputAudioRawFrame, InputAudioRawFrame,
InterruptionFrame, InterruptionFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.processors.frame_processor import FrameDirection, FrameProcessor, FrameProcessorSetup from pipecat.processors.frame_processor import FrameDirection, FrameProcessor, FrameProcessorSetup
from pipecat.transports.base_input import BaseInputTransport from pipecat.transports.base_input import BaseInputTransport
@@ -345,7 +345,9 @@ class TavusTransportClient:
participant_id, callback, audio_source, sample_rate, callback_interval_ms participant_id, callback, audio_source, sample_rate, callback_interval_ms
) )
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a message to participants. """Send a message to participants.
Args: Args:
@@ -373,7 +375,7 @@ class TavusTransportClient:
async def send_interrupt_message(self) -> None: async def send_interrupt_message(self) -> None:
"""Send an interrupt message to the conversation.""" """Send an interrupt message to the conversation."""
transport_frame = TransportMessageUrgentFrame( transport_frame = OutputTransportMessageUrgentFrame(
message={ message={
"message_type": "conversation", "message_type": "conversation",
"event_type": "conversation.interrupt", "event_type": "conversation.interrupt",
@@ -605,7 +607,9 @@ class TavusOutputTransport(BaseOutputTransport):
await super().cancel(frame) await super().cancel(frame)
await self._client.stop() await self._client.stop()
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a message to participants. """Send a message to participants.
Args: Args:

View File

@@ -28,9 +28,9 @@ from pipecat.frames.frames import (
Frame, Frame,
InputAudioRawFrame, InputAudioRawFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.processors.frame_processor import FrameProcessorSetup from pipecat.processors.frame_processor import FrameProcessorSetup
from pipecat.serializers.base_serializer import FrameSerializer from pipecat.serializers.base_serializer import FrameSerializer
@@ -385,7 +385,9 @@ class WebsocketClientOutputTransport(BaseOutputTransport):
await super().cleanup() await super().cleanup()
await self._transport.cleanup() await self._transport.cleanup()
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a transport message through the WebSocket. """Send a transport message through the WebSocket.
Args: Args:

View File

@@ -28,9 +28,9 @@ from pipecat.frames.frames import (
InputAudioRawFrame, InputAudioRawFrame,
InterruptionFrame, InterruptionFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.processors.frame_processor import FrameDirection from pipecat.processors.frame_processor import FrameDirection
from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType
@@ -402,7 +402,9 @@ class FastAPIWebsocketOutputTransport(BaseOutputTransport):
await self._write_frame(frame) await self._write_frame(frame)
self._next_send_time = 0 self._next_send_time = 0
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a transport message frame. """Send a transport message frame.
Args: Args:

View File

@@ -27,9 +27,9 @@ from pipecat.frames.frames import (
InputAudioRawFrame, InputAudioRawFrame,
InterruptionFrame, InterruptionFrame,
OutputAudioRawFrame, OutputAudioRawFrame,
OutputTransportMessageFrame,
OutputTransportMessageUrgentFrame,
StartFrame, StartFrame,
TransportMessageFrame,
TransportMessageUrgentFrame,
) )
from pipecat.processors.frame_processor import FrameDirection from pipecat.processors.frame_processor import FrameDirection
from pipecat.serializers.base_serializer import FrameSerializer from pipecat.serializers.base_serializer import FrameSerializer
@@ -338,7 +338,9 @@ class WebsocketServerOutputTransport(BaseOutputTransport):
await self._write_frame(frame) await self._write_frame(frame)
self._next_send_time = 0 self._next_send_time = 0
async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame): async def send_message(
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
):
"""Send a transport message frame to the client. """Send a transport message frame to the client.
Args: Args:

View File

@@ -11,8 +11,8 @@ from pipecat.frames.frames import (
EndFrame, EndFrame,
Frame, Frame,
InterruptionFrame, InterruptionFrame,
OutputTransportMessageUrgentFrame,
TextFrame, TextFrame,
TransportMessageUrgentFrame,
) )
from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.pipeline import Pipeline
from pipecat.processors.filters.identity_filter import IdentityFilter from pipecat.processors.filters.identity_filter import IdentityFilter
@@ -81,7 +81,7 @@ class TestFrameProcessor(unittest.IsolatedAsyncioTestCase):
if isinstance(frame, TextFrame): if isinstance(frame, TextFrame):
await self.push_interruption_task_frame_and_wait() await self.push_interruption_task_frame_and_wait()
await self.push_frame(TransportMessageUrgentFrame(message=frame.text)) await self.push_frame(OutputTransportMessageUrgentFrame(message=frame.text))
else: else:
await self.push_frame(frame, direction) await self.push_frame(frame, direction)
@@ -101,7 +101,7 @@ class TestFrameProcessor(unittest.IsolatedAsyncioTestCase):
expected_down_frames = [ expected_down_frames = [
InterruptionFrame, InterruptionFrame,
InterruptionFrame, InterruptionFrame,
TransportMessageUrgentFrame, OutputTransportMessageUrgentFrame,
EndFrame, EndFrame,
] ]
await run_test( await run_test(