Overview

DailyTransport provides real-time audio and video communication capabilities using Daily’s WebRTC platform. It supports bidirectional audio/video streams, transcription, voice activity detection (VAD), and participant management.

Installation

To use DailyTransport, install the required dependencies:

pip install pipecat-ai[daily]

You’ll also need to set up your Daily API key as an environment variable: DAILY_API_KEY.

You can obtain a Daily API key by signing up at Daily.

Configuration

Constructor Parameters

room_url
str
required

Daily room URL

token
str | None

Daily room token

bot_name
str
required

Name of the bot in the room

params
DailyParams
default: "DailyParams()"

Transport configuration parameters

DailyParams Configuration

api_url
str
default: "https://api.daily.co/v1"

Daily API endpoint URL

api_key
str
default: ""

Daily API key for authentication

Audio Output Configuration

audio_out_enabled
bool
default: "False"

Enable audio output capabilities

audio_out_is_live
bool
default: "False"

Enable live audio streaming mode

audio_out_sample_rate
int
default: "24000"

Audio output sample rate in Hz

audio_out_channels
int
default: "1"

Number of audio output channels

audio_out_bitrate
int
default: "96000"

Audio output bitrate in bits per second

Audio Input Configuration

audio_in_enabled
bool
default: "False"

Enable audio input capabilities

audio_in_sample_rate
int
default: "16000"

Audio input sample rate in Hz

audio_in_channels
int
default: "1"

Number of audio input channels

audio_in_filter
Optional[BaseAudioFilter]
default: "None"

Audio filter for input processing. Supported filters are: KrispFilter() and NoisereduceFilter(). See the KrispFilter() reference docs and NoisereduceFilter() reference docs` for more information.

Video Output Configuration

camera_out_enabled
bool
default: "False"

Enable video output capabilities

camera_out_is_live
bool
default: "False"

Enable live video streaming mode

camera_out_width
int
default: "1024"

Video output width in pixels

camera_out_height
int
default: "768"

Video output height in pixels

camera_out_bitrate
int
default: "800000"

Video output bitrate in bits per second

camera_out_framerate
int
default: "30"

Video output frame rate

camera_out_color_format
str
default: "RGB"

Video color format (RGB, BGR, etc.)

Voice Activity Detection (VAD)

vad_enabled
bool
default: "False"

Enable voice activity detection

vad_audio_passthrough
bool
default: "False"

Pass through audio during VAD

vad_analyzer
VADAnalyzer | None
default: "None"

Voice Activity Detection analyzer. You can set this to either SileroVADAnalyzer() or WebRTCVADAnalyzer(). SileroVADAnalyzer is the recommended option. Learn more about the SileroVADAnalyzer.

Feature Settings

dialin_settings
Optional[DailyDialinSettings]
default: "None"

Configuration for dial-in functionality

transcription_enabled
bool
default: "False"

Enable real-time transcription

transcription_settings
DailyTranscriptionSettings

Configuration for transcription features

class DailyTranscriptionSettings(BaseModel):
  language: str = "en"                  # Default language
  model: str = "nova-2-general"         # Transcription model
  profanity_filter: bool = True         # Filter profanity
  redact: bool = False                  # Redact sensitive information
  endpointing: bool = True              # Enable speech endpointing
  punctuate: bool = True                # Add punctuation
  includeRawResponse: bool = True       # Include raw API response
  extra: Mapping[str, Any] = {
      "interim_results": True           # Provide any Deepgram-specific settings
  }

Basic Usage

from pipecat.transports.services.daily import DailyTransport, DailyParams
from pipecat.audio.vad.silero import SileroVADAnalyzer

# Configure transport
transport = DailyTransport(
    room_url="https://your-domain.daily.co/room-name",
    token="your-room-token",
    bot_name="AI Assistant",
    params=DailyParams(
        audio_out_enabled=True,
        vad_enabled=True,
        vad_analyzer=SileroVADAnalyzer(params=VADParams(stop_secs=0.5)),
        vad_audio_passthrough=True,
    )
)

# Use in pipeline
pipeline = Pipeline([
    transport.input(),    # Handle incoming audio/video
    stt_service,          # Speech-to-text
    llm_service,          # Language model
    tts_service,          # Text-to-speech
    transport.output()    # Handle outgoing audio/video
])

Event Callbacks

DailyTransport provides a comprehensive callback system for handling various events. Register callbacks using the @transport.event_handler() decorator.

Connection Events

on_joined
async callback

Called when the bot successfully joins the room.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing room join information
@transport.event_handler("on_joined")
async def on_joined(transport, data: Dict[str, Any]):
    logger.info(f"Joined room with data: {data}")
on_left
async callback

Called when the bot leaves the room.

Parameters:

  • transport: The DailyTransport instance
@transport.event_handler("on_left")
async def on_left(transport):
    logger.info("Left room")

Participant Events

on_first_participant_joined
async callback

Called when the first participant joins the room. Useful for initializing conversations.

Parameters:

  • transport: The DailyTransport instance
  • participant: Dictionary containing participant information
@transport.event_handler("on_first_participant_joined")
async def on_first_participant_joined(transport, participant: Dict[str, Any]):
    await transport.capture_participant_transcription(participant["id"])
    await task.queue_frames([LLMMessagesFrame(initial_messages)])
on_participant_joined
async callback

Called when any participant joins the room.

Parameters:

  • transport: The DailyTransport instance
  • participant: Dictionary containing participant information
@transport.event_handler("on_participant_joined")
async def on_participant_joined(transport, participant: Dict[str, Any]):
    logger.info(f"Participant joined: {participant['id']}")
on_participant_left
async callback

Called when a participant leaves the room.

Parameters:

  • transport: The DailyTransport instance
  • participant: Dictionary containing participant information
  • reason: String describing why the participant left, “leftCall” | “hidden”
@transport.event_handler("on_participant_left")
async def on_participant_left(transport, participant: Dict[str, Any], reason: str):
    logger.info(f"Participant {participant['id']} left: {reason}")
on_participant_updated
async callback

Event emitted when a participant is updated. This can mean either the participant’s metadata was updated, or the tracks belonging to the participant changed.

Parameters:

  • transport: The DailyTransport instance
  • participant: Dictionary containing updated participant information
@transport.event_handler("on_participant_updated")
async def on_participant_updated(transport, participant: Dict[str, Any]):
    logger.info(f"Participant updated: {participant}")

Communication Events

on_app_message
async callback

Event emitted when a custom app message is received from another participant or via the REST API.

Parameters:

  • transport: The DailyTransport instance
  • message: The message content (any type)
  • sender: String identifier of the message sender
@transport.event_handler("on_app_message")
async def on_app_message(transport, message: Any, sender: str):
    logger.info(f"Message from {sender}: {message}")
on_call_state_updated
async callback

Event emitted when the call state changes, normally as a consequence of joining or leaving the call.

Parameters:

  • transport: The DailyTransport instance
  • state: String representing the new call state. Learn more about call states.
@transport.event_handler("on_call_state_updated")
async def on_call_state_updated(transport, state: str):
    logger.info(f"Call state updated: {state}")

Dial Events

Dial-in

on_dialin_ready
async callback

Event emitted when dial-in is ready. This happens after the room has connected to the SIP endpoint and the system is ready to receive dial-in calls.

Parameters:

  • transport: The DailyTransport instance
  • sip_endpoint: String containing the SIP endpoint information
@transport.event_handler("on_dialin_ready")
async def on_dialin_ready(transport, sip_endpoint: str):
    logger.info(f"Dial-in ready at: {sip_endpoint}")
on_dialin_connected
async callback

Event emitted when the session with the dial-in remote end is established (i.e. SIP endpoint or PSTN are connectd to the Daily room).

Note: connected does not mean media (audio or video) has started flowing between the room and PSTN, it means the room received the connection request and both endpoints are negotiating the media flow.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing connection information. See DialinConnectedEvent.
@transport.event_handler("on_dialin_connected")
async def on_dialin_connected(transport, data: Any):
    logger.info(f"Dial-in connected: {data}")
on_dialin_stopped
async callback

Event emitted when the dial-in remote end disconnects the call.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing connection information. See DialinStoppedEvent.
@transport.event_handler("on_dialin_stopped")
async def on_dialin_stopped(transport, data: Any):
    logger.info(f"Dial-in stopped: {data}")
on_dialin_error
async callback

Event emitted in the case of dial-in errors which are fatal and the service cannot proceed. For example, an error in SDP negotiation is fatal to the media/SIP pipeline and will result in dialin-error being triggered.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing error information. See DialinEvent.
@transport.event_handler("on_dialin_error")
async def on_dialin_error(transport, data: Any):
    logger.error(f"Dial-in error: {data}")
on_dialin_warning
async callback

Event emitted there is a dial-in non-fatal error, such as the selected codec not being used and a fallback codec being utilized.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing warning information. See DialinEvent.
@transport.event_handler("on_dialin_warning")
async def on_dialin_warning(transport, data: Any):
    logger.warning(f"Dial-in warning: {data}")

Dial-out

on_dialout_answered
async callback

Event emitted when the session with the dial-out remote end is answered.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing call information. Learn more.
@transport.event_handler("on_dialout_answered")
async def on_dialout_answered(transport, data: Any):
    logger.info(f"Dial-out answered: {data}")
on_dialout_connected
async callback

Event emitted when the session with the dial-out remote end is established.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing connection information. Learn more.
@transport.event_handler("on_dialout_connected")
async def on_dialout_connected(transport, data: Any):
    logger.info(f"Dial-out connected: {data}")
on_dialout_stopped
async callback

Event emitted when the dial-out session is stopped.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing connection information. Learn more.
@transport.event_handler("on_dialout_stopped")
async def on_dialout_stopped(transport, data: Any):
    logger.info(f"Dial-out stopped: {data}")
on_dialout_error
async callback

Event emitted in the case of dial-out errors which are fatal and the service cannot proceed. For example, an error in SDP negotiation is fatal to the media/SIP pipeline and will result in dialout-error being triggered.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing error information.Learn more.
@transport.event_handler("on_dialout_error")
async def on_dialout_error(transport, data: Any):
    logger.error(f"Dial-out error: {data}")
on_dialout_warning
async callback

Event emitted there is a dial-out non-fatal error, such as the selected codec not being used and a fallback codec being utilized.

Parameters:

  • transport: The DailyTransport instance
  • data: Dictionary containing warning information. Learn more.
@transport.event_handler("on_dialout_warning")
async def on_dialout_warning(transport, data: Any):
    logger.warning(f"Dial-out warning: {data}")

Transcription Events

on_transcription_message
async callback

Called when a transcription message is received. This includes both interim and final transcriptions.

Parameters:

  • transport: The DailyTransport instance
  • message: Dictionary containing transcription data including. Learn more.
@transport.event_handler("on_transcription_message")
async def on_transcription_message(transport, message: Dict[str, Any]):
    participant_id = message.get("participantId")
    text = message.get("text")
    is_final = message["rawResponse"]["is_final"]
    logger.info(f"Transcription from {participant_id}: {text} (final: {is_final})")

Recording Events

on_recording_started
async callback

Called when a room recording starts successfully.

Parameters:

  • transport: The DailyTransport instance
  • status: Dictionary containing recording status information. Learn more.
@transport.event_handler("on_recording_started")
async def on_recording_started(transport, status: Dict[str, Any]):
    logger.info(f"Recording started with status: {status}")
on_recording_stopped
async callback

Called when a room recording stops.

Parameters:

  • transport: The DailyTransport instance
  • stream_id: String identifier of the stopped recording stream
@transport.event_handler("on_recording_stopped")
async def on_recording_stopped(transport, stream_id: str):
    logger.info(f"Recording stopped for stream: {stream_id}")
on_recording_error
async callback

Called when an error occurs during recording.

Parameters:

  • transport: The DailyTransport instance
  • stream_id: String identifier of the recording stream
  • message: Error message describing what went wrong
@transport.event_handler("on_recording_error")
async def on_recording_error(transport, stream_id: str, message: str):
    logger.error(f"Recording error for stream {stream_id}: {message}")

Error Events

on_error
async callback

Called when a transport error occurs.

Parameters:

  • transport: The DailyTransport instance
  • error: String containing error details
@transport.event_handler("on_error")
async def on_error(transport, error: str):
    logger.error(f"Transport error: {error}")

Notes on Callbacks

  • All callbacks are asynchronous
  • Callbacks are executed in the order they were registered
  • Multiple handlers can be registered for the same event
  • Exceptions in callbacks are logged but don’t stop the transport
  • Callbacks should be lightweight to avoid blocking the event loop
  • Heavy processing should be offloaded to separate tasks

Frame Types

Input Frames

InputAudioRawFrame
Frame

Raw audio data from participants

UserImageRawFrame
Frame

Video frames from participants

Output Frames

OutputAudioRawFrame
Frame

Audio data to be sent

OutputImageRawFrame
Frame

Video frames to be sent

Methods

Room Management

participants
method

Returns a dictionary of all participants currently in the room.

def participants() -> Dict[str, Any]

See participants for more details.

participant_counts
method

Returns participant count statistics for the room.

def participant_counts() -> Dict[str, int]

See participant_counts for more details.

Media Control

send_image
async method

Sends an image frame to the room.

async def send_image(frame: OutputImageRawFrame | SpriteFrame) -> None

Parameters:

  • frame: Image frame to send, either raw image data or sprite animation
send_audio
async method

Sends an audio frame to the room.

async def send_audio(frame: OutputAudioRawFrame) -> None

Parameters:

  • frame: Audio frame to send

Video Management

capture_participant_video
async method

Starts capturing video from a specific participant.

async def capture_participant_video( participant_id: str, framerate: int = 30, video_source: str = "camera", color_format: str = "RGB" ) -> None

Parameters:

  • participant_id: ID of the participant to capture
  • framerate: Target frame rate (default: 30)
  • video_source: Video source type (default: “camera”)
  • color_format: Color format of the video (default: “RGB”)

Transcription Control

capture_participant_transcription
async method

Starts capturing and transcribing audio from a specific participant.

async def capture_participant_transcription(participant_id: str) -> None

Parameters:

  • participant_id: ID of the participant to transcribe
update_transcription
async method

Updates the transcription configuration for specific participants or instances.

async def update_transcription(
   participants: List[str] | None = None,
   instance_id: str | None = None
) -> None

Parameters:

  • participants: Optional list of participant IDs to transcribe. If None, transcribes all participants.
  • instance_id: Optional specific transcription instance ID to update

Example:

# Update transcription for specific participants
await transport.update_transcription(participants=["participant-123", "participant-456"])
# Update specific transcription instance
await transport.update_transcription(instance_id="transcription-789")

Recording Control

start_recording
async method

Starts recording the room session.

async def start_recording( streaming_settings: Dict = None, stream_id: str = None, force_new: bool = None ) -> None

Parameters:

  • streaming_settings: Recording configuration settings
  • stream_id: Optional stream identifier
  • force_new: Force start a new recording

See start_recording for more details.

stop_recording
async method

Stops an active recording.

async def stop_recording(stream_id: str = None) -> None

Parameters:

  • stream_id: Optional stream identifier to stop specific recording

See stop_recording for more details.

Dial-out Control

start_dialout
async method

Initiates a dial-out call.

async def start_dialout(settings: Dict = None) -> None

Parameters:

  • settings: Dial-out configuration settings

See start_dialout for more details.

stop_dialout
async method

Stops an active dial-out call.

async def stop_dialout(participant_id: str) -> None

Parameters:

  • participant_id: ID of the participant to disconnect

See stop_dialout for more details.

Subscription Management

update_subscriptions
async method

Updates subscriptions and subscription profiles. This function allows you to update subscription profiles and at the same time assign specific subscription profiles to a participant and even change specific settings for some participants.

async def update_subscriptions( participant_settings: Dict = None, profile_settings: Dict = None ) -> None

Parameters:

  • participant_settings: Per-participant subscription settings
  • profile_settings: Global subscription profile settings

See update_subscriptions for more details.

Properties

participant_id
property

Returns the transport’s participant ID in the room.

@property
def participant_id() -> str

Notes

  • Supports real-time audio/video communication
  • Handles WebRTC connection management
  • Provides voice activity detection
  • Includes transcription capabilities
  • Manages participant interactions
  • Supports recording and streaming
  • Thread-safe processing
  • All callbacks are asynchronous
  • Multiple handlers can be registered for the same event
  • Exceptions in callbacks are logged but don’t stop the transport