RustCam
Developers
RustCam requirements, project layout, quick start, configuration, API overview and FAQ.
Environment
Rust
1.95+
PostgreSQL
14+ (PostGIS extension required)
TimescaleDB
PostgreSQL extension (telemetry series)
Redis
6+
Node.js
18+ (frontend build)
ZLMediaKit
Any recent version (ingest / pull / relay)
Qt + CMake
Qt 5.15.2 / 6.2+, CMake 3.16+ (desktop client only)
Project layout
crates/rustcam-media/Rust backend library: api / application / auth / domain / infrastructure / protocol / transport / drone_gatewaycrates/rustcam-server/Server binary (rustcam-media)crates/rustcam-drone-service/Mobile Eye control plane: registry, telemetry shadow, leases, commands, geofences, auditcrates/rustcam-drone-adapter/Airborne adapter: MAVLink / PX4 / ArduPilotcrates/rustcam-drone-sim/MAVLink vehicle simulator for tests and demoscrates/rustcam-drone-proto/Mobile Eye gRPC contractcrates/rustcam-drone-core/Shared types and constantsfrontend/Vue 3 console (Vite + Element Plus + Pinia + Cesium)testenv/One-command Mobile Eye test environment (start.ps1 / stop.ps1 / screenshots)clientapp/Qt desktop client (CMake + FFmpeg)public/Public docs: api.md, architecture.mmd, architecture.pngsql/Database scripts (schema.sql)Quick start
Initialise the database
psql -U postgres -c "CREATE DATABASE rustcam;"
psql -U postgres -d rustcam -f sql/schema.sqlStart the backend
cargo run -p rustcam-server
# or a release build
cargo build --release -p rustcam-server
./target/release/rustcam-mediaStart the web console
cd frontend
npm install
npm run devOne-command Mobile Eye test environment
pwsh -File testenv\start.ps1
# login: admin / admin123
# built-in MAVLink simulator: PX4 / ArduPilotLog in and get a token
curl -s -X POST http://127.0.0.1:8081/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"admin"}'Configuration file
Edit config.toml at the repository root. The block below is the minimal configuration that actually starts: server, database, redis, media_servers, cluster, session, onvif, rtsp_auth, signaling_server and jwt are all required, and the backend refuses to start without them. Always change the JWT secret and database password in production.
[server]
host = "0.0.0.0"
port = 8081
tls_enabled = false
[database]
url = "postgres://user:pass@localhost:5432/rustcam"
max_connections = 10
[redis]
url = "redis://localhost:6379"
pool_size = 5
[[media_servers.servers]]
name = "zlmediakit"
url = "http://127.0.0.1:80"
api_key = "your_api_key"
server_type = "zlmediakit" # zlmediakit / srs / xiu
weight = 100
enabled = true
server_tag = "default"
[cluster]
strategy = "round_robin"
health_check_interval_secs = 30
max_session_per_server = 1000
[session]
expiration_secs = 300
max_per_user = 10
[onvif]
discovery_enabled = false
scopes = ["onvif://www.onvif.org/Profile/Streaming", "onvif://www.onvif.org/Profile/PTZ"]
[rtsp_auth]
enabled = true
realm = "RustCam"
[signaling_server]
server_gb_id = "31011500001000000001"
server_gb_domain = "3101150000"
bind_ip = "0.0.0.0"
tcp_signaling_port = 5060
udp_signaling_port = 5061
rtp_port_start = 15000
rtp_port_end = 15100
rtp_bind_addr = "0.0.0.0"
[jwt]
secret = "change-me-in-production"
access_token_expire_minutes = 60
refresh_token_expire_days = 30
[drone]
service_addr = "http://127.0.0.1:50051"API overview
The Axum backend exposes HTTP + WebSocket endpoints under the /api/v1 prefix, grouped by users and permissions, devices and channels, PTZ, streams, recording, alarms, video walls and the Mobile Eye. The complete list lives in public/api.md in the repository.
Authentication
Every endpoint except the public ones requires a JWT in the request header: Authorization: Bearer <access_token>
Authorization: Bearer <access_token>Endpoint groups
| Group | Count | Endpoints |
|---|---|---|
| Users / roles / permissions | 11 | GET/POST /users, PUT /users/{id}/roles, GET/POST /roles |
| Devices | 13 | GET/POST /devices, POST /devices/{id}/play, GET /devices/{id}/config |
| Channels | 7 | GET/POST /channels, GET /channels/{device_tag}/{channel_tag}/status |
| PTZ | 6 | POST /channels/{d}/{c}/ptz, GET/POST/PUT/DELETE .../ptz/presets |
| Streams | 9 | GET/POST /streams, GET /streams/{id}/play, POST /streams/{id}/restart |
| Recording tasks | 10 | GET/POST /recordings, POST /recordings/{id}/start|stop|pause|resume |
| Recording policies | 5 | GET/POST /recording-policies, PUT/DELETE /recording-policies/{id} |
| Media servers | 10 | GET/POST /servers, GET /servers/{tag}/status, POST /servers/{tag}/enable |
| Video wall layouts | 6 | GET/POST /layouts, PUT /layouts/{id}/default |
| Device groups / regions | 8 | GET /groups/tree, POST /groups, GET /regions/tree |
| ONVIF | 6 | POST /onvif/discover, POST /onvif/probe, POST /onvif/devices |
| Mobile Eye (drone) | 19 | GET/POST /drone/drones, POST /drone/{id}/command, GET/POST /drone/routes, GET/POST /drone/fences, POST /drone/control/acquire |
| Sessions / alarms / stats | 5 | GET /sessions, GET /alarms, GET /api/v1/stats |
Public routes (no authentication)
| POST /api/v1/auth/login, /auth/refresh | Login / token refresh |
| GET /api/v1/health, /metrics, /stats | Health / metrics / stats |
| GET /api/v1/public/streams | Public live streams |
| GET /api/v1/proxy/wfs | Map WFS proxy |
| POST /hook/{event_name}, /hook/{server_type}/{event_name} | Media server hooks |
| POST /alarm/{stream_key} | External alarm intake |
| GET /ws, /ws/audio-talk/{device_tag}/{channel_id} | Event push and two-way talk |
| GET /ws/drone/{kind}?ticket=... | Mobile Eye event push with a one-time ticket |
FAQ
How are devices onboarded?
Through GB28181 SIP registration, ONVIF WS-Discovery, direct RTSP or WebSocket — all unified into one device and channel model.
What happens when a PTZ device is offline?
GB28181 returns 503 and the adapter automatically re-registers the device.
Is HTTPS supported?
Yes, but the backend has no built-in TLS listener: put a reverse proxy (Nginx, for example) in front of it to terminate TLS. WSS uses the same entry point, so the proxy must allow WebSocket upgrades.
How does two-way talk work?
The MediaNode middleware chain performs G711 ⇄ PCM conversion and resampling, backing GB28181 broadcast and ONVIF Backchannel talk.
Can I try the Mobile Eye without drone hardware?
Yes. The repository ships rustcam-drone-sim, which simulates PX4 / ArduPilot heartbeats, telemetry and command ACKs. Run pwsh -File testenv\start.ps1 to launch the simulator, adapter, control plane, server and web console.
Which flight controllers are supported?
PX4 and ArduPilot over MAVLink, detected automatically from HEARTBEAT.autopilot, with UDP / TCP / serial links.
When will other media servers be available?
The media server adapter is ready; some integrations are still partially implemented — see the module progress table on the features page.