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.
4.2 KiB
EGG-12: Catalog track (catalog.json)
status: draft
requires: EGG-03
category: optional
Summary
A speaker MAY publish a sibling catalog.json track on the same moq-lite
broadcast as their audio/data track. The catalog carries codec
metadata: format, sample rate, channel count, bitrate, etc. It exists so
clients can render a "speaker is broadcasting Opus 48 kHz mono" tooltip
without parsing audio frames, and so future codec migrations can be
negotiated client-side.
Wire format
Track convention
A speaker MUST publish the catalog on the SAME broadcast as their audio track:
SUBSCRIBE broadcast=<speaker pubkey hex> track="catalog.json"
Payload
Each Group carries a single JSON document encoded as UTF-8. The
publisher emits a fresh group whenever the catalog changes (e.g. codec
swap on mute / unmute). Receivers SHOULD read only the most recent
group.
Document shape:
{
"version": 1,
"audio": [
{
"track": "audio/data",
"codec": "opus",
"sample_rate": 48000,
"channel_count": 1,
"bitrate": 32000
}
]
}
Field reference:
| field | type | required | meaning |
|---|---|---|---|
version |
int | required | Schema version. Currently 1. |
audio |
array | required | One entry per audio track. May be empty. |
audio[].track |
string | required | Track name; matches the moq-lite track this catalog describes (typically "audio/data"). |
audio[].codec |
string | optional | Lower-case codec id (opus, aac, …). |
audio[].sample_rate |
int | optional | Sample rate in Hz. |
audio[].channel_count |
int | optional | 1 = mono, 2 = stereo. |
audio[].bitrate |
int | optional | Target bitrate in bits per second. |
Unknown fields MUST be tolerated: parsers MUST ignore keys they do not
recognise rather than rejecting the document. New keys are added without
incrementing version unless they change the meaning of an existing key.
Behavior
- Publishing a catalog is OPTIONAL. A speaker that omits the
catalog.jsontrack MUST still be playable per EGG-03 (which already pins the audio parameters). - A subscriber MUST tolerate the absence of a catalog. A
Subscriberesponse ofDrop/error on thecatalog.jsontrack is benign — the subscriber falls back to the EGG-03 default parameters. - A subscriber MUST tolerate malformed JSON, missing
version, and unknown fields. Failure to parse means "no catalog metadata" — render the default tooltip. - A publisher MUST NOT use the catalog track to deliver authoritative
stream parameters that contradict EGG-03. The catalog is INFORMATIVE,
not normative: a listener MUST be able to decode
audio/datawithout reading the catalog. - Subscribers SHOULD limit how often they re-render the catalog tooltip: at most once per second, even if catalogs are published more frequently.
- Hosts MAY use the catalog to detect non-conformant publishers (e.g. a
broadcaster claiming
aacwhen EGG-03 mandatesopus) for moderation purposes. The actual moderation flow is out of scope for this EGG.
Example
A speaker comes onstage with default Opus parameters:
SUBSCRIBE broadcast="speakerA" track="catalog.json"
← GROUP sequence=0
← FRAME {"version":1,"audio":[{"track":"audio/data","codec":"opus","sample_rate":48000,"channel_count":1,"bitrate":32000}]}
The same speaker bumps to 64 kbit/s:
← GROUP sequence=1
← FRAME {"version":1,"audio":[{"track":"audio/data","codec":"opus","sample_rate":48000,"channel_count":1,"bitrate":64000}]}
Compatibility
EGG-12 is purely additive on top of EGG-03. A receiver that does not
support EGG-12 MUST still subscribe to audio/data directly (EGG-03)
and decode at the parameters EGG-03 mandates.
A future EGG MAY widen the catalog schema to describe multiple audio
quality tiers, video tracks, or speaker-side hints (e.g. push-to-talk
state). Those additions MUST keep version: 1 working for existing
parsers; breaking changes ship as version: 2 with a separate EGG.