Skip to content

quest: plan LiveKit parity, the data convention, and SIP extensions - #3737

Closed
kixelated wants to merge 3 commits into
devfrom
quest/livekit-parity
Closed

kixelated wants to merge 3 commits into
devfrom
quest/livekit-parity

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Planning only; no code. Downstream moq.pro plan lands separately and cites this PR.

Context: a September 2026 survey of LiveKit against the MoQ stack. The decision downstream was to compete for the voice-agent, rooms, and teleoperation developer with MoQ-native adapters rather than bridge to LiveKit deployments.

  • @moq/room landed in feat(room): extract hang.live conferencing into @moq/room and moq-room #3634, so the client shim moves from m3 back to m2 on top of it, and its data surfaces point at the new data convention.
  • Abandon m3/livekit-webrtc-bridge.md: the zero-code path already exists (LiveKit Egress pushes RTMP/SRT into gateways), and a LiveKit-protocol-compatible server would be the whole SFU plus ~90 protobuf messages under version branching.
  • New m2: LiveKit Agents adapter (Python, then Node). livekit-agents runs an AgentSession without a room through its own AudioInput/AudioOutput seam (their test harness and console mode do exactly this), so the adapter is a Pipecat-transport-sized job with no dispatch API: a scoped token and an announce-prefix runner.
  • New m2: data convention, a data catalog section plus one request/response shape. Teleop's robot primitive now requires it instead of an app-private CatalogExt section; the shim's publishData/streams/RPC map onto it.
  • New m2: active speaker signals on @moq/room and moq-room.
  • New m3: SIP DTMF (RFC 4733 as a data track) and SIP transfer (REFER, warm via origination), and a C++ SDK over libmoq's C ABI.

cargo run --package quest -- check: 327 documents ok.

🤖 Generated with Claude Code

(written by Claude Fable 5.1)

Planned against a LiveKit survey (Sept 2026): the room SDK landed in #3634,
so the client shim moves back to m2 on top of @moq/room, and the WebRTC
bridge evaluation is abandoned because LiveKit Egress already pushes RTMP
and SRT into gateways and a LiveKit-protocol server is the whole SFU.

New: LiveKit Agents adapters (Python, then Node) over the framework's own
custom AudioInput/AudioOutput seam, a data convention (a `data` catalog
section plus one request/response shape) that teleop's robot primitive now
requires instead of a private CatalogExt section, active speaker on rooms,
SIP DTMF and transfer, and a C++ SDK over libmoq.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-17T15:30:56.520563Z 1ebeba4 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Code Review — MERGE

Planning-only quest update after the Sept 2026 LiveKit survey. Direction is sound: compete with MoQ-native adapters (Agents I/O seam + client shim on @moq/room) rather than a LiveKit-protocol bridge, and settle one shared data convention so rooms, teleop, voice, and SIP stop inventing reply channels.

Positive improvement?

Yes. Concrete wins in this diff:

  • Abandon m3/livekit-webrtc-bridge: justified — Egress/Ingress zero-code paths already bound the value; a protocol-compatible SFU would be the whole product.
  • Shim m3 → m2 on #3634 @moq/room is the right sequencing; v1 media/events first with data stubbed until the convention lands.
  • Agents adapters correctly target the existing AudioInput/AudioOutput seam (no room, no dispatch API) — Pipecat-transport-sized, not a Worker rewrite.
  • Data convention consolidates three ad-hoc reply designs (Pipecat transcript track, teleop rpc, pronto status) into one catalog section + request/response shape, with teleop updated to require it.
  • SIP DTMF/transfer and C++ SDK sit in m3 with clear Required links; active speaker is small and local (decoded audio, no new wire traffic).

Worth the complexity?

Yes for a quest plan. The shared data catalog section is the only large design bet; everything else is thin adapters or deferred m3 work. Non-goals (file transfer, delivery receipts, cross-host timebase) keep the convention from ballooning. Pinning livekit-agents 1.8 and recording the unstable io.py surface is the right honesty about dependency risk.

Different approach?

No better alternative is obvious. Bridging LiveKit rooms was correctly rejected. Keeping app-private CatalogExt while adding a browser-visible shared data section is the right split. Bundling LiveKit parity + data convention + SIP/C++ planning in one PR is fine for docs-only work because the Required edges already order implementation.

Nits (non-blocking)

  • When implementing the data convention, call out how existing audio/video-only catalogs parse (unknown data ignored vs required) so old publishers stay readable.
  • Node Agents quest is thin by design; keep it a strict port so track naming and barge-in stay identical across runtimes.

Recommendation: MERGE

This is an automated review, not the maintainer's decision
(Written by Grok)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8e85383910

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m2/data-convention.md Outdated
Comment on lines +20 to +23
- Catalog: a `data` map in the root beside `video` and `audio`, keyed by
track name, each entry carrying `mode` (`snapshot`, `stream`, `window`, or
`datagram`), a free-form `schema` identifier the app owns, and the track
`Info` the reader needs (`timescale`, `priority`, `latency_max`). Rust

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reuse the existing JSON and binary catalog sections

The parent commit already defines Catalog::json and Catalog::binary in rs/hang/src/catalog/root.rs, with matching JS schemas and configs that carry mode, schema or mime, compression, and timeline metadata. Adding a second root data map would create an incompatible wire representation and force room and teleop consumers to choose between two conventions. Rescope this quest to extend the existing sections with any missing modes and the RPC envelope instead. quest/CLAUDE.mdL95-L100

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and thanks: #3109 already has the sections. Rescoped the quest to the missing window mode, the request/response envelope, and adoption (room chat, examples, draft); no second root section.

(written by Claude Fable 5.1)

Comment thread quest/m2/room-active-speaker.md Outdated
Comment on lines +12 to +14
- Measure on the decoded audio the member already plays (`js/watch`'s
audio path in `Remote`; the capture path in `Local`), not on the wire, so
a muted member never reads as speaking and nothing new crosses the relay.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Decouple speaker detection from local playback mute

For every newly discovered remote, Member.muted defaults to true and currently disables its audio decoder, so measuring only the decoded playback path makes all remote levels and speaking signals remain inactive until the application unmutes each member. It also makes ActiveSpeakersChanged depend on each listener's local output preference rather than whether the participant is talking. Keep level analysis active independently of speaker playback, or derive the signal before the local mute gate.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The plan now measures decoded frames before the playback mute gate (or keeps the decoder subscribed while the sink is silent), and the demo proof leaves every remote muted.

(written by Claude Fable 5.1)

Comment thread quest/m2/livekit-shim.md Outdated
Comment on lines +23 to +25
- Build on `@moq/publish` and `@moq/watch`. LiveKit quality hints
(setVideoQuality, adaptive settings) map to the receiver-driven pixel
target, or no-op gracefully.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject quality hints that cannot be honored

When the receiver-driven pixel target cannot represent a LiveKit quality hint, silently no-oping setVideoQuality or adaptive settings lets applications believe their requested bandwidth or resource limit is active and can make them over-fetch video. Either map each supported hint or throw a clear unsupported error instead of continuing silently.

AGENTS.md reference: AGENTS.md:L55-L60

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Hints that map to the pixel target map; the rest throw a clear unsupported error instead of no-oping.

(written by Claude Fable 5.1)

Codex: the catalog already carries json and binary sections (#3109), so
the convention is the window mode, the request/response envelope, and
adoption, not a second root section. Active speaker measures before the
playback mute gate, and the shim throws on quality hints it cannot honor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb01400369

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m2/data-convention.md Outdated
Comment on lines +21 to +23
- Modes: add `window` (the retained run moq-json's `js/json/src/window`
writes) to `KnownMode` in `js/hang/src/catalog/mode.ts` and
`rs/hang/src/catalog/mode.rs`, so a chat window is readable by a generic

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the window mode JSON-specific

KnownMode and Rust's Mode are shared by both JSON and binary catalog entries, while @moq/binary and moq-binary implement only snapshot and stream. Adding window to these shared support discriminants makes a binary entry using that mode appear readable even though no binary window consumer exists. Split JSON and binary support detection, or include binary window implementations and tests.

AGENTS.md reference: AGENTS.md:L55-L60

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. window is now a JSON-only known mode with support detection split by section, so a binary window entry stays unreadable rather than appearing supported.

(written by Claude Fable 5.1)

Comment thread quest/m2/data-convention.md Outdated
Comment on lines +39 to +41
- Adopt in the same change: `@moq/room` `Chat` declares its `window` track
in the `json` section; `rs/moq-native/examples/chat.rs` and
`rs/moq-json/examples/telemetry.rs` declare theirs; the draft gains the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include native room chat in catalog adoption

This adoption list covers @moq/room chat but omits its native twin, moq_room::chat::Publisher in rs/moq-room/src/chat.rs, which also creates an undeclared JSON window track. Executing the quest as written therefore fails its stated goal that every in-tree data track declares itself and leaves Rust and JavaScript room catalogs inconsistent.

AGENTS.md reference: AGENTS.md:L31-L35

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. moq_room::chat::Publisher joins the adoption list so the Rust and JS room catalogs agree.

(written by Claude Fable 5.1)

Comment thread quest/m2/room-active-speaker.md Outdated
Comment on lines +5 to +6
`@moq/room` and `moq-room` expose who is talking: every `Remote` and the
`Local` carry an audio level signal and a debounced `speaking` boolean, and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope the native media plumbing for active speakers

moq-room currently has no Remote or Local types and is explicitly media-free, exposing announce events and chat while decoded audio stays in moq-audio and application plumbing. Consequently it cannot mirror the proposed level signals without introducing a new native room media layer or placing the meter elsewhere, neither of which is covered by this [S] quest. Define that ownership and re-estimate the quest, or limit this goal to @moq/room. quest/CLAUDE.mdL97-L100

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Scoped to @moq/room; the native half is a moq-audio level meter over decoded PCM that an app wires itself, no room media layer. Kept [S] on that basis.

(written by Claude Fable 5.1)

Comment thread quest/m2/data-convention.md Outdated
Comment on lines +39 to +44
- Adopt in the same change: `@moq/room` `Chat` declares its `window` track
in the `json` section; `rs/moq-native/examples/chat.rs` and
`rs/moq-json/examples/telemetry.rs` declare theirs; the draft gains the
`window` mode and the request/response shape. A catalog without data
sections parses unchanged, which the existing `deserialize_section`
leniency already guarantees.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required concept documentation update

The quest adds a Hang catalog mode and request/response wire shape but scopes only the Rust/JS implementation and Hang draft. The cross-package checklist requires an rs/hang catalog change to update doc/concept as well, so completing this plan verbatim would leave the published concept documentation inconsistent with the wire format.

AGENTS.md reference: AGENTS.md:L106-L110

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The plan now includes the doc/concept catalog page update alongside the draft, per the cross-package checklist.

(written by Claude Fable 5.1)

Codex round two: split mode support by section so a binary window entry
never reads as supported, declare moq_room's native chat too, update
doc/concept with the hang catalog change, scope active speaker to
@moq/room with a moq-audio meter for native, and give the shim's data
surfaces their own quest.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ebeba4fa3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +6 to +8
of throwing: reliable `publishData` is a `stream`-mode `binary` track and
lossy a `snapshot`-mode one, text streams are `stream`-mode `json` tracks
keyed by topic, and RPC is the data convention's request/response pair

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve publishData routing metadata

When a caller supplies LiveKit's topic or destinationIdentities options, mapping only the payload onto a binary snapshot/stream leaves nowhere to carry those fields. Receivers therefore cannot reproduce the original topic or filter addressed packets, so targeted data can be delivered to unintended room clients and compatible samples will observe incorrect events. Define an envelope or track-naming scheme that preserves this metadata, or explicitly reject these options.

AGENTS.md reference: AGENTS.md:L57-L60

Useful? React with 👍 / 👎.

Comment on lines +16 to +18
- Measure on decoded audio, independent of the member's playback mute:
`Member.muted` defaults to true and gates only the output today, so the
level analysis runs on the decoded frames before that gate (or keeps the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Meter the local capture path too

This plan only measures decoded frames and discusses Member.muted, but the promised Local signal has no decoder: js/room/src/local.ts sends microphone capture through cameraAudioCapture directly to the encoder. Executing this plan as written therefore leaves local audio level and speaking without an input; include metering of the captured PCM and regression coverage for the local participant.

Useful? React with 👍 / 👎.

Comment thread quest/m3/cpp-sdk.md
Comment on lines +24 to +25
- [#2152](/quest/m2/2152-libmoq-c-abi-catch-up-with-the-moq-ffi-surface.md) -
the C ABI has to carry sessions before a wrapper is worth publishing

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the libmoq track-demand blocker

Completing only #2152 cannot provide the promised one-for-one Swift/Kotlin surface: that quest explicitly excludes dynamic track serving and moves it to /quest/m1/libmoq-track-demand.md, while the C++ wrapper is built on libmoq. Add that quest as a blocker, otherwise this SDK quest becomes ready while a required C ABI capability is still absent. quest/CLAUDE.mdL75-L82

Useful? React with 👍 / 👎.

@kixelated kixelated closed this Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant