Cameras
EdgeCaster RTSP Gateway
Run EdgeCaster on a Raspberry Pi 5 or any Ubuntu/Debian machine to re-broadcast Rhombus camera streams as sub-second-latency RTSP for legacy VMS, NVR, and third-party video systems.
On this page
- How it works
- Sub-second latency, always the latest frame
- Unlimited concurrent streams
- 24/7 self-healing
- Features
- Requirements
- Install
- Set up (2 minutes)
- Web dashboard
- Live health metrics
- Webhook alerts
- Live logs
- Public access (optional)
- Network ports
- Rhombus API endpoints used
- Managing services
- Auto-updates
- Configuration
- Local development
- EdgeCaster API
- Limitations
- Security notes
- Troubleshooting
- Need help?
- Resources
EdgeCaster is a local edge gateway that pulls Rhombus Secure Raw Streams (H.264 over HTTPS) and re-broadcasts them as standard RTSP on your local network using bundled MediaMTX. It runs on a Raspberry Pi 5, a mini-PC, or any Ubuntu/Debian machine, so legacy VMS, NVR, and third-party AI/video systems that require RTSP can consume video from Rhombus cameras with sub-second added latency. You manage it from a simple web dashboard; it runs 24/7 and heals itself when a stream drops.
Rhombus does not support RTSP natively because it is not a secure protocol. EdgeCaster bridges this gap for environments that require RTSP compatibility by converting Rhombus's encrypted raw streams locally on your network. Deploy EdgeCaster only on trusted networks.
How it works
Rhombus Camera
│
│ Secure Raw Stream (HTTPS H.264)
▼
EdgeCaster (Raspberry Pi 5 / mini-PC / Ubuntu-Debian machine)
│ FFmpeg stream copy (no transcoding)
▼
MediaMTX (RTSP server, port 8554)
│
▼
External Systems (VMS / NVR / AI)EdgeCaster uses the Rhombus API to discover cameras, creates secure raw streams via createRawHttpStream, and pipes them through FFmpeg (stream copy — no transcoding) to MediaMTX, which serves them as standard RTSP.
Sub-second latency, always the latest frame
Because streams are copied rather than transcoded (-c copy), there is no decode/encode delay. EdgeCaster minimizes latency by stripping buffering at every hop instead:
- FFmpeg runs with no input buffering, low-delay flags, reduced probe/analyze time for fast startup, and zeroed mux delay and preload, so packets are forwarded the instant they arrive. The tunables (probe size, analyze duration, stall threshold) are exposed in
/etc/edgecaster/config.yamlif you need to adjust them on-device. - MediaMTX is tuned for low latency and fast failure detection: its control API is enabled on localhost, and a short read timeout drops a stalled publisher quickly. Each RTSP reader gets its own queue, so a slow consumer cannot add latency to the publisher or to other readers.
The result: EdgeCaster always pushes the newest frame with sub-second added latency inside the device. End-to-end ("glass-to-glass") latency also depends on the camera's GOP/keyframe interval and your consuming system's own buffer, which EdgeCaster doesn't control.
Unlimited concurrent streams
There is no fixed stream limit — the device runs as many streams as its network and CPU allow. Because stream copy is very light, real-world testing on a Raspberry Pi 5 showed a handful of 1080p streams plus multiple RTSP readers at roughly 3% CPU, leaving large headroom. max_streams: 0 (the default) means unlimited; set a positive value in config.yaml if you want an optional hard safety ceiling.
24/7 self-healing
EdgeCaster monitors each stream at the frame level using FFmpeg's progress output — not just "is the process alive" — so a frozen-but-alive feed (no new frames) is detected within seconds by a watchdog. All failure triggers (process exit, frozen feed, dead process) funnel through one recovery path that guarantees exactly one relaunch, with no double-restart races. Recovery re-fetches a fresh Secure Raw Stream URL from Rhombus (stream tokens expire) and resumes, typically within seconds.
If a stream keeps failing, EdgeCaster retries fast (every 5 seconds, up to 10 times), then backs off to every 5 minutes — and keeps trying forever. It never permanently gives up on a 24/7 device. Frozen-feed recovery uses a lighter, faster backoff.
Features
- Sub-second added latency, always-latest-frame restreaming (stream copy, no transcoding)
- Unlimited concurrent streams — as many as your device's network and CPU allow
- 24/7 self-healing with frame-level stall detection and automatic stream URL refresh
- Live health dashboard with real-time metrics over Server-Sent Events
- Webhook alerts for stream drops and device strain (Slack, Make.com, or any HTTP listener)
- Live logs viewer in the dashboard — no SSH needed
- Optional one-click secure public access via a Cloudflare quick tunnel
- Automatic camera discovery via the Rhombus API
- Persistent stream state across reboots; streams auto-restore on startup
- Nightly auto-updates, a one-line installer, and a ready-to-flash Raspberry Pi image
Requirements
| Component | Requirement |
|---|---|
| Device | Raspberry Pi 5 (8 GB RAM recommended) or any Ubuntu/Debian machine (mini-PC, VM) |
| Architecture | arm64, amd64, or armv7 |
| Network | Wired Gigabit Ethernet |
| OS | Ubuntu or Debian (the Pi image ships Ubuntu Server 24.04) |
| Rhombus | Org API Key |
Install
On any machine running Ubuntu or Debian (Raspberry Pi, mini-PC, or virtual machine), run:
curl -fsSL https://raw.githubusercontent.com/RhombusSystems/edgecaster-stream-converter/main/scripts/bootstrap.sh | sudo bashThe script downloads and installs everything — FFmpeg, MediaMTX, systemd services — then prints the web address to open.
Flash a ready-to-use image — no typing required:
- Get the image
Ask Rhombus for the EdgeCaster SD-card image, or build one yourself (see the next tab).
- Flash it
Write the
.img.xzfile to an SD card with the free Raspberry Pi Imager. - Boot
Put the card in a Raspberry Pi 5, connect it to your network with an Ethernet cable, and power it on.
- Open the dashboard
Wait a few minutes, then open
http://edgecaster.localin a web browser.
On first boot the device sets its hostname to edgecaster, creates the edgecaster user (default password: edgecaster), and starts all services.
Change the default password immediately after first login: passwd edgecaster
Install from a git checkout:
git clone https://github.com/RhombusSystems/edgecaster-stream-converter.git
cd edgecaster-stream-converter
sudo bash scripts/install.shThe installer keeps a git checkout on the device, so manual installs receive nightly auto-updates just like the Pi image.
To build a flashable SD-card image instead:
# Cloud-init mode (smaller image, needs internet on first boot)
sudo bash image/build-image.sh
# Pre-baked mode (larger image, no internet needed on first boot)
sudo bash image/build-image.sh --prebakedOutput is a flashable .img.xz.
Set up (2 minutes)
- Open the dashboard
Open EdgeCaster in a web browser:
http://edgecaster.localorhttp://<device-ip>. - Paste your Rhombus Org API Key
Your cameras appear automatically.
- Toggle a camera on
Flip the switch next to any camera to start its RTSP stream.
- Connect your systems
Copy the camera's RTSP link into your VMS, NVR, or AI system:
rtsp://<device-ip>:8554/front_door rtsp://<device-ip>:8554/warehouse rtsp://<device-ip>:8554/parking_lotCamera names are normalized to URL-safe slugs and persisted, so RTSP paths survive reboots. Test with VLC:
vlc rtsp://<device-ip>:8554/<stream-name>
Web dashboard
The dashboard is a clean, responsive operator console that works on any device or browser — on mobile, the sidebar becomes a drawer. A persistent status pulse (live stream count and a health dot) is always visible in the top bar.
Live health metrics
The dashboard streams metrics live (about once per second) over Server-Sent Events — no manual refresh: active streams, cameras found, CPU %, memory %, temperature, power/throttle status (under-voltage and throttling), 1-minute load average, uptime, and per-stream throughput and reader counts.
Raspberry Pi temperature and power/throttle metrics require the Raspberry Pi kernel (linux-raspi). On the Ubuntu -generic/virtual kernel these read "N/A" because the OS exposes no thermal sensors. Fix: sudo apt-get install -y linux-raspi && sudo reboot. Everything else works regardless.
Webhook alerts
EdgeCaster can send an alert to a generic webhook — a Slack incoming webhook, Make.com, or any HTTP listener — when:
- A stream drops or can't recover
- The Pi reports under-voltage (power constrained)
- The Pi reports thermal throttling
- CPU or load average stays high
Thresholds are configurable, each alert has a cooldown, and alerts clear on recovery so the webhook isn't spammed. Set it up under Settings → Alerts, which includes a Send test alert button. Active alerts also show on the dashboard.
Live logs
A Logs tab (under Cameras) shows the device's logs live in a terminal-style console — useful for diagnosing a camera or connection issue without SSH:
- Sources: Application, Streams, and Rhombus API
- New lines stream in live, with color-coded log levels
- Pause and clear controls
Public access (optional)
To reach the dashboard from outside your network, go to Settings → Public Access, set a username and password, and click Turn on public access. EdgeCaster creates a secure public link via a Cloudflare quick tunnel and shows it. No Cloudflare account, token, or configuration is required.
The access model: on your local network you never log in; the public link always requires the username and password. Only traffic arriving over the public tunnel is challenged (HTTP Basic auth); the password is stored hashed, never in plaintext.
- The public link is ephemeral — it changes each time public access restarts. That's the trade-off for needing zero Cloudflare credentials.
- The link exposes camera controls: use a strong password and turn public access off when you don't need it.
- Only the web dashboard is exposed publicly — RTSP is not tunneled and stays on the LAN.
Public access requires the cloudflared helper, which the installer includes.
Network ports
| Port | Purpose |
|---|---|
| 80 | Web UI |
| 8554 | RTSP streams (MediaMTX) |
| 8000 | Backend API (internal, localhost only) |
| 9997 | MediaMTX control API (internal, localhost only) |
Rhombus API endpoints used
EdgeCaster interacts with 5 Rhombus API endpoints automatically:
| Endpoint | Purpose |
|---|---|
POST | Discover cameras in your organization |
POST | Create a secure raw stream for a camera |
POST | Clean up stream when disabled |
POST | List existing raw streams |
POST | Resolve location names for the UI |
Managing services
EdgeCaster runs as systemd services (edgecaster and mediamtx) with watchdog integration. Enabled cameras and their RTSP slugs persist across reboots, and streams auto-restore on startup.
# Check status
sudo systemctl status edgecaster mediamtx
# View logs
journalctl -u edgecaster -f
# Restart
sudo systemctl restart edgecaster
# Update now (also runs nightly on its own)
sudo bash /opt/edgecaster/scripts/edgecaster-update.sh
# Uninstall
sudo bash /opt/edgecaster/scripts/uninstall.shAuto-updates
EdgeCaster checks for updates hourly and applies them (git fast-forward) during a configurable window (default: 2:00–5:00 AM). All install methods auto-update, including manual git-checkout installs. Configure via the web UI Settings page or directly:
# /etc/edgecaster/config.yaml
auto_update_enabled: true
update_hour_start: 2
update_hour_end: 5Configuration
Configuration lives in /etc/edgecaster/config.yaml; runtime state (enabled cameras and RTSP slugs) lives in /var/lib/edgecaster/state.json; logs live in /var/log/edgecaster/. Notable keys:
# /etc/edgecaster/config.yaml
max_streams: 0 # 0 = unlimited (default); positive value = hard ceiling
stall_threshold_seconds: 6 # frozen-feed detection threshold
ffmpeg_probesize: 500000 # lower = faster startup
ffmpeg_analyzeduration: 1000000
alerts_enabled: false
alert_webhook_url: ""
cpu_alert_threshold: 85 # percent, sustained
temp_alert_threshold_c: 80
load_alert_threshold: 0 # 1-min load average; 0 = disabledLocal development
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cd backend
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000cd frontend
npm install
npm run dev
# Dev server on http://localhost:5173, proxies /api to backendpip install pytest pytest-asyncio
python -m pytest backend/tests/ -vEdgeCaster API
The EdgeCaster backend exposes a local REST API:
| Method | Path | Description |
|---|---|---|
GET | /api/ | Check setup state |
GET | /api/ | Get app settings |
POST | /api/ | Set Rhombus API key |
PUT | /api/ | Configure auto-update window |
PUT | /api/ | Configure webhook alerts |
POST | /api/ | Send a test alert |
GET | /api/ | Get public access status |
POST | /api/ | Set public access username/password |
POST | /api/ | Turn on public access |
POST | /api/ | Turn off public access |
POST | /api/ | Refresh camera list from Rhombus |
GET | /api/ | List discovered cameras |
GET | /api/ | List active RTSP streams |
POST | /api/ | Start RTSP stream for a camera |
POST | /api/ | Stop RTSP stream |
GET | /api/ | System health snapshot |
GET | /api/ | Live system status (Server-Sent Events, ~1s) |
GET | /api/ | Log snapshot |
GET | /api/ | Live log tail (Server-Sent Events) |
GET | /api/ | List available log sources |
Limitations
- RTSP authentication is not enabled in v1 — restrict access via network controls (can be added via MediaMTX config)
- Consuming systems must be on the local network — RTSP is not tunneled by public access
- Secure raw stream tokens expire automatically; EdgeCaster re-fetches them on recovery
- No login on the LAN web UI — trusted network deployment only (public access adds a login for the public tunnel only)
Security notes
- Your API key is stored in
/etc/edgecaster/config.yaml(owned by theedgecasteruser, not world-readable) - API keys are never logged or exposed in API responses
- The systemd service runs with hardened security:
NoNewPrivileges,ProtectSystem=strict,ProtectHome,PrivateTmp - RTSP streams are unauthenticated — restrict port 8554 access at the network level
- With public access on, only tunnel traffic is challenged with HTTP Basic auth; the password is stored hashed (never plaintext) and LAN traffic is never challenged
Troubleshooting
No cameras found
Verify your Rhombus API key is valid and has access to cameras. Check that the device can reach api2.rhombussystems.com. Try refreshing discovery from the Settings page.
Stream not starting
Check FFmpeg is installed (ffmpeg -version), MediaMTX is running (systemctl status mediamtx), and the camera is online. Check the Logs tab under Cameras, or view logs with journalctl -u edgecaster -f.
RTSP URL not working
Confirm the stream shows "running" in the web UI. Test with VLC: vlc rtsp://<device-ip>:8554/<path>. Check that port 8554 is not blocked by a firewall.
Temperature or power status shows N/A
On a Raspberry Pi running the Ubuntu -generic or virtual kernel, the OS exposes no thermal sensors. Install the Pi kernel: sudo apt-get install -y linux-raspi && sudo reboot. All other metrics work regardless.
Public link stopped working
The public link is ephemeral — it changes each time public access restarts (for example after a reboot). Open Settings → Public Access on the LAN to see the current link.
Auto-update not running
Check the timer: systemctl status edgecaster-update.timer. Verify the installation is git-based (.git folder exists) and the current time falls within the update window.
Need help?
Email support@rhombus.com and we'll help you get set up. It helps to include what you were doing and anything shown on the dashboard.
Resources
Source code, image builder, and issue tracker
Direct streaming integration without RTSP conversion
Embed camera streams in React applications
Full documentation for raw stream and camera endpoints