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:

  1. Acquire the AdmissionGuard mutex for exclusive access to the ended flag, peer count, and version pin
  2. Reject if the room is ended or full (MAX_PEERS_PER_ROOM = 25)
  3. Verify the requested protocol version matches the pinned version
  4. Allocate a peer_index and epoch via AdmissionGuard::alloc, incrementing the epoch each time an index is reused
  5. Insert the new AudioPeer into the DashMap and broadcast a RosterDelta to 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_index byte
  • v3: Two-byte sequence of peer_index followed by epoch

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(&timestamp.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_peer ensures all participants use identical protocol versions, enforced by the AdmissionGuard
  • The 8-byte v2 header (sequence, timestamp, level, flags) is parsed in wire.rs with strict validation and telemetry clamping
  • Non-blocking broadcast via mpsc::Sender drops frames rather than delaying the real-time stream when buffers fill
  • Mesh support uses deliver_prefixed to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →