-c:v copy) and only
changes the container, so the relay stays light and adds little latency.
It lives in
github.com/altnautica/ADOSMissionControl
under tools/video-relay/, GPL-3.0.
How it works
The browser side of this is the GCS MSE player
(
src/lib/video/mse-player.ts). It expects an H.264 stream and uses
the codec string video/mp4; codecs="avc1.640029". If you change the
relay’s input codec, that codec string has to change to match.Quick start (local)
3001 by default. Connect a WebSocket client
to ws://localhost:3001/ws/stream/{deviceId}, where {deviceId} is the
RTSP stream name. The device id must match [a-zA-Z0-9_-]+; anything
else is rejected with a 400 on the upgrade.
Health check
A plainGET to the relay returns a small JSON status with the active
session count and a per-device viewer count:
activeSessions is the number of live ffmpeg sessions. The sessions
map gives the viewer count per device id.
Configuration
The relay reads two environment variables.The HTTP and WebSocket listen port.
The RTSP source URL template. The relay replaces
{deviceId} with
the stream name taken from the WebSocket path. The default points at
localhost:8554, which works when mediamtx runs on the same host as
the relay.RTSP_URL_PATTERN to reach that source. The compose file
defaults to host.docker.internal so a relay container can reach an
RTSP server on the Docker host.
Deploy with Docker
The relay ships its own compose file undertools/video-relay/deploy/.
Fill in the env file
Set the RTSP source and, if you expose the relay through a tunnel,
the tunnel token.
- video-relay: the Node.js relay plus ffmpeg, published on port
3001. - cloudflared: an optional tunnel that exposes the relay to a public hostname. WebSocket connections are ordinary HTTP upgrades, so they pass through a tunnel with no special configuration.
Browser client
A minimal MSE viewer: open a WebSocket, create aMediaSource, and feed
each binary frame into a SourceBuffer.
!buf.updating), and prune the buffer as it grows. The
GCS player at src/lib/video/mse-player.ts is a full reference
implementation with queueing, reconnect, and buffer management.
Where this fits
The video relay is the streaming layer of the cloud relay. It is optional and independent of the other layers: you run it only when you want live video in the browser across a network, on top of a self-hosted Convex backend and the MQTT bridge. For a single host that brings up everything at once, see the all-in-one stack.MQTT bridge
Forward live telemetry to Convex over Mosquitto.
All-in-one stack
One Docker Compose for the whole self-hosted stack.