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:uint32Strings/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
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.