feat(nests): align moq-lite catalog with kixelated/hang shape

Switch RoomSpeakerCatalog to the canonical hang catalog format
(camelCase audio.renditions[<track>] with container.kind), wrap
audio frames in the legacy varint(timestamp_us) prefix on publish,
and strip it on subscribe. Also reply to inbound Probe/Fetch/Session
bidis with a bitrate hint or clean FIN instead of hanging.
This commit is contained in:
Claude
2026-05-06 03:16:01 +00:00
parent 5389b32e52
commit 5b7e347ac0
7 changed files with 281 additions and 65 deletions
@@ -203,17 +203,29 @@ class MoqLiteNestsSpeaker internal constructor(
companion object {
/**
* moq-lite catalog manifest broadcast on the
* [MoqLiteNestsListener.CATALOG_TRACK] track. The shape mirrors
* what the kixelated/moq browser watcher parses
* ([com.vitorpamplona.amethyst.commons.viewmodels.RoomSpeakerCatalog]):
* a versioned envelope with an `audio[]` of track descriptors.
* [MoqLiteNestsListener.CATALOG_TRACK] track. Verbatim
* canonical kixelated/moq `hang` shape (camelCase, nested
* `audio.renditions[<trackName>]`, `container.kind = "legacy"`).
* The rendition key MUST equal the moq-lite track we publish
* audio frames on ([MoqLiteNestsListener.AUDIO_TRACK]) so the
* watcher's "subscribe to this rendition" path resolves to our
* actual audio stream.
*
* `container.kind = "legacy"` declares the wire layout the
* watcher must expect inside each moq-lite frame: a single
* `varint(timestamp_us)` prefix followed by the raw codec
* payload (no MOOF/MDAT wrapping). The publisher side honours
* this contract in
* [com.vitorpamplona.nestsclient.audio.NestMoqLiteBroadcaster].
*
* Hard-coded because the speaker's encoder is fixed at
* 48 kHz mono Opus today; if [OpusEncoder] becomes parameterised
* this should be derived from the encoder config instead.
*/
const val SPEAKER_CATALOG_JSON: String =
"{\"version\":1,\"audio\":[{\"track\":\"audio/data\"," +
"\"codec\":\"opus\",\"sample_rate\":48000,\"channel_count\":1}]}"
"{\"audio\":{\"renditions\":{\"" + MoqLiteNestsListener.AUDIO_TRACK + "\":{" +
"\"codec\":\"opus\",\"container\":{\"kind\":\"legacy\"}," +
"\"sampleRate\":48000,\"numberOfChannels\":1}}}}"
/**
* How often the catalog group is re-emitted. The relay drops