Protobuf
Binary frame serialization for WebSocket transports with ProtobufFrameSerializer, wire-compatible with Pipecat's frames.proto.
Overview
A serializer turns frames into the messages a transport sends, and incoming messages back into
frames. ProtobufFrameSerializer encodes frames as Protocol Buffers with Pipecat's
frames.proto schema, so a pipedog bot talks to Pipecat's WebSocket clients and to Pipecat bots
over the same wire format.
It is the default serializer of WebsocketClientTransport, and the usual choice for
FastAPIWebsocketTransport and SingleClientWebsocketServerTransport when the other end is a
Pipecat client.
Upstream: serializers
Pipecat's serializer overview. Upstream has no page for this class.
Source
packages/serializer-protobuf/src/protobuf.ts, with the schema codec in
packages/core/src/frames/protobufs/frames_pb2.ts.
WebSocket transports
The transports this serializer is used with.
Installation
bun add @pipedog/serializer-protobufimport { ProtobufFrameSerializer } from "@pipedog/serializer-protobuf/protobuf";@pipedog/transport-websocket already depends on it.
Prerequisites
None. No account or key is needed. The other end must speak the same schema: a Pipecat client SDK's WebSocket transport with its protobuf serializer, or another Pipecat or pipedog bot.
ProtobufFrameSerializer
Configuration
new ProtobufFrameSerializer(options?). The options are the base serializer's:
Prop
Type
Usage
import { TextFrame } from "@pipedog/core/frames/frames";
import { ProtobufFrameSerializer } from "@pipedog/serializer-protobuf/protobuf";
import {
FastAPIWebsocketParams,
FastAPIWebsocketTransport,
} from "@pipedog/transport-websocket/fastapi";
import type { WebsocketConnection } from "@pipedog/transport-websocket/socket";
function createTransport(connection: WebsocketConnection): FastAPIWebsocketTransport {
return new FastAPIWebsocketTransport(
connection,
new FastAPIWebsocketParams({
audioInEnabled: true,
audioOutEnabled: true,
serializer: new ProtobufFrameSerializer(),
}),
);
}The transports call serialize() and deserialize() for you. Called directly:
// The transports call these for you; this shows the wire form of one frame.
const serializer = new ProtobufFrameSerializer();
const bytes = await serializer.serialize(new TextFrame({ text: "hello" }));
const frame = bytes ? await serializer.deserialize(bytes) : null;Notes
The schema has five frame types:
| Proto field | Serialized from | Deserialized to |
|---|---|---|
text | TextFrame | TextFrame |
audio | OutputAudioRawFrame | InputAudioRawFrame |
transcription | TranscriptionFrame | TranscriptionFrame |
message | OutputTransportMessageFrame, OutputTransportMessageUrgentFrame | InputTransportMessageFrame |
interruption | InterruptionFrame | InterruptionFrame |
- Transport messages go on the wire as a
messageframe whosedatais the JSON-encoded message. On the way in,datais parsed back to an object; invalid JSON logs an error and returnsnull. - Any other frame type logs a warning and serializes to
null, which the transport skips. - RTVI messages are always sent. The base serializer drops them by default to keep them off
telephony streams, but this constructor sets
ignoreRtviMessagestofalse, even if you pass params: WebSocket transports are how RTVI messages reach the client. deserialize()takes bytes. A text message throws aTypeError, as protobuf'sFromStringdoes upstream.- The frame's
id,nameandpts(for audio) are carried across when set.
Runtime notes
| Runtime | Works | What it needs |
|---|---|---|
| Bun | ✅ yes | Nothing. |
| Node.js | ✅ yes | Nothing. |
| Deno | ✅ yes | Nothing. |
| Cloudflare Workers | ✅ yes | Nothing. |
Generated from pipecat.runtimes and pipecat.compat in packages/serializer-protobuf/package.json: ✅ means the compat smoke test passes on that runtime.
Upstream's frames_pb2 is generated by protoc and needs the protobuf runtime. pipedog's core
has no third-party dependencies, so frames_pb2.ts is a hand-written proto3 codec for the same
schema, with the same wire format. uint64 fields are JS numbers, exact up to 2^53.
The serializer runs on Bun, Node, Deno and Cloudflare Workers.
The other serializers are ported too: RTVI client, and the telephony serializers for Twilio, Telnyx, Plivo, Exotel, Vonage and Genesys.
pipedog is an unofficial community TypeScript port of Pipecat. It is not affiliated with or endorsed by Daily or the Pipecat project.
Portions adapted from the Pipecat documentation, Copyright (c) 2024–2025 Daily, BSD-2-Clause (see apps/docs/LICENSE-pipecat-docs).