From 3fa193b98385df41d0dd028a04bf87744e478009 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 7 May 2026 15:34:32 -0300 Subject: [PATCH 01/11] Unified start route to make all transports available. --- src/pipecat/runner/run.py | 498 ++++++++++++++++++++++---------------- 1 file changed, 283 insertions(+), 215 deletions(-) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index f3965b79c..88b518c07 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -19,6 +19,10 @@ All bots must implement a `bot(runner_args)` async function as the entry point. The server automatically discovers and executes this function when connections are established. +By default the runner starts a single FastAPI server that supports WebRTC, Daily, +and telephony transports simultaneously. Clients declare which transport they want +via the ``transport`` field in the ``/start`` request body (default: ``"webrtc"``). + Single transport example:: async def bot(runner_args: RunnerArguments): @@ -55,14 +59,33 @@ Supported transports: - WebRTC - Provides local WebRTC interface with prebuilt UI - Telephony - Handles webhook and WebSocket connections for Twilio, Telnyx, Plivo, Exotel +The ``/start`` endpoint accepts:: + + { + "transport": "webrtc", // "webrtc" | "daily" | "twilio" | "telnyx" | + // "plivo" | "exotel" — default: "webrtc" + + // WebRTC-specific + "enableDefaultIceServers": false, + "body": {...}, + + // Daily-specific + "createDailyRoom": true, + "dailyRoomProperties": {...}, + "dailyMeetingTokenProperties": {...}, + "body": {...} + } + To run locally: -- WebRTC: `python bot.py -t webrtc` -- ESP32: `python bot.py -t webrtc --esp32 --host 192.168.1.100` -- Daily (server): `python bot.py -t daily` -- Daily (direct, testing only): `python bot.py -d` -- Telephony: `python bot.py -t twilio -x your_username.ngrok.io` -- Exotel: `python bot.py -t exotel` (no proxy needed, but ngrok connection to HTTP 7860 is required) +- All transports (default): ``python bot.py`` +- WebRTC only: ``python bot.py -t webrtc`` +- ESP32: ``python bot.py -t webrtc --esp32 --host 192.168.1.100`` +- Daily only: ``python bot.py -t daily`` +- Daily (direct, testing only): ``python bot.py -d`` +- Telephony: ``python bot.py -t twilio -x your_username.ngrok.io`` +- Exotel: ``python bot.py -t exotel`` (no proxy needed, but ngrok connection to HTTP 7860 is required) +- WhatsApp: ``python bot.py --whatsapp`` """ import argparse @@ -187,7 +210,7 @@ async def _run_telephony_bot(websocket: WebSocket, args: argparse.Namespace): def _configure_server_app(args: argparse.Namespace): - """Configure the module-level FastAPI app with transport-specific routes.""" + """Configure the module-level FastAPI app with routes for all transports.""" app.add_middleware( CORSMiddleware, allow_origins=["*"], @@ -196,17 +219,178 @@ def _configure_server_app(args: argparse.Namespace): allow_headers=["*"], ) - # Set up transport-specific routes - if args.transport == "webrtc": - _setup_webrtc_routes(app, args) - if args.whatsapp: - _setup_whatsapp_routes(app, args) - elif args.transport == "daily": - _setup_daily_routes(app, args) - elif args.transport in TELEPHONY_TRANSPORTS: - _setup_telephony_routes(app, args) - else: - logger.warning(f"Unknown transport type: {args.transport}") + # Shared session store: session_id -> body data. Used by the WebRTC /start + # flow and the /sessions/{session_id}/... proxy routes. + active_sessions: dict[str, dict[str, Any]] = {} + + _setup_webrtc_routes(app, args, active_sessions) + _setup_daily_routes(app, args) + _setup_telephony_routes(app, args) + _setup_unified_start_route(app, args, active_sessions) + + if args.whatsapp: + _setup_whatsapp_routes(app, args) + + +def _setup_unified_start_route( + app: FastAPI, args: argparse.Namespace, active_sessions: dict[str, dict[str, Any]] +): + """Register the unified POST /start endpoint. + + Handles WebRTC, Daily, and telephony transport start flows. Clients specify + which transport they want via the ``transport`` field in the request body. + When ``-t`` was passed on the command line, requests for any other transport + are rejected with HTTP 400. + """ + + class IceServer(TypedDict, total=False): + urls: str | list[str] + + class IceConfig(TypedDict): + iceServers: list[IceServer] + + class StartBotResult(TypedDict, total=False): + sessionId: str + iceConfig: IceConfig | None + dailyRoom: str | None + dailyToken: str | None + websocketUrl: str | None + + @app.post("/start") + async def start_agent(request: Request): + """Start a bot session. + + Accepts:: + + { + "transport": "webrtc", // "webrtc" | "daily" | "twilio" | "telnyx" | + // "plivo" | "exotel" — default: "webrtc" + + // WebRTC-specific + "enableDefaultIceServers": false, + "body": {...}, + + // Daily-specific + "createDailyRoom": true, + "dailyRoomProperties": {...}, + "dailyMeetingTokenProperties": {...}, + "body": {...} + } + """ + try: + request_data = await request.json() + logger.debug(f"Received request: {request_data}") + except Exception as e: + logger.error(f"Failed to parse request body: {e}") + request_data = {} + + # Determine transport: explicit field → legacy Daily hint → CLI default → webrtc + transport = request_data.get("transport") + if transport is None and request_data.get("createDailyRoom", False): + transport = "daily" + if transport is None: + transport = args.transport or "webrtc" + + # Enforce restriction when -t was explicitly set on the command line + if args.transport is not None and transport != args.transport: + raise HTTPException( + status_code=400, + detail=( + f"Transport '{transport}' is not allowed. " + f"Server is configured for '{args.transport}' only (-t {args.transport})." + ), + ) + + if transport == "webrtc": + # WebRTC: register the session; the bot starts when the WebRTC offer arrives. + session_id = str(uuid.uuid4()) + active_sessions[session_id] = request_data.get("body", {}) + + result: StartBotResult = {"sessionId": session_id} + if request_data.get("enableDefaultIceServers"): + result["iceConfig"] = IceConfig( + iceServers=[IceServer(urls=["stun:stun.l.google.com:19302"])] + ) + return result + + elif transport == "daily": + create_daily_room = request_data.get("createDailyRoom", False) + body = request_data.get("body", {}) + daily_room_properties_dict = request_data.get("dailyRoomProperties", None) + daily_token_properties_dict = request_data.get("dailyMeetingTokenProperties", None) + + bot_module = _get_bot_module() + + existing_room_url = os.getenv("DAILY_ROOM_URL") + session_id = str(uuid.uuid4()) + result = None + + if create_daily_room or existing_room_url: + from pipecat.runner.daily import configure + from pipecat.transports.daily.utils import ( + DailyMeetingTokenProperties, + DailyRoomProperties, + ) + + async with aiohttp.ClientSession() as session: + room_properties = None + if daily_room_properties_dict: + daily_room_properties_dict.setdefault( + "exp", time.time() + PIPECAT_ROOM_EXP_HOURS * 3600 + ) + daily_room_properties_dict.setdefault("eject_at_room_exp", True) + try: + room_properties = DailyRoomProperties(**daily_room_properties_dict) + logger.debug(f"Using custom room properties: {room_properties}") + except Exception as e: + logger.error(f"Failed to parse dailyRoomProperties: {e}") + + token_properties = None + if daily_token_properties_dict: + try: + token_properties = DailyMeetingTokenProperties( + **daily_token_properties_dict + ) + logger.debug(f"Using custom token properties: {token_properties}") + except Exception as e: + logger.error(f"Failed to parse dailyMeetingTokenProperties: {e}") + + room_url, token = await configure( + session, + room_exp_duration=PIPECAT_ROOM_EXP_HOURS, + room_properties=room_properties, + token_properties=token_properties, + ) + runner_args = DailyRunnerArguments( + room_url=room_url, token=token, body=body, session_id=session_id + ) + result = { + "dailyRoom": room_url, + "dailyToken": token, + "sessionId": session_id, + } + else: + runner_args = RunnerArguments(body=body, session_id=session_id) + + runner_args.cli_args = args + asyncio.create_task(bot_module.bot(runner_args)) + return result + + elif transport in TELEPHONY_TRANSPORTS: + # Telephony: the bot starts when the provider connects to /ws. + # Return the WebSocket URL so the caller knows where to point their provider. + session_id = str(uuid.uuid4()) + scheme = "wss" if args.host != "localhost" else "ws" + return StartBotResult( + sessionId=session_id, + websocketUrl=f"{scheme}://{args.host}:{args.port}/ws", + ) + + else: + raise HTTPException( + status_code=400, + detail=f"Unknown transport '{transport}'.", + ) def _resolve_download_path(folder: str, filename: str) -> Path: @@ -220,7 +404,9 @@ def _resolve_download_path(folder: str, filename: str) -> Path: return file_path -def _setup_webrtc_routes(app: FastAPI, args: argparse.Namespace): +def _setup_webrtc_routes( + app: FastAPI, args: argparse.Namespace, active_sessions: dict[str, dict[str, Any]] +): """Set up WebRTC-specific routes.""" try: from pipecat_ai_small_webrtc_prebuilt.frontend import SmallWebRTCPrebuiltUI @@ -236,19 +422,6 @@ def _setup_webrtc_routes(app: FastAPI, args: argparse.Namespace): logger.error(f"WebRTC transport dependencies not installed: {e}") return - class IceServer(TypedDict, total=False): - urls: str | list[str] - - class IceConfig(TypedDict): - iceServers: list[IceServer] - - class StartBotResult(TypedDict, total=False): - sessionId: str - iceConfig: IceConfig | None - - # In-memory store of active sessions: session_id -> session info - active_sessions: dict[str, dict[str, Any]] = {} - # Mount the frontend app.mount("/client", SmallWebRTCPrebuiltUI) @@ -315,29 +488,6 @@ def _setup_webrtc_routes(app: FastAPI, args: argparse.Namespace): await small_webrtc_handler.handle_patch_request(request) return {"status": "success"} - @app.post("/start") - async def rtvi_start(request: Request): - """Mimic Pipecat Cloud's /start endpoint.""" - # Parse the request body - try: - request_data = await request.json() - logger.debug(f"Received request: {request_data}") - except Exception as e: - logger.error(f"Failed to parse request body: {e}") - request_data = {} - - # Store session info immediately in memory, replicate the behavior expected on Pipecat Cloud - session_id = str(uuid.uuid4()) - active_sessions[session_id] = request_data.get("body", {}) - - result: StartBotResult = {"sessionId": session_id} - if request_data.get("enableDefaultIceServers"): - result["iceConfig"] = IceConfig( - iceServers=[IceServer(urls=["stun:stun.l.google.com:19302"])] - ) - - return result - @app.api_route( "/sessions/{session_id}/{path:path}", methods=["GET", "POST", "PUT", "PATCH", "DELETE"], @@ -563,12 +713,10 @@ def _setup_whatsapp_routes(app: FastAPI, args: argparse.Namespace): def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): """Set up Daily-specific routes.""" - @app.get("/") + @app.get("/daily") async def create_room_and_start_agent(): """Launch a Daily bot and redirect to room.""" - print("Starting bot with Daily transport and redirecting to Daily room") - - import aiohttp + logger.debug("Starting bot with Daily transport and redirecting to Daily room") from pipecat.runner.daily import configure @@ -584,105 +732,6 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): asyncio.create_task(bot_module.bot(runner_args)) return RedirectResponse(room_url) - @app.post("/start") - async def start_agent(request: Request): - """Handler for /start endpoints. - - Expects POST body like:: - { - "createDailyRoom": true, - "dailyRoomProperties": { "start_video_off": true }, - "dailyMeetingTokenProperties": { "is_owner": true, "user_name": "Bot" }, - "body": { "custom_data": "value" } - } - """ - print("Starting bot with Daily transport") - - # Parse the request body - try: - request_data = await request.json() - logger.debug(f"Received request: {request_data}") - except Exception as e: - logger.error(f"Failed to parse request body: {e}") - request_data = {} - - create_daily_room = request_data.get("createDailyRoom", False) - body = request_data.get("body", {}) - daily_room_properties_dict = request_data.get("dailyRoomProperties", None) - daily_token_properties_dict = request_data.get("dailyMeetingTokenProperties", None) - - bot_module = _get_bot_module() - - existing_room_url = os.getenv("DAILY_ROOM_URL") - - session_id = str(uuid.uuid4()) - result = None - - # Configure room if: - # 1. Explicitly requested via createDailyRoom in payload - # 2. Using pre-configured room from DAILY_ROOM_URL env var - if create_daily_room or existing_room_url: - import aiohttp - - from pipecat.runner.daily import configure - from pipecat.transports.daily.utils import ( - DailyMeetingTokenProperties, - DailyRoomProperties, - ) - - async with aiohttp.ClientSession() as session: - # Parse dailyRoomProperties if provided - room_properties = None - if daily_room_properties_dict: - # Apply Pipecat Cloud's session policy if caller didn't override. - daily_room_properties_dict.setdefault( - "exp", time.time() + PIPECAT_ROOM_EXP_HOURS * 3600 - ) - daily_room_properties_dict.setdefault("eject_at_room_exp", True) - try: - room_properties = DailyRoomProperties(**daily_room_properties_dict) - logger.debug(f"Using custom room properties: {room_properties}") - except Exception as e: - logger.error(f"Failed to parse dailyRoomProperties: {e}") - # Continue without custom properties - - # Parse dailyMeetingTokenProperties if provided - token_properties = None - if daily_token_properties_dict: - try: - token_properties = DailyMeetingTokenProperties( - **daily_token_properties_dict - ) - logger.debug(f"Using custom token properties: {token_properties}") - except Exception as e: - logger.error(f"Failed to parse dailyMeetingTokenProperties: {e}") - # Continue without custom properties - - room_url, token = await configure( - session, - room_exp_duration=PIPECAT_ROOM_EXP_HOURS, - room_properties=room_properties, - token_properties=token_properties, - ) - runner_args = DailyRunnerArguments( - room_url=room_url, token=token, body=body, session_id=session_id - ) - result = { - "dailyRoom": room_url, - "dailyToken": token, - "sessionId": session_id, - } - else: - runner_args = RunnerArguments(body=body, session_id=session_id) - - # Update CLI args. - runner_args.cli_args = args - - # Start the bot in the background - asyncio.create_task(bot_module.bot(runner_args)) - - return result - if args.dialin: @app.post("/daily-dialin-webhook") @@ -731,8 +780,6 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): detail="Missing required fields: From, To, callId, callDomain", ) - import aiohttp - from pipecat.runner.daily import configure from pipecat.runner.types import DailyDialinRequest, DialinSettings @@ -801,44 +848,51 @@ def _setup_daily_routes(app: FastAPI, args: argparse.Namespace): def _setup_telephony_routes(app: FastAPI, args: argparse.Namespace): - """Set up telephony-specific routes.""" - # XML response templates (Exotel doesn't use XML webhooks) - XML_TEMPLATES = { - "twilio": f""" + """Set up telephony-specific routes. + + The WebSocket endpoint (``/ws``) is always registered so providers can + connect directly. The XML webhook (``POST /``) is only registered when a + specific telephony transport is chosen via ``-t`` because the XML template + is provider-specific and requires a proxy hostname (``--proxy``). + """ + if args.transport in TELEPHONY_TRANSPORTS: + # XML response templates (Exotel doesn't use XML webhooks) + XML_TEMPLATES = { + "twilio": f""" """, - "telnyx": f""" + "telnyx": f""" """, - "plivo": f""" + "plivo": f""" wss://{args.proxy}/ws """, - } + } - @app.post("/") - async def start_call(): - """Handle telephony webhook and return XML response.""" - if args.transport == "exotel": - # Exotel doesn't use POST webhooks - redirect to proper documentation - logger.debug("POST Exotel endpoint - not used") - return { - "error": "Exotel doesn't use POST webhooks", - "websocket_url": f"wss://{args.proxy}/ws", - "note": "Configure the WebSocket URL above in your Exotel App Bazaar Voicebot Applet", - } - else: - logger.debug(f"POST {args.transport.upper()} XML") - xml_content = XML_TEMPLATES.get(args.transport, "") - return HTMLResponse(content=xml_content, media_type="application/xml") + @app.post("/") + async def start_call(): + """Handle telephony webhook and return XML response.""" + if args.transport == "exotel": + # Exotel doesn't use POST webhooks - redirect to proper documentation + logger.debug("POST Exotel endpoint - not used") + return { + "error": "Exotel doesn't use POST webhooks", + "websocket_url": f"wss://{args.proxy}/ws", + "note": "Configure the WebSocket URL above in your Exotel App Bazaar Voicebot Applet", + } + else: + logger.debug(f"POST {args.transport.upper()} XML") + xml_content = XML_TEMPLATES.get(args.transport, "") + return HTMLResponse(content=xml_content, media_type="application/xml") @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): @@ -847,11 +901,6 @@ def _setup_telephony_routes(app: FastAPI, args: argparse.Namespace): logger.debug("WebSocket connection accepted") await _run_telephony_bot(websocket, args) - @app.get("/") - async def start_agent(): - """Simple status endpoint for telephony transports.""" - return {"status": f"Bot started with {args.transport}"} - async def _run_daily_direct(args: argparse.Namespace): """Run Daily bot with direct connection (no FastAPI server).""" @@ -922,22 +971,27 @@ def runner_port() -> int: def main(parser: argparse.ArgumentParser | None = None): """Start the Pipecat development runner. - Parses command-line arguments and starts a FastAPI server configured - for the specified transport type. + Parses command-line arguments and starts a FastAPI server that supports + WebRTC, Daily, and telephony transports simultaneously. Clients declare + which transport to use via the ``transport`` field in the ``/start`` body. + + When ``-t`` is provided, the server restricts ``/start`` to that transport + only and displays transport-specific startup information. The runner discovers and runs any ``bot(runner_args)`` function found in the calling module. Command-line arguments: - - --host: Server host address (default: localhost) 879 + - --host: Server host address (default: localhost) - --port: Server port (default: 7860) - - -t/--transport: Transport type (daily, webrtc, twilio, telnyx, plivo, exotel) + - -t/--transport: Restrict to a single transport and set as default for /start + (daily, webrtc, twilio, telnyx, plivo, exotel). Omit to support all transports. - -x/--proxy: Public proxy hostname for telephony webhooks - -d/--direct: Connect directly to Daily room (automatically sets transport to daily) - -f/--folder: Path to downloads folder - - --dialin: Enable Daily PSTN dial-in webhook handling (requires Daily transport) + - --dialin: Enable Daily PSTN dial-in webhook handling - --esp32: Enable SDP munging for ESP32 compatibility (requires --host with IP address) - - --whatsapp: Ensure requried WhatsApp environment variables are present + - --whatsapp: Ensure required WhatsApp environment variables are present - -v/--verbose: Increase logging verbosity Args: @@ -958,8 +1012,11 @@ def main(parser: argparse.ArgumentParser | None = None): "--transport", type=str, choices=["daily", "webrtc", *TELEPHONY_TRANSPORTS], - default="webrtc", - help="Transport type", + default=None, + help=( + "Restrict the server to a single transport and set it as the default for /start. " + "Omit to support all transports simultaneously (default behaviour)." + ), ) parser.add_argument("-x", "--proxy", help="Public proxy host name") parser.add_argument( @@ -977,7 +1034,7 @@ def main(parser: argparse.ArgumentParser | None = None): "--dialin", action="store_true", default=False, - help="Enable Daily PSTN dial-in webhook handling (requires Daily transport)", + help="Enable Daily PSTN dial-in webhook handling", ) parser.add_argument( "--esp32", @@ -989,7 +1046,7 @@ def main(parser: argparse.ArgumentParser | None = None): "--whatsapp", action="store_true", default=False, - help="Ensure requried WhatsApp environment variables are present", + help="Ensure required WhatsApp environment variables are present", ) args = parser.parse_args() @@ -998,12 +1055,13 @@ def main(parser: argparse.ArgumentParser | None = None): if args.proxy: args.proxy = _validate_and_clean_proxy(args.proxy) - # Auto-set transport to daily if --direct is used without explicit transport - if args.direct and args.transport == "webrtc": # webrtc is the default - args.transport = "daily" - elif args.direct and args.transport != "daily": - logger.error("--direct flag only works with Daily transport (-t daily)") - return + # --direct implies Daily transport + if args.direct: + if args.transport is None or args.transport == "daily": + args.transport = "daily" + else: + logger.error("--direct flag only works with Daily transport (-t daily)") + return # Validate ESP32 requirements if args.esp32 and args.host == "localhost": @@ -1011,7 +1069,7 @@ def main(parser: argparse.ArgumentParser | None = None): return # Validate dial-in requirements - if args.dialin and args.transport != "daily": + if args.dialin and args.transport is not None and args.transport != "daily": logger.error("--dialin flag only works with Daily transport (-t daily)") return @@ -1029,28 +1087,38 @@ def main(parser: argparse.ArgumentParser | None = None): asyncio.run(_run_daily_direct(args)) return - # Print startup message for server-based transports - if args.transport == "webrtc": - print() + # Print startup message + print() + if args.transport is None: + print("🚀 Bot ready!") + print(f" → WebRTC: http://{args.host}:{args.port}/client") + print(f" → Daily: http://{args.host}:{args.port}/daily") + print(f" → Telephony: ws://{args.host}:{args.port}/ws") + elif args.transport == "webrtc": if args.esp32: - print(f"🚀 Bot ready! (ESP32 mode)") + print("🚀 Bot ready! (ESP32 mode)") elif args.whatsapp: - print(f"🚀 Bot ready! (WhatsApp)") + print("🚀 Bot ready! (WhatsApp)") else: - print(f"🚀 Bot ready!") + print("🚀 Bot ready! (WebRTC)") print(f" → Open http://{args.host}:{args.port}/client in your browser") - print() elif args.transport == "daily": - print() - print(f"🚀 Bot ready!") + print("🚀 Bot ready! (Daily)") if args.dialin: print( f" → Daily dial-in webhook: http://{args.host}:{args.port}/daily-dialin-webhook" ) print(f" → Configure this URL in your Daily phone number settings") else: - print(f" → Open http://{args.host}:{args.port} in your browser to start a session") - print() + print( + f" → Open http://{args.host}:{args.port}/daily in your browser to start a session" + ) + elif args.transport in TELEPHONY_TRANSPORTS: + print(f"🚀 Bot ready! ({args.transport.capitalize()})") + if args.proxy: + print(f" → XML webhook: http://{args.host}:{args.port}/") + print(f" → WebSocket: ws://{args.host}:{args.port}/ws") + print() RUNNER_DOWNLOADS_FOLDER = args.folder RUNNER_HOST = args.host From 1eade184f1e358d37461ec759ac6ba53219d3c54 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 7 May 2026 15:53:15 -0300 Subject: [PATCH 02/11] Creating a status endpoint to return the available transports. --- src/pipecat/runner/run.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index 88b518c07..b8405b0c9 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -235,13 +235,20 @@ def _configure_server_app(args: argparse.Namespace): def _setup_unified_start_route( app: FastAPI, args: argparse.Namespace, active_sessions: dict[str, dict[str, Any]] ): - """Register the unified POST /start endpoint. + """Register the unified POST /start and GET /status endpoints. Handles WebRTC, Daily, and telephony transport start flows. Clients specify which transport they want via the ``transport`` field in the request body. When ``-t`` was passed on the command line, requests for any other transport are rejected with HTTP 400. """ + ALL_TRANSPORTS = ["webrtc", "daily", *TELEPHONY_TRANSPORTS] + + @app.get("/status") + async def status(): + """Return the transports supported by this runner instance.""" + transports = [args.transport] if args.transport is not None else ALL_TRANSPORTS + return {"status": "ready", "transports": transports} class IceServer(TypedDict, total=False): urls: str | list[str] From d39beff8178b0d310d3b26a507cc66b774b098dd Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 7 May 2026 16:01:54 -0300 Subject: [PATCH 03/11] Fixing format. --- src/pipecat/runner/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index b8405b0c9..29697a5d5 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -313,7 +313,7 @@ def _setup_unified_start_route( session_id = str(uuid.uuid4()) active_sessions[session_id] = request_data.get("body", {}) - result: StartBotResult = {"sessionId": session_id} + result = {"sessionId": session_id} if request_data.get("enableDefaultIceServers"): result["iceConfig"] = IceConfig( iceServers=[IceServer(urls=["stun:stun.l.google.com:19302"])] @@ -330,7 +330,7 @@ def _setup_unified_start_route( existing_room_url = os.getenv("DAILY_ROOM_URL") session_id = str(uuid.uuid4()) - result = None + result: StartBotResult | None = None if create_daily_room or existing_room_url: from pipecat.runner.daily import configure From cb426cbb145f0ff12f5a525a5748e7ec0508a845 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 7 May 2026 16:04:43 -0300 Subject: [PATCH 04/11] Fixing format. --- src/pipecat/runner/run.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index 29697a5d5..1c6e53c8d 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -313,7 +313,9 @@ def _setup_unified_start_route( session_id = str(uuid.uuid4()) active_sessions[session_id] = request_data.get("body", {}) - result = {"sessionId": session_id} + result = StartBotResult( + sessionId=session_id, + ) if request_data.get("enableDefaultIceServers"): result["iceConfig"] = IceConfig( iceServers=[IceServer(urls=["stun:stun.l.google.com:19302"])] @@ -371,11 +373,11 @@ def _setup_unified_start_route( runner_args = DailyRunnerArguments( room_url=room_url, token=token, body=body, session_id=session_id ) - result = { - "dailyRoom": room_url, - "dailyToken": token, - "sessionId": session_id, - } + result = StartBotResult( + dailyRoom=room_url, + dailyToken=token, + sessionId=session_id, + ) else: runner_args = RunnerArguments(body=body, session_id=session_id) From 2638885c62e9f0523678a8e3dd375be2457ab4db Mon Sep 17 00:00:00 2001 From: filipi87 Date: Fri, 8 May 2026 09:37:07 -0300 Subject: [PATCH 05/11] Adding support for the plain websocket transport. --- src/pipecat/runner/run.py | 41 ++++++++++++++++++++++++++++++++----- src/pipecat/runner/types.py | 4 ++++ src/pipecat/runner/utils.py | 6 ++++++ 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index 1c6e53c8d..62d2c4f4e 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -209,6 +209,31 @@ async def _run_telephony_bot(websocket: WebSocket, args: argparse.Namespace): await bot_module.bot(runner_args) +async def _run_websocket_bot(websocket: WebSocket, args: argparse.Namespace): + """Run a bot for plain WebSocket transport.""" + bot_module = _get_bot_module() + + runner_args = WebSocketRunnerArguments( + websocket=websocket, + transport_type="websocket", + session_id=str(uuid.uuid4()), + ) + runner_args.cli_args = args + + await bot_module.bot(runner_args) + + +def _setup_websocket_routes(app: FastAPI, args: argparse.Namespace): + """Set up the plain WebSocket route at ``/ws-client``.""" + + @app.websocket("/ws-client") + async def websocket_client_endpoint(websocket: WebSocket): + """Handle plain WebSocket connections (non-telephony).""" + await websocket.accept() + logger.debug("Plain WebSocket connection accepted") + await _run_websocket_bot(websocket, args) + + def _configure_server_app(args: argparse.Namespace): """Configure the module-level FastAPI app with routes for all transports.""" app.add_middleware( @@ -226,6 +251,7 @@ def _configure_server_app(args: argparse.Namespace): _setup_webrtc_routes(app, args, active_sessions) _setup_daily_routes(app, args) _setup_telephony_routes(app, args) + _setup_websocket_routes(app, args) _setup_unified_start_route(app, args, active_sessions) if args.whatsapp: @@ -242,7 +268,7 @@ def _setup_unified_start_route( When ``-t`` was passed on the command line, requests for any other transport are rejected with HTTP 400. """ - ALL_TRANSPORTS = ["webrtc", "daily", *TELEPHONY_TRANSPORTS] + ALL_TRANSPORTS = ["webrtc", "daily", *TELEPHONY_TRANSPORTS, "websocket"] @app.get("/status") async def status(): @@ -261,7 +287,7 @@ def _setup_unified_start_route( iceConfig: IceConfig | None dailyRoom: str | None dailyToken: str | None - websocketUrl: str | None + wsUrl: str | None @app.post("/start") async def start_agent(request: Request): @@ -388,11 +414,16 @@ def _setup_unified_start_route( elif transport in TELEPHONY_TRANSPORTS: # Telephony: the bot starts when the provider connects to /ws. # Return the WebSocket URL so the caller knows where to point their provider. - session_id = str(uuid.uuid4()) scheme = "wss" if args.host != "localhost" else "ws" return StartBotResult( - sessionId=session_id, - websocketUrl=f"{scheme}://{args.host}:{args.port}/ws", + wsUrl=f"{scheme}://{args.host}:{args.port}/ws", + ) + + elif transport == "websocket": + # Plain WebSocket: the bot starts when the client connects to /ws-client. + scheme = "wss" if args.host != "localhost" else "ws" + return StartBotResult( + wsUrl=f"{scheme}://{args.host}:{args.port}/ws-client", ) else: diff --git a/src/pipecat/runner/types.py b/src/pipecat/runner/types.py index 70ce03f29..b6bdd0014 100644 --- a/src/pipecat/runner/types.py +++ b/src/pipecat/runner/types.py @@ -105,10 +105,14 @@ class WebSocketRunnerArguments(RunnerArguments): Parameters: websocket: WebSocket connection for audio streaming + transport_type: Transport type identifier. Set to ``"websocket"`` for plain + WebSocket connections; ``None`` triggers auto-detection from the first + telephony provider message. body: Additional request data """ websocket: WebSocket + transport_type: str | None = None @dataclass diff --git a/src/pipecat/runner/utils.py b/src/pipecat/runner/utils.py index 84316a743..196a4e667 100644 --- a/src/pipecat/runner/utils.py +++ b/src/pipecat/runner/utils.py @@ -568,6 +568,12 @@ async def create_transport( ) elif isinstance(runner_args, WebSocketRunnerArguments): + if runner_args.transport_type == "websocket": + params = _get_transport_params("websocket", transport_params) + from pipecat.transports.websocket.fastapi import FastAPIWebsocketTransport + + return FastAPIWebsocketTransport(websocket=runner_args.websocket, params=params) + # Parse once to determine the provider and get data transport_type, call_data = await parse_telephony_websocket(runner_args.websocket) params = _get_transport_params(transport_type, transport_params) From c9f0172e9f47f4996d8eda90936309785f1f8a4a Mon Sep 17 00:00:00 2001 From: filipi87 Date: Fri, 8 May 2026 09:46:18 -0300 Subject: [PATCH 06/11] Example supporting plain websocket. --- examples/voice/voice-elevenlabs.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/voice/voice-elevenlabs.py b/examples/voice/voice-elevenlabs.py index 8f61bb665..f3b28e709 100644 --- a/examples/voice/voice-elevenlabs.py +++ b/examples/voice/voice-elevenlabs.py @@ -22,6 +22,7 @@ from pipecat.processors.aggregators.llm_response_universal import ( ) from pipecat.runner.types import RunnerArguments from pipecat.runner.utils import create_transport +from pipecat.serializers.protobuf import ProtobufFrameSerializer from pipecat.services.elevenlabs.stt import ElevenLabsRealtimeSTTService from pipecat.services.elevenlabs.tts import ElevenLabsTTSService from pipecat.services.openai.llm import OpenAILLMService @@ -47,6 +48,12 @@ transport_params = { audio_in_enabled=True, audio_out_enabled=True, ), + "websocket": lambda: FastAPIWebsocketParams( + audio_in_enabled=True, + audio_out_enabled=True, + add_wav_header=False, + serializer=ProtobufFrameSerializer(), + ), } From 33b73df6ec37a648d52495cc3a6437a260c3292a Mon Sep 17 00:00:00 2001 From: filipi87 Date: Tue, 12 May 2026 10:38:15 -0300 Subject: [PATCH 07/11] Changing the websocket route to return the same data as PCC. --- src/pipecat/runner/run.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index 62d2c4f4e..11cc439b1 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -288,6 +288,7 @@ def _setup_unified_start_route( dailyRoom: str | None dailyToken: str | None wsUrl: str | None + token: str | None @app.post("/start") async def start_agent(request: Request): @@ -422,8 +423,11 @@ def _setup_unified_start_route( elif transport == "websocket": # Plain WebSocket: the bot starts when the client connects to /ws-client. scheme = "wss" if args.host != "localhost" else "ws" + session_id = str(uuid.uuid4()) return StartBotResult( wsUrl=f"{scheme}://{args.host}:{args.port}/ws-client", + sessionId=session_id, + token="mock_token" ) else: From d6655e7a5e8b92212c396f717823fe18b630d19f Mon Sep 17 00:00:00 2001 From: filipi87 Date: Tue, 12 May 2026 10:40:09 -0300 Subject: [PATCH 08/11] Fixing ruff format. --- src/pipecat/runner/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index 11cc439b1..5917a5863 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -427,7 +427,7 @@ def _setup_unified_start_route( return StartBotResult( wsUrl=f"{scheme}://{args.host}:{args.port}/ws-client", sessionId=session_id, - token="mock_token" + token="mock_token", ) else: From c8efe319b31543f5808fd7dc17a9dab867644ff4 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 14 May 2026 11:10:33 -0300 Subject: [PATCH 09/11] Adding the changelog for the changes. --- changelog/4442.added.2.md | 1 + changelog/4442.added.md | 1 + changelog/4442.changed.md | 1 + 3 files changed, 3 insertions(+) create mode 100644 changelog/4442.added.2.md create mode 100644 changelog/4442.added.md create mode 100644 changelog/4442.changed.md diff --git a/changelog/4442.added.2.md b/changelog/4442.added.2.md new file mode 100644 index 000000000..1c2452667 --- /dev/null +++ b/changelog/4442.added.2.md @@ -0,0 +1 @@ +- Added `GET /status` endpoint to the development runner that reports which transports the running instance accepts (all by default, or the single transport passed via `-t`). diff --git a/changelog/4442.added.md b/changelog/4442.added.md new file mode 100644 index 000000000..2360e4e78 --- /dev/null +++ b/changelog/4442.added.md @@ -0,0 +1 @@ +- Added plain WebSocket transport support to the development runner. Bots can now accept connections from non-telephony WebSocket clients (e.g., browser apps using protobuf framing) via the `/ws-client` endpoint alongside other transports. diff --git a/changelog/4442.changed.md b/changelog/4442.changed.md new file mode 100644 index 000000000..0299bc831 --- /dev/null +++ b/changelog/4442.changed.md @@ -0,0 +1 @@ +- ⚠️ The development runner now supports all transports (WebRTC, Daily, telephony, plain WebSocket) simultaneously from a single server. The `/start` endpoint accepts a `"transport"` field to select the transport per-request; omitting `-t` at startup enables all transports instead of defaulting to WebRTC. The Daily browser-redirect route moved from `GET /` to `GET /daily`. From c3338667b1432f2773a22623ab906cfa846c8084 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Fri, 15 May 2026 10:06:47 -0300 Subject: [PATCH 10/11] Mounting the prebuilt frontend UI and root redirect for all transports. --- pyproject.toml | 2 +- src/pipecat/runner/run.py | 27 +++++++++++++++--------- uv.lock | 43 +++++++++++++++++++++++++-------------- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2f3de7ea9..7206dae00 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,7 +103,7 @@ piper = [ "piper-tts>=1.3.0,<2", "requests>=2.32.5,<3" ] qwen = [] resembleai = [ "pipecat-ai[websockets-base]" ] rime = [ "pipecat-ai[websockets-base]" ] -runner = [ "python-dotenv>=1.0.0,<2.0.0", "uvicorn>=0.32.0,<1.0.0", "fastapi>=0.115.6,<1", "pipecat-ai-small-webrtc-prebuilt>=2.5.0"] +runner = [ "python-dotenv>=1.0.0,<2.0.0", "uvicorn>=0.32.0,<1.0.0", "fastapi>=0.115.6,<1", "pipecat-ai-prebuilt>=1.0.0"] sagemaker = ["aws_sdk_sagemaker_runtime_http2; python_version>='3.12'"] sambanova = [] sarvam = [ "sarvamai==0.1.28", "pipecat-ai[websockets-base]" ] diff --git a/src/pipecat/runner/run.py b/src/pipecat/runner/run.py index 5917a5863..62f3b2d51 100644 --- a/src/pipecat/runner/run.py +++ b/src/pipecat/runner/run.py @@ -248,6 +248,7 @@ def _configure_server_app(args: argparse.Namespace): # flow and the /sessions/{session_id}/... proxy routes. active_sessions: dict[str, dict[str, Any]] = {} + _setup_frontend_routes(app) _setup_webrtc_routes(app, args, active_sessions) _setup_daily_routes(app, args) _setup_telephony_routes(app, args) @@ -448,13 +449,27 @@ def _resolve_download_path(folder: str, filename: str) -> Path: return file_path +def _setup_frontend_routes(app: FastAPI): + """Mount the prebuilt frontend UI and root redirect for all transports.""" + try: + from pipecat_ai_prebuilt.frontend import PipecatPrebuiltUI + except ImportError as e: + logger.error(f"Prebuilt frontend not available: {e}") + return + + app.mount("/client", PipecatPrebuiltUI) + + @app.get("/", include_in_schema=False) + async def root_redirect(): + """Redirect root requests to client interface.""" + return RedirectResponse(url="/client/") + + def _setup_webrtc_routes( app: FastAPI, args: argparse.Namespace, active_sessions: dict[str, dict[str, Any]] ): """Set up WebRTC-specific routes.""" try: - from pipecat_ai_small_webrtc_prebuilt.frontend import SmallWebRTCPrebuiltUI - from pipecat.transports.smallwebrtc.connection import SmallWebRTCConnection from pipecat.transports.smallwebrtc.request_handler import ( IceCandidate, @@ -466,14 +481,6 @@ def _setup_webrtc_routes( logger.error(f"WebRTC transport dependencies not installed: {e}") return - # Mount the frontend - app.mount("/client", SmallWebRTCPrebuiltUI) - - @app.get("/", include_in_schema=False) - async def root_redirect(): - """Redirect root requests to client interface.""" - return RedirectResponse(url="/client/") - @app.get("/files/{filename:path}") async def download_file(filename: str): """Handle file downloads.""" diff --git a/uv.lock b/uv.lock index 4853a838c..549550bc2 100644 --- a/uv.lock +++ b/uv.lock @@ -1903,7 +1903,9 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8b/0f/a91f143f356523ff682309732b175765a9bc2836fd7c081c2c67fedc1ad4/greenlet-3.5.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8f1cc966c126639cd152fdaa52624d2655f492faa79e013fea161de3e6dda082", size = 284726, upload-time = "2026-04-27T12:20:51.402Z" }, { url = "https://files.pythonhosted.org/packages/95/82/800646c7ffc5dbabd75ddd2f6b519bb898c0c9c969e5d0473bfe5d20bcce/greenlet-3.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:362624e6a8e5bca3b8233e45eef33903a100e9539a2b995c364d595dbc4018b3", size = 604264, upload-time = "2026-04-27T12:52:39.494Z" }, { url = "https://files.pythonhosted.org/packages/ca/ac/354867c0bba812fc33b15bc55aedafedd0aee3c7dd91dfca22444157dc0c/greenlet-3.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5ecd83806b0f4c2f53b1018e0005cd82269ea01d42befc0368730028d850ed1c", size = 616099, upload-time = "2026-04-27T12:59:39.623Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ab/192090c4a5b30df148c22bf4b8895457d739a7c7c5a7b9c41e5dd7f537f2/greenlet-3.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa94cb2288681e3a11645958f1871d48ee9211bd2f66628fdace505927d6e564", size = 623976, upload-time = "2026-04-27T13:02:37.363Z" }, { url = "https://files.pythonhosted.org/packages/ff/b0/815bece7399e01cadb69014219eebd0042339875c59a59b0820a46ece356/greenlet-3.5.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ff251e9a0279522e62f6176412869395a64ddf2b5c5f782ff609a8216a4e662", size = 615198, upload-time = "2026-04-27T12:25:25.928Z" }, + { url = "https://files.pythonhosted.org/packages/24/11/05eb2b9b188c6df7d68a89c99134d644a7af616a40b9808e8e6ced315d5d/greenlet-3.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:64d6ac45f7271f48e45f67c95b54ef73534c52ec041fcda8edf520c6d811f4bc", size = 418379, upload-time = "2026-04-27T13:05:12.755Z" }, { url = "https://files.pythonhosted.org/packages/10/80/3b2c0a895d6698f6ddb31b07942ebfa982f3e30888bc5546a5b5990de8b2/greenlet-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d874e79afd41a96e11ff4c5d0bc90a80973e476fda1c2c64985667397df432b", size = 1574927, upload-time = "2026-04-27T12:53:25.81Z" }, { url = "https://files.pythonhosted.org/packages/44/0e/f354af514a4c61454dbc68e44d47544a5a4d6317e30b77ddfa3a09f4c5f3/greenlet-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0ed006e4b86c59de7467eb2601cd1b77b5a7d657d1ee55e30fe30d76451edba4", size = 1642683, upload-time = "2026-04-27T12:25:23.9Z" }, { url = "https://files.pythonhosted.org/packages/fa/6a/87f38255201e993a1915265ebb80cd7c2c78b04a45744995abbf6b259fd8/greenlet-3.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:703cb211b820dbffbbc55a16bfc6e4583a6e6e990f33a119d2cc8b83211119c8", size = 238115, upload-time = "2026-04-27T12:21:48.845Z" }, @@ -1911,7 +1913,9 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/32/f2ce6d4cac3e55bc6173f92dbe627e782e1850f89d986c3606feb63aafa7/greenlet-3.5.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:db2910d3c809444e0a20147361f343fe2798e106af8d9d8506f5305302655a9f", size = 286228, upload-time = "2026-04-27T12:20:34.421Z" }, { url = "https://files.pythonhosted.org/packages/b7/aa/caed9e5adf742315fc7be2a84196373aab4816e540e38ba0d76cb7584d68/greenlet-3.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ec9ea74e7268ace7f9aab1b1a4e730193fc661b39a993cd91c606c32d4a3628", size = 601775, upload-time = "2026-04-27T12:52:41.045Z" }, { url = "https://files.pythonhosted.org/packages/c7/af/90ae08497400a941595d12774447f752d3dfe0fbb012e35b76bc5c0ff37e/greenlet-3.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54d243512da35485fc7a6bf3c178fdda6327a9d6506fcdd62b1abd1e41b2927b", size = 614436, upload-time = "2026-04-27T12:59:41.595Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e9/4eeadf8cb3403ac274245ba75f07844abc7fa5f6787583fc9156ba741e0f/greenlet-3.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:41353ec2ecedf7aa8f682753a41919f8718031a6edac46b8d3dc7ed9e1ceb136", size = 620610, upload-time = "2026-04-27T13:02:39.194Z" }, { url = "https://files.pythonhosted.org/packages/2b/e0/2e13df68f367e2f9960616927d60857dd7e56aaadd59a47c644216b2f920/greenlet-3.5.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d280a7f5c331622c69f97eb167f33577ff2d1df282c41cd15907fc0a3ca198c", size = 611388, upload-time = "2026-04-27T12:25:28.008Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ef/f913b3c0eb7d26d86a2401c5e1546c9d46b657efee724b06f6f4ac5d8824/greenlet-3.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:58c1c374fe2b3d852f9b6b11a7dff4c85404e51b9a596fd9e89cf904eb09866d", size = 422775, upload-time = "2026-04-27T13:05:14.261Z" }, { url = "https://files.pythonhosted.org/packages/82/f7/393c64055132ac0d488ef6be549253b7e6274194863967ddc0bc8f5b87b8/greenlet-3.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1eb67d5adefb5bd2e182d42678a328979a209e4e82eb93575708185d31d1f588", size = 1570768, upload-time = "2026-04-27T12:53:28.099Z" }, { url = "https://files.pythonhosted.org/packages/b8/4b/eaf7735253522cf56d1b74d672a58f54fc114702ceaf05def59aae72f6e1/greenlet-3.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2628d6c86f6cb0cb45e0c3c54058bbec559f57eaae699447748cb3928150577e", size = 1635983, upload-time = "2026-04-27T12:25:26.903Z" }, { url = "https://files.pythonhosted.org/packages/4c/fe/4fb3a0805bd5165da5ebf858da7cc01cce8061674106d2cf5bdab32cbfde/greenlet-3.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:d4d9f0624c775f2dfc56ba54d515a8c771044346852a918b405914f6b19d7fd8", size = 238840, upload-time = "2026-04-27T12:23:54.806Z" }, @@ -1919,7 +1923,9 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0c/58/fc576f99037ce19c5aa16628e4c3226b6d1419f72a62c79f5f40576e6eb3/greenlet-3.5.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:5a5ed18de6a0f6cc7087f1563f6bd93fc7df1c19165ca01e9bde5a5dc281d106", size = 285066, upload-time = "2026-04-27T12:23:05.033Z" }, { url = "https://files.pythonhosted.org/packages/4a/ba/b28ddbe6bfad6a8ac196ef0e8cff37bc65b79735995b9e410923fffeeb70/greenlet-3.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a717fbc46d8a354fa675f7c1e813485b6ba3885f9bef0cd56e5ba27d758ff5b", size = 604414, upload-time = "2026-04-27T12:52:42.358Z" }, { url = "https://files.pythonhosted.org/packages/09/06/4b69f8f0b67603a8be2790e55107a190b376f2627fe0eaf5695d85ffb3cd/greenlet-3.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ddc090c5c1792b10246a78e8c2163ebbe04cf877f9d785c230a7b27b39ad038e", size = 617349, upload-time = "2026-04-27T12:59:43.32Z" }, + { url = "https://files.pythonhosted.org/packages/6a/15/a643b4ecd09969e30b8a150d5919960caae0abe4f5af75ab040b1ab85e78/greenlet-3.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4964101b8585c144cbda5532b1aa644255126c08a265dae90c16e7a0e63aaa9d", size = 623234, upload-time = "2026-04-27T13:02:40.611Z" }, { url = "https://files.pythonhosted.org/packages/8a/17/a3918541fd0ddefe024a69de6d16aa7b46d36ac19562adaa63c7fa180eff/greenlet-3.5.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2094acd54b272cb6eae8c03dd87b3fa1820a4cef18d6889c378d503500a1dc13", size = 613927, upload-time = "2026-04-27T12:25:30.28Z" }, + { url = "https://files.pythonhosted.org/packages/77/18/3b13d5ef1275b0ffaf933b05efa21408ac4ca95823c7411d79682e4fdcff/greenlet-3.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:7022615368890680e67b9965d33f5773aade330d5343bbe25560135aaa849eae", size = 425243, upload-time = "2026-04-27T13:05:15.689Z" }, { url = "https://files.pythonhosted.org/packages/ee/e1/bd0af6213c7dd33175d8a462d4c1fe1175124ebed4855bc1475a5b5242c2/greenlet-3.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5e05ba267789ea87b5a155cf0e810b1ab88bf18e9e8740813945ceb8ee4350ba", size = 1570893, upload-time = "2026-04-27T12:53:29.483Z" }, { url = "https://files.pythonhosted.org/packages/9b/2a/0789702f864f5382cb476b93d7a9c823c10472658102ccd65f415747d2e2/greenlet-3.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0ecec963079cd58cbd14723582384f11f166fd58883c15dcbfb342e0bc9b5846", size = 1636060, upload-time = "2026-04-27T12:25:28.845Z" }, { url = "https://files.pythonhosted.org/packages/b2/8f/22bf9df92bbff0eb07842b60f7e63bf7675a9742df628437a9f02d09137f/greenlet-3.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:728d9667d8f2f586644b748dbd9bb67e50d6a9381767d1357714ea6825bb3bf5", size = 238740, upload-time = "2026-04-27T12:24:01.341Z" }, @@ -1927,7 +1933,9 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/94/5e/a70f31e3e8d961c4ce589c15b28e4225d63704e431a23932a3808cbcc867/greenlet-3.5.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:f35807464c4c58c55f0d31dfa83c541a5615d825c2fe3d2b95360cf7c4e3c0a8", size = 285564, upload-time = "2026-04-27T12:23:08.555Z" }, { url = "https://files.pythonhosted.org/packages/af/a6/046c0a28e21833e4086918218cfb3d8bed51c075a1b700f20b9d7861c0f4/greenlet-3.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55fa7ea52771be44af0de27d8b80c02cd18c2c3cddde6c847ecebdf72418b6a1", size = 651166, upload-time = "2026-04-27T12:52:43.644Z" }, { url = "https://files.pythonhosted.org/packages/47/f8/4af27f71c5ff32a7fbc516adb46370d9c4ae2bc7bd3dc7d066ac542b4b15/greenlet-3.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a97e4821aa710603f94de0da25f25096454d78ffdace5dc77f3a006bc01abba3", size = 663792, upload-time = "2026-04-27T12:59:44.93Z" }, + { url = "https://files.pythonhosted.org/packages/fb/89/2dadb89793c37ee8b4c237857188293e9060dc085f19845c292e00f8e091/greenlet-3.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bf2d8a80bec89ab46221ae45c5373d5ba0bd36c19aa8508e85c6cd7e5106cd37", size = 668086, upload-time = "2026-04-27T13:02:42.314Z" }, { url = "https://files.pythonhosted.org/packages/a3/59/1bd6d7428d6ed9106efbb8c52310c60fd04f6672490f452aeaa3829aa436/greenlet-3.5.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f52a464e4ed91780bdfbbdd2b97197f3accaa629b98c200f4dffada759f3ae7", size = 660933, upload-time = "2026-04-27T12:25:33.276Z" }, + { url = "https://files.pythonhosted.org/packages/82/35/75722be7e26a2af4cbd2dc35b0ed382dacf9394b7e75551f76ed1abe87f2/greenlet-3.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:1bae92a1dd94c5f9d9493c3a212dd874c202442047cf96446412c862feca83a2", size = 470799, upload-time = "2026-04-27T13:05:17.094Z" }, { url = "https://files.pythonhosted.org/packages/83/e4/b903e5a5fae1e8a28cdd32a0cfbfd560b668c25b692f67768822ddc5f40f/greenlet-3.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:762612baf1161ccb8437c0161c668a688223cba28e1bf038f4eb47b13e39ccdf", size = 1618401, upload-time = "2026-04-27T12:53:31.062Z" }, { url = "https://files.pythonhosted.org/packages/0e/e3/5ec408a329acb854fb607a122e1ee5fb3ff649f9a97952948a90803c0d8e/greenlet-3.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:57a43c6079a89713522bc4bcb9f75070ecf5d3dbad7792bfe42239362cbf2a16", size = 1682038, upload-time = "2026-04-27T12:25:31.838Z" }, { url = "https://files.pythonhosted.org/packages/91/20/6b165108058767ee643c55c5c4904d591a830ee2b3c7dbd359828fbc829f/greenlet-3.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bc59be3945ae9750b9e7d45067d01ae3fe90ea5f9ade99239dabdd6e28a5033", size = 239835, upload-time = "2026-04-27T12:24:54.136Z" }, @@ -1935,7 +1943,9 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/a8/4522939255bb5409af4e87132f915446bf3622c2c292d14d3c38d128ae82/greenlet-3.5.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:a10a732421ab4fec934783ce3e54763470d0181db6e3468f9103a275c3ed1853", size = 293614, upload-time = "2026-04-27T12:24:12.874Z" }, { url = "https://files.pythonhosted.org/packages/15/5e/8744c52e2c027b5a8772a01561934c8835f869733e101f62075c60430340/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7fc391b1566f2907d17aaebe78f8855dc45675159a775fcf9e61f8ee0078e87f", size = 650723, upload-time = "2026-04-27T12:52:45.412Z" }, { url = "https://files.pythonhosted.org/packages/00/ef/7b4c39c03cf46ceca512c5d3f914afd85aa30b2cc9a93015b0dd73e4be6c/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:680bd0e7ad5e8daa8a4aa89f68fd6adc834b8a8036dc256533f7e08f4a4b01f7", size = 656529, upload-time = "2026-04-27T12:59:46.295Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5c/0602239503b124b70e39355cbdb39361ecfe65b87a5f2f63752c32f5286f/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1aa4ce8debcd4ea7fb2e150f3036588c41493d1d52c43538924ae1819003f4ce", size = 657015, upload-time = "2026-04-27T13:02:43.973Z" }, { url = "https://files.pythonhosted.org/packages/0b/b5/c7768f352f5c010f92064d0063f987e7dc0cd290a6d92a34109015ce4aa1/greenlet-3.5.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddb36c7d6c9c0a65f18c7258634e0c416c6ab59caac8c987b96f80c2ebda0112", size = 654364, upload-time = "2026-04-27T12:25:35.64Z" }, + { url = "https://files.pythonhosted.org/packages/38/51/8699f865f125dc952384cb432b0f7138aa4d8f2969a7d12d0df5b94d054d/greenlet-3.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:728a73687e39ae9ca34e4694cbf2f049d3fbc7174639468d0f67200a97d8f9e2", size = 488275, upload-time = "2026-04-27T13:05:18.28Z" }, { url = "https://files.pythonhosted.org/packages/ef/d0/079ebe12e4b1fc758857ce5be1a5e73f06870f2101e52611d1e71925ce54/greenlet-3.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e5ddf316ced87539144621453c3aef229575825fe60c604e62bedc4003f372b2", size = 1614204, upload-time = "2026-04-27T12:53:32.618Z" }, { url = "https://files.pythonhosted.org/packages/6d/89/6c2fb63df3596552d20e58fb4d96669243388cf680cff222758812c7bfaa/greenlet-3.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4a448128607be0de65342dc9b31be7f948ef4cc0bc8832069350abefd310a8f2", size = 1675480, upload-time = "2026-04-27T12:25:34.168Z" }, { url = "https://files.pythonhosted.org/packages/15/32/77ee8a6c1564fc345a491a4e85b3bf360e4cf26eac98c4532d2fdb96e01f/greenlet-3.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d60097128cb0a1cab9ea541186ea13cd7b847b8449a7787c2e2350da0cb82d86", size = 245324, upload-time = "2026-04-27T12:24:40.295Z" }, @@ -3764,9 +3774,12 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "grpcio" }, { name = "grpcio-tools" }, + { name = "protobuf" }, { name = "websockets" }, ] wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/f9/85f0bf863deed9078f3a25938a9f06206f98bcc39a6541a48cc97143db10/nvidia_riva_client-2.25.1-1-py3-none-any.whl", hash = "sha256:bde1232a8de3fe1561cccf49d3d0e6fe06190b1f0df4ad0ba118b9f5ae5a06aa", size = 55383, upload-time = "2026-04-30T10:27:58.381Z" }, + { url = "https://files.pythonhosted.org/packages/27/c6/eb4acc0cb884c06109ea123d1c7dbb28974c9dddd73a624b1765a89e023e/nvidia_riva_client-2.25.1-2-py3-none-any.whl", hash = "sha256:5657680ab238b5930c07ce9a4a50d642524f25bff4099c1f818baaa8baad94fe", size = 55462, upload-time = "2026-05-06T12:30:02.948Z" }, { url = "https://files.pythonhosted.org/packages/08/3b/b267af66a49c2e80e673b85ccd5484059b141be8031e4a4bb84ea4bcf31f/nvidia_riva_client-2.25.1-py3-none-any.whl", hash = "sha256:07c48c9cc7f3ca04cd988ad6d2205b0bcf3f6f25bb97d76b397e87cc696acc9f", size = 55371, upload-time = "2026-03-25T13:05:57.425Z" }, ] @@ -4350,7 +4363,7 @@ rnnoise = [ ] runner = [ { name = "fastapi" }, - { name = "pipecat-ai-small-webrtc-prebuilt" }, + { name = "pipecat-ai-prebuilt" }, { name = "python-dotenv" }, { name = "uvicorn" }, ] @@ -4515,7 +4528,7 @@ requires-dist = [ { name = "pipecat-ai", extras = ["websockets-base"], marker = "extra == 'ultravox'" }, { name = "pipecat-ai", extras = ["websockets-base"], marker = "extra == 'websocket'" }, { name = "pipecat-ai", extras = ["websockets-base"], marker = "extra == 'xai'" }, - { name = "pipecat-ai-small-webrtc-prebuilt", marker = "extra == 'runner'", specifier = ">=2.5.0" }, + { name = "pipecat-ai-prebuilt", marker = "extra == 'runner'", specifier = ">=1.0.0" }, { name = "piper-tts", marker = "extra == 'piper'", specifier = ">=1.3.0,<2" }, { name = "protobuf", specifier = ">=5.29.6,<7" }, { name = "protobuf", marker = "extra == 'nvidia'", specifier = ">=6.31.1,<7" }, @@ -4577,15 +4590,15 @@ docs = [ ] [[package]] -name = "pipecat-ai-small-webrtc-prebuilt" -version = "2.5.0" +name = "pipecat-ai-prebuilt" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastapi", extra = ["all"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2c/4f/40bfc9fc1a13f9b1f2657e292c51ff3e3516c530ca722effdcf342d465d9/pipecat_ai_small_webrtc_prebuilt-2.5.0.tar.gz", hash = "sha256:51481506b7b5dff10eff0357ff929cba504a5198c3393697178d2be9895ad9e6", size = 474299, upload-time = "2026-04-22T18:05:16.494Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/86/7527474a324e3da787468133a1dba877e06576edc502e1bc7dd84ba7c9f7/pipecat_ai_prebuilt-1.0.0.tar.gz", hash = "sha256:dc66df541f17620eef5dedb2fd44737eb97232899779afb66dcca5aaa9317512", size = 601709, upload-time = "2026-05-14T21:15:26.575Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/58/1a2e10c1fb7b44e47558cb6c0954e24a60f98afe912fe55c74fdee66f080/pipecat_ai_small_webrtc_prebuilt-2.5.0-py3-none-any.whl", hash = "sha256:23b1eee95662a0072d9ee5128b8567108eda10d5a54ad71f279730afbb678bfe", size = 474308, upload-time = "2026-04-22T18:05:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/89/b1/648122d5e418d3e0c8f797028bc53a22229ffc07a2406712b13b76735f38/pipecat_ai_prebuilt-1.0.0-py3-none-any.whl", hash = "sha256:6b7057920d3d00e5687adb26e032634ba1f6d924eb9079b1804d031620a1e854", size = 601949, upload-time = "2026-05-14T21:15:24.666Z" }, ] [[package]] @@ -4780,17 +4793,17 @@ wheels = [ [[package]] name = "protobuf" -version = "6.33.6" +version = "6.33.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/70/e908e9c5e52ef7c3a6c7902c9dfbb34c7e29c25d2f81ade3856445fd5c94/protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135", size = 444531, upload-time = "2026-03-18T19:05:00.988Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/9f/2f509339e89cfa6f6a4c4ff50438db9ca488dec341f7e454adad60150b00/protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3", size = 425739, upload-time = "2026-03-18T19:04:48.373Z" }, - { url = "https://files.pythonhosted.org/packages/76/5d/683efcd4798e0030c1bab27374fd13a89f7c2515fb1f3123efdfaa5eab57/protobuf-6.33.6-cp310-abi3-win_amd64.whl", hash = "sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326", size = 437089, upload-time = "2026-03-18T19:04:50.381Z" }, - { url = "https://files.pythonhosted.org/packages/5c/01/a3c3ed5cd186f39e7880f8303cc51385a198a81469d53d0fdecf1f64d929/protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a", size = 427737, upload-time = "2026-03-18T19:04:51.866Z" }, - { url = "https://files.pythonhosted.org/packages/ee/90/b3c01fdec7d2f627b3a6884243ba328c1217ed2d978def5c12dc50d328a3/protobuf-6.33.6-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2", size = 324610, upload-time = "2026-03-18T19:04:53.096Z" }, - { url = "https://files.pythonhosted.org/packages/9b/ca/25afc144934014700c52e05103c2421997482d561f3101ff352e1292fb81/protobuf-6.33.6-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3", size = 339381, upload-time = "2026-03-18T19:04:54.616Z" }, - { url = "https://files.pythonhosted.org/packages/16/92/d1e32e3e0d894fe00b15ce28ad4944ab692713f2e7f0a99787405e43533a/protobuf-6.33.6-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593", size = 323436, upload-time = "2026-03-18T19:04:55.768Z" }, - { url = "https://files.pythonhosted.org/packages/c4/72/02445137af02769918a93807b2b7890047c32bfb9f90371cbc12688819eb/protobuf-6.33.6-py3-none-any.whl", hash = "sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901", size = 170656, upload-time = "2026-03-18T19:04:59.826Z" }, + { url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" }, + { url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" }, + { url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" }, + { url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" }, + { url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" }, + { url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" }, ] [[package]] From b493ed8d3a503616d6fba0c095909fb13de0d16d Mon Sep 17 00:00:00 2001 From: filipi87 Date: Fri, 15 May 2026 10:11:38 -0300 Subject: [PATCH 11/11] Removing the websocket transport from elevenlabs example. --- examples/voice/voice-elevenlabs.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/examples/voice/voice-elevenlabs.py b/examples/voice/voice-elevenlabs.py index f3b28e709..8f61bb665 100644 --- a/examples/voice/voice-elevenlabs.py +++ b/examples/voice/voice-elevenlabs.py @@ -22,7 +22,6 @@ from pipecat.processors.aggregators.llm_response_universal import ( ) from pipecat.runner.types import RunnerArguments from pipecat.runner.utils import create_transport -from pipecat.serializers.protobuf import ProtobufFrameSerializer from pipecat.services.elevenlabs.stt import ElevenLabsRealtimeSTTService from pipecat.services.elevenlabs.tts import ElevenLabsTTSService from pipecat.services.openai.llm import OpenAILLMService @@ -48,12 +47,6 @@ transport_params = { audio_in_enabled=True, audio_out_enabled=True, ), - "websocket": lambda: FastAPIWebsocketParams( - audio_in_enabled=True, - audio_out_enabled=True, - add_wav_header=False, - serializer=ProtobufFrameSerializer(), - ), }