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

112 lines
3.6 KiB
Markdown

# EGG-03: Audio plane (moq-lite)
`status: draft`
`requires: EGG-02`
`category: required`
## Summary
Audio is carried over [moq-lite](https://github.com/kixelated/moq) 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 `Frame`s 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 `Frame`s 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`.