Security SolutionsSoftware de seguridad
Documentación

RTMP, RTMPS and SRT camera streams

Esta documentación técnica está disponible en inglés.

For the mixed fleet above ten million cameras, use the distributed camera-fleet plan. The local addresses below are for the single-machine test installation; fleet cameras use their assigned receiving nodes.

Sentinel ID supports two streaming workflows: pull an existing camera/source stream, or accept an authenticated publisher through the camera stream receiver. Both feed the camera processing and authorised live-view workflow.

Incoming publishing to the current test server

Register the source under Cameras > Add camera > Camera sends images / streams. Save it and copy the dedicated camera key. Use the actual camera record _id in place of CAMERA_ID.

Protocol Destination Network
RTMP rtmp://192.168.1.31:1935/cameras/CAMERA_ID?user=camera&pass=YOUR_CAMERA_KEY TCP 1935
SRT srt://192.168.1.31:8890?streamid=publish:cameras/CAMERA_ID:camera:YOUR_CAMERA_KEY&pkt_size=1316&mode=caller UDP 8890
RTMPS rtmps://YOUR_CERTIFICATE_HOST:1936/cameras/CAMERA_ID?user=camera&pass=YOUR_CAMERA_KEY TCP 1936; enabled only with TLS certificate and private key

These ports are separate from the HTTP API on port 4000. The RTMP/SRT receiver must be running, and the encoder must be able to reach the relevant port through the network/firewall. The setup does not create public DNS records or automatically open router/firewall ports.

Use H.264 video for initial compatibility testing. RTMP normally carries FLV; SRT input uses MPEG-TS. Test the actual codec/profile/encoder before deployment. Body cameras and phone encoder apps may use these URLs if they support RTMP or SRT publishing.

OBS or an encoder with separate server and stream-key fields

Server:     rtmp://192.168.1.31:1935/cameras
Stream key: CAMERA_ID?user=camera&pass=YOUR_CAMERA_KEY

If the encoder supports a full publish URL, use the complete RTMP URL from the table. The admin camera page provides the URLs with the current server hostname and, immediately after creation or rotation, the actual camera key. Keys are shown once.

Test publishing a file

The following examples use an encoder executable named ffmpeg. Substitute the installed encoder path if it is not on PATH. Replace camera ID/key placeholders and use an approved test recording.

ffmpeg -re -i test.mp4 -c:v libx264 -preset veryfast -tune zerolatency -an -f flv "rtmp://192.168.1.31:1935/cameras/CAMERA_ID?user=camera&pass=YOUR_CAMERA_KEY"
ffmpeg -re -i test.mp4 -c:v libx264 -preset veryfast -tune zerolatency -an -f mpegts "srt://192.168.1.31:8890?streamid=publish:cameras/CAMERA_ID:camera:YOUR_CAMERA_KEY&pkt_size=1316&mode=caller"

The receiver accepts only paths of the form cameras/<registered camera _id>. A valid, active key belonging to that enabled push-mode camera is required. The receiver does not grant public stream-reading access. Recognition frames are sampled using the camera's intervalSec and sent through the existing authenticated camera upload API; authorised browser live viewing uses the existing camera MJPEG endpoint.

Rotate the camera key or disable/delete the camera to stop its publisher. Active publishers are rechecked about every 1.5 seconds; pending uploads are also subject to the camera API's key and enabled-state checks. A publisher cannot replace another active publisher on the same path.

Direct source pulling

For a camera or upstream server already exposing a stream, select the matching mode:

Admin mode Source URL example
Server reads the video stream rtsp://CAMERA_IP:554/SOURCE_PATH or rtsps://CAMERA_HOST/SOURCE_PATH
Server reads RTMP / RTMPS rtmp://SOURCE_HOST/APP/STREAM or rtmps://SOURCE_HOST/APP/STREAM
Server reads SRT srt://SOURCE_HOST:PORT?mode=caller&streamid=SOURCE_STREAM_ID

These are source addresses, not publishing destinations on this server. The application must reach the upstream source. SRT source pulling uses caller mode; use the incoming publisher receiver for sources that call this server.

Example registration JSON, sent to POST /api/v1/cameras with an authorised token granting cameras:manage:

{
  "name": "Upstream RTMP camera",
  "mode": "rtmp",
  "purpose": "both",
  "streamUrl": "rtmp://SOURCE_HOST/APP/STREAM",
  "intervalSec": 5,
  "address": "Main gate"
}

Use "mode":"srt" and an srt:// source for SRT. streamUrl is accepted on create/update and stored in the existing rtspUrl field for backward compatibility. Existing RTSP records continue working.

For RTSP/RTMP source authentication, enter the username and password in the separate camera fields where the upstream protocol supports them. For an SRT source requiring encryption, enter its encryption passphrase in the camera password field, or include passphrase in the source URL. Stream IDs and upstream access credentials follow that source's requirements.

Test a source with Cameras > Test. Recognition uses sampled frames; live views use the shared decoder and existing permission-controlled camera-view endpoints. This is not a promise to record every frame or preserve a full original stream automatically. Use the recording/evidence workflow when complete video retention is required.

Receiver installation and startup

Run these commands from the backend project directory:

npm run camera:relay:install
npm run camera:relay

The installer downloads the pinned receiver release from its official source and verifies its SHA256 digest before extraction. It preserves the upstream licence in the installed runtime folder. The standalone launcher connects to the configured application database and forwards sampled frames to CAMERA_RELAY_INGEST_ORIGIN.

When CAMERA_RELAY_ENABLED=true, the updated backend automatically starts the receiver on its API node. If the standalone receiver is already active for that runtime directory, the backend uses it instead of launching a duplicate. Enable a listener on one designated node; route publisher traffic to that node. Restart the backend after installing updated camera code to load new source modes and status routes.

The receiver's private RTSP bridge and control API bind to loopback and require an internal per-process credential. Do not expose those internal ports. On shutdown, managed receiver and decoder processes are stopped. A failed receiver is retried after a delay; a failed decoder is retried while the authorised source remains connected.

Environment configuration

Variable Default / meaning
CAMERA_RELAY_ENABLED false in the example environment; set true on the designated receiving node.
CAMERA_RELAY_BIND 0.0.0.0, receiving interface; use 127.0.0.1 for host-only testing.
CAMERA_RELAY_RTMP_PORT 1935, incoming TCP RTMP.
CAMERA_RELAY_SRT_PORT 8890, incoming UDP SRT.
CAMERA_RELAY_RTMPS_PORT 1936, used only when TLS files are configured.
CAMERA_RELAY_TLS_CERT TLS certificate file path for RTMPS.
CAMERA_RELAY_TLS_KEY Matching private-key file path for RTMPS.
CAMERA_RELAY_SRT_PASSPHRASE Optional SRT encryption secret, 10-79 characters; configure the same value on each publishing encoder.
CAMERA_RELAY_INTERNAL_RTSP_PORT 8555, private loopback bridge.
CAMERA_RELAY_CONTROL_PORT 9998, private loopback control API.
CAMERA_RELAY_MAX_STREAMS 24, maximum authorised concurrent publishers; increase only after workload testing.
CAMERA_RELAY_INGEST_ORIGIN http://127.0.0.1:4000, application origin receiving sampled camera frames.
CAMERA_RELAY_DIR Empty uses storage/camera-relay; contains private configuration and receiver status.
CAMERA_RELAY_BIN Empty uses the installed executable under the runtime directory's bin folder.
CAMERA_STREAM_CA_FILE Optional trusted PEM CA file for direct RTMPS sources; certificate validation remains enabled.
CAMERA_VIDEO_MAX_SOURCES 32, maximum active compressed viewing sources per process; viewers share each source.
CAMERA_LIVE_MAX_SOURCES 32, maximum active image-mode viewing sources per process.
CAMERA_LIVE_FPS 15, image fallback frame rate; does not limit compressed video or recognition sampling.
CAMERA_VIEW_PORT 4100, port of the optional dedicated viewing process.
CAMERA_VIEW_BIND 127.0.0.1, viewing process interface; expose through the trusted HTTPS proxy.

For SRT encryption append &passphrase=YOUR_SRT_ENCRYPTION_SECRET to the encoder URL or use its encryption setting. The SRT passphrase is separate from the dedicated camera key in streamid. Keep both private. For internet-facing RTMP use RTMPS with a valid certificate, or an approved private network/VPN; plain RTMP is not encrypted.

In production, set CAMERA_RELAY_INGEST_ORIGIN to the application's trusted HTTPS origin if the application's transport policy requires HTTPS, including for the receiver's local uploads.

Status, commissioning and limits

Live-view performance

For compatible H.264 streams, the admin wall requests compressed video over ws(s)://SERVER/api/v1/cameras/CAMERA_ID/view?format=fmp4&token=USER_TOKEN. It forwards the camera's encoded video in small fragmented MP4 segments; the server does not decode, resize or re-encode the viewing feed. The browser decodes the video and follows the live edge. Multiple viewers on the same node share one camera connection. This uses cameras:read and the user's agency visibility, network policy and session checks. Access is checked again every 15 seconds. Reverse proxies must forward WebSocket upgrades; the supplied Nginx examples include this route.

Unsupported codecs and browsers, snapshot cameras and event-only cameras fall back to binary JPEG, then the existing MJPEG /live endpoint when necessary. Image-mode sources share one decoder per camera on each viewing node. CAMERA_LIVE_FPS=15 controls this fallback (1–30), separately from recognition intervalSec. Compressed video retains the source's frame rate. Browser buffers retain only a short live window, image viewers drop queued frames, and slow compressed connections are closed rather than accumulating an unbounded backlog. The wall selects at most 16 tiles; source limits bound the work on each viewing node.

In Cameras > Edit camera, optionally enter a Live-view substream URL (liveUrl in the API). A smaller H.264 stream reduces decoding and bandwidth on a multi-camera wall. The main source remains available for recognition. Frame-based live-view recordings also use the selected viewing source. For incoming RTMP/SRT, use H.264 in the encoder, a keyframe interval of approximately one second, and a low-latency encoder preset where available. Long keyframe intervals delay the first usable picture and late joins. These encoder settings require changes on the camera/encoder, not just the receiving server.

For an active incoming RTMP/SRT publisher, a viewing server colocated with its assigned receiver reads continuous video from the receiver's private loopback stream. This avoids the recognition sampling interval. A viewing node without that receiver uses the uploaded images; deploy viewing beside each assigned receiver for continuous playback. HTTP event-only and snapshot cameras remain limited by how often they produce pictures. These changes do not establish a 10-million-camera capacity benchmark.

Dedicated production viewing process

Start npm run camera:viewer alongside the application and assigned receiver. It listens on CAMERA_VIEW_BIND:CAMERA_VIEW_PORT and serves camera WebSockets and a health check. It does not start recognition galleries, polling workers, scheduled recognition jobs or camera ingestion endpoints. It must use the same database, authentication secrets and receiver runtime directory as the application/receiver. This allows live video to run outside the recognition API process.

The complete single-host proxy example is deploy/nginx/camera-viewer.conf.example. It routes /api/v1/cameras/CAMERA_ID/view to port 4100 and other application traffic to port 4000, preserving one browser origin. The process alone does not change routing: install the proxy configuration to use it. Keep internal ports private, and retain the existing production HTTPS and trusted-proxy settings.

For cluster-based image fallback and camera invalidations, give the viewer a unique NODE_NAME and NODE_URL, and configure CLUSTER_PEERS in both directions with the shared CLUSTER_KEY. For example, the API can advertise http://127.0.0.1:4000 and the viewer http://127.0.0.1:4100; each includes the other in its peers. Use process-specific environment overrides. Start the main application first to provision its database indexes. The dedicated process does not replace the receiver or recognition workers.

For multiple receiving hosts, route each camera's viewing request to a viewer beside its assigned receiver; ordinary round-robin across unrelated receiver hosts will not provide every camera's continuous feed. Size and benchmark each node with the intended camera resolution, bitrate, codec, simultaneous viewers, recording activity and recognition workload before increasing the guards. Spread receiver/viewing nodes and recognition workers across the fleet.

GET /api/v1/cameras/connection-info with cameras:read returns supported pull protocols and receiver availability, ports, encryption configuration and stream limit, without returning internal secrets. Cameras > Connection details shows this information and the setup examples.

  1. Confirm the updated backend has restarted and the receiver reports running.
  2. Register an enabled push-mode camera and copy its key.
  3. Publish a short test stream using its exact camera ID and key.
  4. Verify that frames arrive, the camera becomes online and an authorised live view displays the image.
  5. Test a configured recognition/site rule with approved records.
  6. Disable the camera or rotate the key and confirm the stream disconnects.

If publishing fails, check the separate TCP/UDP ports, correct cameras/CAMERA_ID path, active key, camera mode, SRT stream ID and encryption settings. A connection alone does not establish codec compatibility. Network bandwidth, decoder CPU and recognition load determine practical concurrent capacity; the configured stream limit is a resource guard, not a performance benchmark.

For HTTP images, clips, NVR snapshots and officer-approved field sharing, see Camera and field-phone connections.