Streams overview
The streams tile is a unified browser for every live video source the mission has. It has three tabs and a single selection event that the rest of the console listens for.
The three tabs
TACLINK
Every peer-to-peer video track currently published into the mission room — handheld Android drones, DJI dock aircraft, bodycams, phone cameras. Rendered as a live- thumbnail grid.
VMS
CCTV and IP cameras attached to this mission — HLS, MJPEG, MP4 direct, or embed. Includes an add-camera form, per-camera test, PTZ controls, and map-integration metadata.
DOCKS
DJI docks currently assigned to this mission, scoped to your org. Status, battery, activity text, and a one-click open.
See per-tab pages for details:
What the tile reads from the room
The tile subscribes to WebRtcService.status$ and reflects status.video.streams[].
Each entry carries:
peerId— the LiveKit participant identity (e.g.dji-dock-{sn}for a DJI dock’s telemetry peer;dji-dock-{sn}-{videoSlug}for its video ingress; other IDs for handheld peers).trackId— the specific video track within that peer. Secondary drone tracks (zoom/thermal) carry aVIDEO_DRONE_TRACK_ID + '_…'suffix and are hidden from the grid.stream— theMediaStreamitself.active— whether the track is currently producing frames.
Drone-name resolution runs in a reactive effect: every new peer id is looked up
against Firestore assets (firebaseApi.getAsset(droneId)) to render a friendly
callsign instead of a UUID. Results cache in a droneNames signal so subsequent
renders are free.
Opening a stream (the selection event)
Clicking any stream thumbnail emits the streamSelected event from the tile. The
payload shape:
{ peerId: string; trackId: string; isDrone: boolean; dockSn?: string; mode?: 'taclink' | 'djiCloud';}- For regular drone peers,
isDrone: true, nodockSn,mode: 'taclink'. - For DJI dock peers,
isDrone: true,dockSnresolved from the peer id,mode: 'djiCloud'— this tells the drone-stream tile to route through the DJI Cloud transport instead of TACLINK. - For VMS cameras, a separate flow (no
streamSelectedevent) routes into the camera-stream tile or the VMS player pane.
The parent component (usually operation.component) listens for the event and
switches the bound drone-stream tile to the selected stream.
Debug-mode overlays
With debug mode enabled, every stream card gains a
small latency badge showing round-trip time in milliseconds. The tile polls
RTCPeerConnection.getStats() for each connected peer every 2 seconds and pulls
currentRoundTripTime from the selected candidate pair. Values above ~200 ms are
a sign of packet loss or a TURN relay; below 100 ms indicates a healthy direct or
fast-relay path.
Debug badges are additive — if you enable them before opening TACLINK, they show up for every stream once you flip to that tab.
Cycling between streams
The tile header has prev/next chevron buttons when more than one stream is
available. They call cyclePrevStream() / cycleNextStream() which advance the
selection modulo the stream count, wrap-around at the ends. The header shows the
current position as N / total.
No keyboard shortcuts are wired for cycle; operators who want shortcuts should rebind them through the controls page.
Tab persistence
The current tab is stored in the activeTab signal — it’s session-scoped (not
persisted across reloads). If you always want TACLINK first, that’s the default
— other tabs are opt-in per-session.
Related
- TACLINK
- VMS cameras
- DOCKS
- Stream forwarding
- Recordings
- Drone stream tile — where selected streams open.