DJI auto-stream
When a DJI dock is online and assigned to a mission, ARGUS auto-provisions a TACLINK WHIP ingress and tells the dock to push its aircraft camera feed into it. No operator button. No second tool. The stream just appears in the mission’s room within a few seconds and gets torn down cleanly when the dock is unassigned or goes offline.
This page covers what the autopilot does, the preconditions it waits for, how to override it, and what to do when things don’t work.
The preconditions
The autopilot watches a per-dock composite state and only acts when all three conditions are true:
dji_docks/{sn}.online === true— the dock is currently connected to EMQX.dji_docks/{sn}.missionIdis set — the dock has been assigned to an operation.dji_docks/{sn}.liveCapacity.device_listreports at least one aircraft camera.
The third condition matters because live_capacity is the DJI field
telling us which cameras are actually available to stream. A dock with no
aircraft attached or one still in cover-closed startup has no available
capacity — the autopilot waits for update_topo + live_capacity to settle
before acting.
The 2-second debounce
After a dock update Firestore-writes, the autopilot waits 2 seconds for state to settle before acting. On dock-online the composite state (online, missionId, capacity) tends to write in a rapid burst over a few hundred ms; debouncing coalesces them into one reconcile.
What the autopilot does when preconditions match
- Create a WHIP ingress via
livekit-server-sdk’s IngressClient, with:roomName= mission id.participantIdentity=dji-dock-{sn}-{videoSlug}(prefix matches the telemetry peer soisDjiPeer()catches both).participantMetadata= JSON{source: 'dji-cloud', role: 'video', dockSn, videoId, dockModel, autopilot: true}so the webapp can classify without prefix-sniffing.
- Publish MQTT
live_start_pushto the dock withurl_type: 4(WHIP) and the composed WHIP URL. - Dock streams H.264 over HTTPS WHIP → TACLINK ingress → participants subscribe to the video track.
No argus-api round-trip is needed — argus-dji calls LiveKit directly using the credentials it already has. This keeps the path resilient to argus-api outages.
Which camera + lens is auto-selected
By default the autopilot picks the aircraft’s normal-0 camera — the
wide-lens, default-quality stream. Operators can switch lens (wide /
zoom / ir) and quality (smooth / SD / HD / UHD) mid-stream via
the drone-stream tile controls — the autopilot
doesn’t fight the manual change.
Teardown
The autopilot also watches for teardown conditions:
missionId: null → setwas what started us.missionId: set → null— dock was unassigned. Tear down.online: true → false— dock went offline. Tear down.- Dock doc deleted. Tear down.
- Mission completed. Tear down.
On teardown, ARGUS publishes live_stop_push to the dock + deletes the
LiveKit ingress. No leaked ingresses or orphan MQTT publish sessions.
Race conditions handled
- Snapshot races — if the dock flaps online/offline in quick succession, the 2 s debounce absorbs it.
- Mission swap — if
missionIdchanges (dock reassigned mid-op), the autopilot tears the old ingress down and provisions a new one for the new mission’s room. - Double-reconcile — the reconcile is idempotent — if it runs twice with the same state, the second run finds no work to do.
Manual override
You can still start a stream manually even with auto-stream running:
POST /api/dji/streams/start— argus-api’s manual-start route. Useful for starting a second camera (e.g. the dock’s FPV in addition to the aircraft’s wide cam). The manual route uses the same identity + metadata scheme so the webapp renders it alongside auto-stream participants seamlessly.- Operator can also disable auto-stream per mission via Mission detail → Configure → DJI → Disable auto-stream — leaves existing streams alone but won’t start new ones.
Fallback: RTMP
If the dock NACKs WHIP (live_start_push returns non-zero), argus-dji
returns the failure flag up to argus-api’s /api/dji/streams/fallback-rtmp
route, which creates an RTMP ingress and retries. The retry uses the same
room + participant-metadata scheme — the stream lands in the room either
way, just with slightly higher latency for RTMP. This is the only case
where RTMP is used; auto-stream prefers WHIP universally.
Troubleshooting
- Stream doesn’t appear. Check the three preconditions. Most common
cause:
liveCapacitynot yet populated (aircraft still booting). - Ingress leaks. The autopilot is rigorous about cleanup; if you see an ingress not torn down after a mission ends, report the mission ID to support — there may be a rare race we haven’t caught yet.
- Stream drops mid-flight. Usually a network issue on the dock side
— check
dji_docks/{sn}.onlinestate and the dock’s WAN link.
Related
- Streams → DOCKS tab
- Drone stream tile — where the stream opens.
- DJI overview