Files
amethyst/nestsClient/specs/EGG-03.md
T
Claude 5c40e27fde docs(nestsClient/specs): EGG-00..EGG-12 — Extensible Gossip Guidelines
Wire-protocol specs for nostrnests-style audio rooms, in the
style of Nostr NIPs and Blossom BUDs. Each spec documents one
self-contained capability that a client or relay can implement;
two compliant peers implementing the same set of EGGs round-trip
without further coordination.

Layout:

  README.md            cover, status table, conformance levels
  EGG-01.md  Room event (kind:30312)              required
  EGG-02.md  Auth + WebTransport handshake        required
  EGG-03.md  Audio plane (moq-lite)               required
  EGG-04.md  Presence (kind:10312)                required
  EGG-05.md  In-room chat (kind:1311)             optional
  EGG-06.md  Reactions (kind:7)                   optional
  EGG-07.md  Roles & moderation (kind:4312)       optional
  EGG-08.md  Scheduling (status=planned)          optional
  EGG-09.md  User server list (kind:10112)        optional
  EGG-10.md  Theming (c/f/bg tags)                decorative
  EGG-11.md  Recording                            decorative
  EGG-12.md  Catalog track (catalog.json)         optional

Conformance levels (Listener / Speaker / Host) defined in the
README so a deployment can declare "we implement EGG-01..EGG-04"
and other peers know exactly what to expect.

Each spec follows the same shape (Summary / Wire format /
Behavior numbered MUST/SHOULD/MAY rules / Example /
Compatibility) and fits on a single printed page. Wire formats
are documented exactly as nostrnests + amethyst implement them
on this branch — no hypothetical capabilities, no "future" tags
without an EGG number.
2026-04-27 03:54:45 +00:00

3.6 KiB

EGG-03: Audio plane (moq-lite)

status: draft requires: EGG-02 category: required

Summary

Audio is carried over moq-lite Lite-03 on top of the WebTransport session opened in EGG-02. Each speaker publishes one broadcast keyed by their pubkey hex, on a single track named audio/data, encoded as Opus.

This EGG defines the broadcast/track naming convention and the audio codec parameters. It does not redefine moq-lite framing — refer to the upstream spec for the wire layout of Subscribe, Announce, Group, and Frame control messages.

Wire format

Speaker → relay (publish)

A speaker MUST send a moq-lite Announce with:

prefix     = ""           (empty — relative to the JWT's `root` namespace)
suffix     = <pubkey hex>
status     = Active

After the announce, the speaker opens a unidirectional QUIC stream per group, prefixed with a moq-lite Group header followed by Frames carrying Opus payloads.

Listener → relay (subscribe)

A listener MUST send a moq-lite Subscribe with:

broadcast  = <speaker pubkey hex>
track      = "audio/data"
priority   = 128            (recommended)
ordered    = true
maxLatency = 0              (unlimited)

The relay forwards each subsequent Group and its Frames to the listener in subscribe-id order.

Codec

Parameter Value
Codec Opus (RFC 6716)
Sample rate 48 kHz
Channels 1 (mono)
Frame duration 20 ms (960 samples)
Bit-rate target 32 kbit/s (configurable, no upper cap)
VBR Allowed

A new Group MUST be opened on every Opus reset (e.g. mute/unmute).

Behavior

  1. A speaker MUST emit an Announce with status=Active immediately after the WebTransport session reaches a usable state, and emit status=Ended when stopping the broadcast cleanly.
  2. A speaker MUST cap their broadcast to one concurrent audio/data track per session. Multi-quality stacks are reserved for a future EGG.
  3. Listeners MUST tolerate gaps in the group sequence (frames dropped due to network loss). They MUST NOT request retransmits.
  4. Listeners SHOULD subscribe with ordered=true. Out-of-order delivery would re-introduce reorderable jitter the Opus decoder is not equipped to handle.
  5. A speaker MUST encode in mono. Stereo broadcasts are reserved for a future EGG.
  6. Listeners MUST NOT subscribe to their own broadcast (would create an audio loopback through the relay).
  7. The relay MUST drop a publishing peer's Announce and any subsequent stream data if the JWT's put claim does not contain <pubkey hex>.

Example

A two-speaker room:

A's session:  ANNOUNCE  prefix="" suffix="speakerA" status=Active
              GROUP     subscribe-id=…, sequence=0
              FRAME     <opus payload, 20ms>
              FRAME     <opus payload, 20ms>
              …

Listener's session:
  SUBSCRIBE  broadcast="speakerA" track="audio/data"
  ←  GROUP   sequence=0
  ←  FRAME   <opus payload, 20ms>
  ←  …
  SUBSCRIBE  broadcast="speakerB" track="audio/data"
  ←  GROUP   sequence=0
  ←  FRAME   <opus payload, 20ms>
  ←  …

Compatibility

EGG-12 adds an OPTIONAL catalog.json track per broadcast carrying codec metadata. EGG-12 MUST NOT change the audio/data track parameters defined here.

A future "video plane" EGG MAY introduce additional tracks; their names MUST NOT collide with audio/data or catalog.json.