A Pipecat community integration that lets you use Bandwidth Programmable Voice as the telephony layer for your Pipecat voice bots.
This package provides BandwidthFrameSerializer, a FrameSerializer you plug
into a FastAPIWebsocketTransport to handle Bandwidth's bidirectional
WebSocket media stream protocol.
Maintained by Bandwidth.
- Decodes Bandwidth's inbound μ-law audio (8 kHz) into Pipecat audio frames.
- Encodes outbound audio as either μ-law or linear PCM at 8/16/24 kHz. PCM at 24 kHz noticeably improves TTS quality compared to μ-law.
- Handles interruptions by emitting Bandwidth's
clearevent, so the bot stops talking immediately when the caller speaks. - Auto hangs up the call via the Bandwidth Voice API on
EndFrameorCancelFrame, using OAuth 2.0 client_credentials.
pip install pipecat-bandwidthOr with uv:
uv add pipecat-bandwidthfrom pipecat.transports.websocket.fastapi import (
FastAPIWebsocketParams,
FastAPIWebsocketTransport,
)
from pipecat_bandwidth import BandwidthFrameSerializer
# IMPORTANT: call_id and account_id flow into an authenticated POST to the
# Bandwidth Voice API on auto hang-up. They MUST come from a server-trusted
# source — typically the (authenticated) inbound voice webhook body — and
# NOT from the WebSocket "start" event's metadata, which is unauthenticated
# and attacker-controllable. See the chatbot example for one safe pattern
# (token-in-URL correlating the webhook to the WS connect).
serializer = BandwidthFrameSerializer(
stream_id=stream_id,
call_id=call_id,
account_id=account_id,
client_id=os.getenv("BANDWIDTH_CLIENT_ID"),
client_secret=os.getenv("BANDWIDTH_CLIENT_SECRET"),
)
transport = FastAPIWebsocketTransport(
websocket=websocket,
params=FastAPIWebsocketParams(
audio_in_enabled=True,
audio_out_enabled=True,
add_wav_header=False,
serializer=serializer,
),
)For higher-fidelity outbound audio, configure linear PCM:
from pipecat_bandwidth import BandwidthFrameSerializer
serializer = BandwidthFrameSerializer(
stream_id=stream_id,
call_id=call_id,
account_id=account_id,
client_id=os.getenv("BANDWIDTH_CLIENT_ID"),
client_secret=os.getenv("BANDWIDTH_CLIENT_SECRET"),
params=BandwidthFrameSerializer.InputParams(
outbound_encoding="PCM",
outbound_pcm_sample_rate=24000,
),
)A complete end-to-end example lives in
examples/bandwidth-chatbot. It shows a
single-file FastAPI server that:
- Returns a
<StartStream>BXML response on Bandwidth's voice webhook. - Accepts the bidirectional WebSocket and reads Bandwidth's
startevent for the stream/call/account IDs. - Runs a Deepgram (STT) → OpenAI (LLM) → Cartesia (TTS) Pipecat pipeline.
See the example's README for setup and run instructions.
Bandwidth does not deliver DTMF over the media-stream WebSocket. DTMF is
captured by the BXML <Gather> verb and posted to a separate webhook. Wire
DTMF handling in your application's webhook handler — not in the serializer.
- Tested with Pipecat v1.1.0.
- Python 3.11, 3.12.
BSD 2-Clause. See LICENSE.
Issues and PRs are welcome. For larger changes, please open an issue first to discuss what you'd like to change.