feat: NV conference provider (Old PoC)

Draft
RO
2mo ago
+25338-562

PoC — not for merge as-is. Draft, stacked on #41657.
Base is feat/persistant-chat, so this diff shows only the native-provider work. Review #41657 first.

Proposed changes

Adds LiveKit as a native video conference provider, so a call can run inside Rocket.Chat instead of handing the user off to someone else's page.

Every provider until now has been a URL. The workspace knows a call is open and nothing else: not who is in it, not what was said, and certainly not how to record it. Running the call in-process changes what the server is able to know, and most of this diff is the consequence of that rather than the SFU itself — conferences now carry the participants actually connected, so presence stops being inferred from who clicked join.

On top of that: multi-party calls with a grid and spotlight, screen sharing, hand-raise and reactions, egress-based recording that lands as an ordinary upload posted in a thread under the call's message, and opt-in live captions from a worker that joins each room as a hidden participant — with note-taking on, the transcript is kept and summarised when the call ends.

The provider is enterprise and off unless configured. A workspace with no LiveKit deployment behaves exactly as before.

Deployment (CloudFormation + walkthrough): docs/features/native-video-conference/deploying-livekit.md.

Where this came from

Ported from #40726 (feat/vc-poc), minus that PR's persistent-chat work, which this stack already carries from #41657. That PR's history splits cleanly: commits up to 7e617cc8a8c are the LiveKit work, everything after is its own conference-window integration. Only the first range was taken, so none of client/views/conference/, client/views/root/, appLayout, desktop-api or startup/routes.tsx came across.

Reconciling against a newer develop needed six things:

  • app/ was restructured — the settings, notifications and file-upload imports across eight EE files point at their new homes (server/settings, server/lib/notifications/core/lib/Notifications, server/lib/media/file-upload, server/meteor-methods/messages/sendFileMessage).
  • useGoToRoom left ui-contexts for the app.
  • fuselage no longer accepts the w / h / bg shorthands.
  • MediaCallRoomActivity gained MediaCallViewProvider and container-height sizing on develop while the PR replaced that sizing with useTileGridLayout; the PR's layout wins, since it is what the rewritten section expects.
  • IVideoConference took both sides — this stack's membership predicates and the provider's participant / recording / transcript records.
  • @livekit/agents and @livekit/rtc-node were pinned at latest, which a committed lockfile cannot honour. Pinned to what resolved (^1.6.2, ^0.13.33).

Then it was wired to the conference window

Testing against a live LiveKit found the seam between the two features, and it was worse than "not wired": with both enabled, the room's call button led to a preflight that never went anywhere. An embedded provider answers the join with an empty url — there is no page to send anyone to — and the conference page read a missing url as "not joined yet", so it re-rendered the preflight forever.

  • The page now waits on having joined rather than on having a url, and renders the call itself when there is no page to embed.
  • The connection is registered with the bridge above the route, which is the same slot the in-room path uses — a call cannot be claimed twice, and it survives the page re-rendering.
  • One bottom bar. The call brings mic, camera, screen, hand and hang-up; the window already had a bar carrying members and chat. The call's controls are handed to that bar and take its centre. They are moved, not rebuilt — the same nodes in the same component — so the two placements cannot drift.
  • The floating mini-view is gone. It followed the user out of the call's room, which a call that always has a window of its own never needs; in that window it drew a second copy of the call over the members panel.
  • Twelve strings in the call's bar were hardcoded English or asked for keys that were never added, so recording, notes, captions and the camera tooltip rendered as Start_recording and friends. The hang-up button read "End call with Call" on group calls.

Steps to test or reproduce

Requires a LiveKit deployment; see the deploy doc. Then, as admin:

  1. Admin → Video Conference — enable LiveKit, set URL / API key / secret, make it the default provider.
  2. Open a channel and press Video call. The preflight opens in a dedicated window; set mic/camera there.
  3. Confirm — the call runs in that window with its chat and members panels beside it, and the controls in the single bottom bar.

Verified

Against a live LiveKit (wss://livekit.dev.rocket.chat):

video-conference.capabilitiesreports the provider embedded: true
video-conference.startcreates the conference, posts the call block
video-conference.joinreturns url: "", records the participant
…livekit.transport.configmints a real room token
The callconnects; live 1280×720 camera track; members panel populates
Preflight honouredstarted with mic off / camera on — the inverse of the provider defaults — and the call came up muted with video
One bar1 footer; 8 call controls + 2 panel toggles in it
Layoutcall column min-width: 0, no horizontal overflow

yarn typecheck clean · jest 309 suites / 2214 passing · mocha 2258 · definition 152 · eslint clean over the ported tree.

Not verified — please exercise before this goes anywhere near merge

  • A second participant. Grid and spotlight layout, per-tile speaking indicators, hand-raise queue positions and reactions have all only been seen with one person in the call.
  • Recording. The egress path, S3 upload, and the thread reply were never triggered.
  • Captions / transcripts / AI summary. The agent worker was never dispatched.
  • The 1:1 VoIP path. MediaCallRoomSection now renders CallStage for direct calls too, replacing develop's MediaCallCardList. That is the ported PR's design, but it changes existing VoIP call rendering and deserves a look on a running workspace.
  • Docker: Dockerfile.alpine gained a musl build of the LiveKit FFI binding; the image was never built here.

Further comments

MEDIA-CALLS-FEATURE.md and deploy/livekit/deploy.md moved under docs/features/native-video-conference/, where this repo keeps feature docs. The CloudFormation templates stay in deploy/livekit/.

🤖 Generated with Claude Code