Skip to content

VMS cameras

The VMS tab of the streams tile manages third-party IP cameras — NVR CCTV feeds, ONVIF PTZ cameras, embed-only streams from proprietary systems. You can add, test, edit, and delete cameras per mission, and each camera has a full geolocation + field-of-view profile so it renders as an FOV cone on the map.

The camera grid

Every camera attached to this mission renders as a card showing:

  • Thumbnail (live if the stream resolves).
  • Name + group tag.
  • Stream type badge (HLS / MJPEG / MP4 / Embed).
  • Location + bearing chip if geocoded.
  • Edit (pencil) and delete (trash) buttons.

Cards are driven by a subscription to Firestore — any edit you make, or anything a teammate makes, shows up within a second.

Add-camera form

Click Add camera in the tab header. A side panel slides in with the form. All fields:

Basics

  • Name — required. Shown on the card and map cone tooltip.
  • URL — required. The raw stream URL. For HLS it’s an .m3u8; for MJPEG it’s the camera’s motion-JPEG endpoint; for MP4 it’s a direct-play URL; for embed it’s an iframe URL.
  • Stream type — dropdown: HLS / MJPEG / MP4 / Embed.
  • Enabled — toggle. Disabled cameras stay in the list but don’t render their stream or FOV cone.
  • Channel — numeric. Useful when multiple cameras share a common NVR naming scheme.
  • Group — free text (e.g. “North perimeter”, “Gate cameras”).
  • Location — free text location label.
  • Notes — free text, up to a few hundred chars.

The four stream types

TypeWhat you provideHow it renders
HLS.m3u8 playlist URLAdaptive-bitrate playback via hls.js. Works in every browser.
MJPEGmotion-JPEG HTTP endpointFrame-at-a-time via <img> tag. High CPU on the viewer but universal.
MP4Direct MP4 URL (file or live-MP4)Native <video> element. Low latency if your server produces live fragmented MP4.
EmbedArbitrary iframe URL<iframe> — used for proprietary web players that can’t be extracted into a direct stream.

Authentication

  • Auth type — dropdown: none / basic / token.
  • Username + password — shown only for basic. HTTP Basic Auth.
  • Auth token — shown only for token. Attached as a Bearer token via the Authorization header (or appended as a query-string if the camera can’t handle header auth; the player tries both).

PTZ

  • PTZ enabled — toggle. Reveals the rest of the PTZ block.
  • PTZ URL — optional. For HTTP-controlled PTZ, the URL template with {direction} / {speed} placeholders. For ONVIF, leave blank.
  • PTZ type — dropdown: onvif / http. ONVIF speaks SOAP ContinuousMove commands; http substitutes into the URL template.
  • PTZ speed — 1-10 slider. Sent with every PTZ command.
  • PTZ profile token — ONVIF only. Most ONVIF cameras auto-expose a default profile; only set this if your camera has multiple profiles and you want to target a specific one.

Location + field-of-view

Fill these to render the camera on the map as an FOV cone on the ground:

  • Lat / Lng — required for map rendering.
  • Height (m) — default 3 m. The camera’s height above ground.
  • Bearing (degrees) — 0-360, default 0. Compass heading the camera points at.
  • Tilt (degrees) — -90 to 0. Downward pitch; -30 is a common angle for perimeter cams.
  • Horizontal FOV (degrees) — 10-180. The camera’s horizontal cone angle.

Missing location fields just skip map rendering — the card and player still work.

The test-stream flow

Click Test after filling URL + auth. The tile calls vmsService.checkHealth(fakeCam) and the testResult signal cycles through these states:

StateMeaning
noneNot tested yet.
liveTest succeeded — stream is reachable and returns video.
auth_error401/403 from the camera. Your credentials are wrong.
offlineConnection refused / timeout / DNS failure. Camera is unreachable.
errorSomething else broke — invalid URL, unsupported codec, corrupt stream.

The result badge stays until you change a field or click Test again. A successful test doesn’t guarantee the camera will work in production (transient network blips) but it catches the common config-error cases.

Saving

Click Save. The camera is written to Firestore under missions/{missionId}/vms_cameras/{cameraId}. It appears on every participant’s grid within a second and, if location fields are filled, on the map as a cone cone.

Editing

Click the pencil icon on any card. The form reopens pre-filled with all current values. Saving updates the Firestore doc in place — the camera’s ID is preserved so flags and any other docs that reference it stay valid.

Deleting

Click the trash icon. A confirmation prompt appears (two-step for safety). On confirm, the camera is removed from Firestore and from everyone’s grid. Deleting a camera does NOT delete any recordings — those live separately.

Sharing across missions

Cameras added via the VMS tab live inside the mission. To share across missions, add them at the org level via Admin → Organisation → VMS library — those appear in every mission automatically.

Per-camera playback

Click a card to open the VMS player in-tile. Controls:

  • Play / Pause.
  • Mute / Unmute.
  • Full-screen.
  • Snapshot (PNG of the current frame).
  • PTZ arrows + zoom rocker if PTZ is configured and enabled.
  • Recording (start / stop) — delegates to the VMS service for server-side recording.

PTZ commands go through an ARGUS proxy (your browser can’t speak ONVIF SOAP directly). The proxy lives in argus-api’s /api/vms surface.

Known limitations

  • No auto-cycle for streams that drop connection — if the NVR reboots, you must manually click into the camera to force a retry.
  • No RTSP direct — only HLS / MJPEG / MP4 / Embed. For RTSP cameras, put a transcoder (e.g. go2rtc or RTSPtoWeb) in front of them and point ARGUS at the HLS output.
  • No multi-camera preset tour — each camera is played individually; there’s no “tour four cameras sequentially” mode.