Architecture of the Huddle Audio WebSocket Opus Relay in Buzz
Buzz implements Huddle audio as a real-time Opus-only relay built on a three-layer architecture consisting of a WebSocket entry point, an audio room manager, and a wire protocol layer that handles parsing and broadcasting.
The Huddle audio WebSocket Opus relay powers real-time voice communication in the Buzz decentralized social protocol. According to the block/buzz source code, the relay operates entirely on the buzz-relay server and forwards raw Opus payloads without transcoding, minimizing latency while enforcing strict protocol versioning and admission control.
Three-Layer System Architecture
The relay consists of three tightly-coupled layers that handle connection establishment, state management, and frame distribution.
| Layer | Component | Key File |
|---|---|---|
| WebSocket Entry Point | Handles the GET /huddle/:channel/audio upgrade, NIP-42 authentication, and protocol version negotiation |
crates/buzz-relay/src/handlers/huddle.rs |
| Audio Room Manager | Maintains the Room state, peer indices, version pinning, and admission gates |
crates/buzz-relay/src/audio/room.rs |
| Wire Protocol | Parses the 8-byte frame headers, clamps telemetry, and manages v2/v3 prefix formats | crates/buzz-relay/src/audio/wire.rs |
When a client connects, the handler in huddle.rs upgrades the HTTP request to a binary WebSocket and forwards the stream to the audio subsystem, which creates or retrieves a Room instance via the AudioRoomManager.
Admission Control and Version Pinning
The Room::add_peer routine enforces strict admission rules to ensure protocol consistency within a channel.
When the first peer joins a room, the system creates a pinned_version based on the client's advertised protocol version. All subsequent joins must present the exact same version, or the admission guard returns an AdmissionError::VersionMismatch. This pin persists across peer churn and is cleared only when AudioRoomManager::cleanup_if_empty destroys the empty room.
The admission sequence follows five sequential steps:
- Acquire the
AdmissionGuardmutex for exclusive access to the ended flag, peer count, and version pin - Reject if the room is ended or full (
MAX_PEERS_PER_ROOM = 25) - Verify the requested protocol version matches the pinned version
- Allocate a peer_index and epoch via
AdmissionGuard::alloc, incrementing the epoch each time an index is reused - Insert the new
AudioPeerinto theDashMapand broadcast aRosterDeltato all connected clients
This design prevents version skew and allows receivers to fence stale frames using the epoch counter.
Wire Protocol and Frame Parsing
Clients prepend an 8-byte v2 header (V2_HEADER_LEN = 8) to every Opus payload before transmission over the WebSocket.
Bytes 0-1 : seq (u16) - Sequence number
Bytes 2-5 : ts_48k (u32) - RTP-style 48kHz timestamp
Byte 6 : level_dbov (i8) - Audio level in dBov, clamped to –127..0
Byte 7 : flags (u8) - Bit 0 indicates FLAG_DTX (comfort noise)
In crates/buzz-relay/src/audio/wire.rs, the FrameHeader::parse function validates the buffer length, reads fields in network-byte order, clamps the level_dbov telemetry to prevent overflow attacks, and returns the header along with the remaining payload bytes. If the buffer is shorter than FRAME_HEADER_LEN, the function returns None and the relay drops the malformed frame.
For protocol v3, the system adds a second epoch byte to the wire format, allowing clients to detect and discard frames from previous session epochs.
Broadcasting and Mesh Delivery
After parsing, Room::broadcast_frame constructs a peer-specific prefix and distributes the frame to all participants in the room.
The prefix format varies by protocol version:
- v2 and earlier: Single
peer_indexbyte - v3: Two-byte sequence of
peer_indexfollowed byepoch
The system prepends this prefix to the opaque Opus payload and transmits it via mpsc::Sender to each peer's audio channel (AudioPeer::audio_tx). The try_send operation is non-blocking; if a peer's buffer (capacity: 8 frames ≈ 160ms) is full, the relay drops that specific frame to preserve real-time performance rather than introducing backpressure.
Mesh Pod Forwarding
In multi-pod deployments, when a frame arrives from another relay instance (the mesh layer), it already carries the correct [peer_index][epoch?] prefix. The Room::deliver_prefixed method forwards this frame to all local peers except the author identified by author_index, preventing self-echo while maintaining zero-copy forwarding semantics.
Roster Management and State Recovery
The relay maintains an ordered roster of participants using RosterPeer and RosterSnapshot structures. Any membership change (join or leave) emits a RosterDelta on a Tokio broadcast channel subscribed to via Room::subscribe_roster.
If a client falls behind on delta processing, it can request a full Room::roster_snapshot and replay subsequent deltas with revision numbers greater than the snapshot's baseline. This mechanism makes the relay stateless regarding audio payloads while maintaining minimal metadata for routing and UI synchronization.
Mesh-Aware Room Lookup
To prevent cross-community audio leakage in distributed deployments, the mesh layer performs room lookups using AudioRoomManager::get_unambiguous_by_channel, which searches only by channel UUID. If two distinct communities accidentally reuse the same channel UUID, the lookup fails closed rather than risking audio bleed between unrelated communities.
Implementation Examples
Client-Side Frame Transmission
// Establish WebSocket and authenticate (NIP-42)
let mut ws = connect_ws("/huddle/channel-uuid/audio").await?;
// Construct the 8-byte v2 header + Opus payload
let mut frame = BytesMut::with_capacity(8 + opus_data.len());
frame.extend_from_slice(&seq.to_be_bytes()); // u16 sequence
frame.extend_from_slice(×tamp.to_be_bytes()); // u32 timestamp
frame.extend_from_slice(&[level_dbov, flags]); // i8 + u8
frame.extend_from_slice(&opus_data);
// Send binary frame
ws.send(Message::Binary(frame.freeze())).await?;
Server-Side Frame Handling
use buzz_relay::audio::{wire::FrameHeader, room::Room};
async fn handle_audio_stream(
ws: WebSocket,
room: Arc<Room>,
peer_id: Uuid
) {
while let Some(Ok(Message::Binary(bytes))) = ws.next().await {
// Parse the 8-byte header
if let Some((header, payload)) = FrameHeader::parse(&bytes) {
// Broadcast to local peers (non-blocking)
room.broadcast_frame(peer_id, payload).await;
// Forward to mesh if this is a multi-pod setup
mesh::forward_prefixed(room.channel_id(), header, payload);
}
}
}
Receiving Mesh Frames
fn on_mesh_frame_received(
channel_id: Uuid,
author_index: u8,
prefixed_frame: Bytes
) {
if let Some(room) = audio_manager.get_unambiguous_by_channel(channel_id) {
// Deliver to all local peers except the author
room.deliver_prefixed(author_index, prefixed_frame);
}
}
Summary
- The Huddle audio WebSocket Opus relay in Buzz uses a three-layer architecture: WebSocket handlers, room management, and wire protocol parsing
- Version pinning in
Room::add_peerensures all participants use identical protocol versions, enforced by theAdmissionGuard - The 8-byte v2 header (sequence, timestamp, level, flags) is parsed in
wire.rswith strict validation and telemetry clamping - Non-blocking broadcast via
mpsc::Senderdrops frames rather than delaying the real-time stream when buffers fill - Mesh support uses
deliver_prefixedto forward already-annotated frames between relay pods while preventing self-echo - Roster deltas and snapshots provide eventual consistency for participant lists without holding audio state
Frequently Asked Questions
How does the Buzz relay handle protocol version mismatches?
When the first peer joins a room, Room::add_peer pins the protocol version to that peer's advertised version. Subsequent peers presenting different versions receive an AdmissionError::VersionMismatch and are rejected. This prevents incompatible clients from joining the same audio room.
What happens when a peer's buffer is full during broadcasting?
The relay uses try_send on the mpsc::Sender channel with a capacity of 8 frames (approximately 160ms). If the channel is full, the frame is dropped rather than blocking the broadcaster. This preserves real-time performance for the entire room at the cost of occasional packet loss for slow consumers.
How does the relay prevent audio from bleeding between communities?
The mesh layer in AudioRoomManager::get_unambiguous_by_channel looks up rooms only by channel UUID. If the UUID exists across multiple communities, the lookup fails closed to prevent cross-community audio leakage. This ensures strict isolation between unrelated social graphs.
What is the purpose of the epoch byte in protocol v3?
The epoch byte increments each time a peer index is reused after a disconnect. Receiving clients use this value to fence stale frames that might arrive late from the previous occupant of that peer slot. This eliminates ghost audio from recently disconnected participants without requiring complex sequence tracking.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →