Snapcast.Protocol (Snapcast v0.1.0)

Copy Markdown View Source

Snapcast binary wire protocol — encode/decode (a pure-Elixir snapcast SERVER).

Every message is a 26-byte little-endian base header followed by size payload bytes:

type:uint16  id:uint16  refersTo:uint16
sent.sec:int32  sent.usec:int32
received.sec:int32  received.usec:int32
size:uint32

Strings/JSON payloads are uint32 length-prefixed. Message types: 1 CodecHeader, 2 WireChunk, 3 ServerSettings, 4 Time, 5 Hello, 7 ClientInfo, 8 Error. (See snapcast common/message/*.hpp.)

The server owns the audio timeline: it stamps each WireChunk with the server-clock time at which that chunk should play, and the client plays it bufferMs later on its sync-corrected clock — so there is no producer/consumer pacing drift.

Summary

Functions

CodecHeader (type 1): codec name + codec-specific header payload.

CodecHeader (type 1) for the flac codec. Payload is FLAC stream metadata.

CodecHeader (type 1) for Snapcast's raw opus codec.

CodecHeader (type 1) for the pcm codec: codec name + 44-byte WAV header.

Peel one full message off a receive buffer. Returns {:ok, message, rest} once a whole header+payload is present, or :incomplete. message is a map with the base header fields plus a decoded :body for known types.

Frame a message: 26-byte base header + payload.

ServerSettings (type 3): bufferMs / latency / volume% / muted, JSON payload.

Time response (type 4). The client computes its clock offset from the round trip, so the server must reply with latency = serverReceived - clientSent (in the payload) and set the base header sent to the server time at send.

WireChunk (type 2): playout timestamp (server clock) + codec payload.

Types

tv()

@type tv() :: {integer(), integer()}

Functions

codec_header(codec, header_payload, opts \\ [])

CodecHeader (type 1): codec name + codec-specific header payload.

codec_header_flac(flac_metadata, opts \\ [])

CodecHeader (type 1) for the flac codec. Payload is FLAC stream metadata.

codec_header_opus(rate, bits, channels, opts \\ [])

CodecHeader (type 1) for Snapcast's raw opus codec.

codec_header_pcm(rate, bits, channels, opts \\ [])

CodecHeader (type 1) for the pcm codec: codec name + 44-byte WAV header.

decode(buffer)

Peel one full message off a receive buffer. Returns {:ok, message, rest} once a whole header+payload is present, or :incomplete. message is a map with the base header fields plus a decoded :body for known types.

frame(type, payload, opts \\ [])

Frame a message: 26-byte base header + payload.

header_size()

server_settings(buffer_ms, latency, volume, muted, opts \\ [])

ServerSettings (type 3): bufferMs / latency / volume% / muted, JSON payload.

time_response(arg, opts \\ [])

Time response (type 4). The client computes its clock offset from the round trip, so the server must reply with latency = serverReceived - clientSent (in the payload) and set the base header sent to the server time at send.

wire_chunk(arg, payload_binary, opts \\ [])

WireChunk (type 2): playout timestamp (server clock) + codec payload.