Appearance
Architecture
Overview
ForgeVis takes each camera's stream once and hands it to every consumer through a broadcast architecture. No transcoding by default: video from the camera is recorded and served as is. Transcoding starts only when a viewer picks 720p over HLS.
Core Components
┌─────────────┐
│ Camera │ RTSP/H.264
│ (source) │────────────┐
└─────────────┘ │
▼
┌──────────────┐
│ StreamHub │
│ (broadcast) │
└──────────────┘
│
┌──────────┼──────────┐─────────┐
▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│Recorder│ │ RTSP │ │ RTSP │ │ HLS │
│ │ │Client 1│ │Client 2│ │Client 1│
└────────┘ └────────┘ └────────┘ └────────┘
│ │
▼ ▼
┌────────┐ ┌────────┐
│ Disk │ │ HLS │
│ (fMP4) │ │Client 2│
└────────┘ └────────┘StreamHub
Purpose: Single connection to camera, broadcast to multiple consumers
Key Features:
- One RTSP connection per camera
- Internal frame buffer for smooth distribution
- Lazy connection: starts on first subscriber
- Idle timeout: disconnects after N seconds without subscribers
Data flow: Camera → StreamHub → Multiple consumers (Recorder + RTSP clients)
Recorder
Purpose: Write video frames to fMP4 segments
Key Features:
- Fragmented MP4 format
- Configurable segment duration (default: 900s = 15 minutes)
- Automatic reconnection on timeout/error
- Path templates with placeholders
Process:
- Subscribe to StreamHub
- Wait for keyframe to start recording
- Write video data to file
- Create new segment file every N seconds
- Finalize segment on timeout or manual stop
RTSP Server
Purpose: Restream camera feeds to RTSP clients
Key Features:
- Full RTSP protocol support
- TCP transport for reliability
- Automatic packet fragmentation for network efficiency
- Main + substream support (
/camera_001and/camera_001/sub)
How it works:
- Client connects via RTSP protocol
- Server subscribes to StreamHub for this camera
- Video frames are packaged and sent to client
- Connection closes automatically when client disconnects
Data Flow
Recording Path
Camera (RTSP)
→ StreamHub (broadcast)
→ Recorder (subscribe)
→ Disk (fMP4 segment files)Restreaming Path
Camera (RTSP)
→ StreamHub (broadcast)
→ RTSP Server (subscribe)
→ Client (VLC, media players)No Transcoding by Default
Video from the camera is recorded and served as is.
Recording and restreaming:
- ✅ Read the stream from the camera
- ✅ Write it to files and serve it to clients
- ✅ Package it for network transport and into MP4 containers
- ❌ Decode, process or encode video
- ❌ Change bitrate, resolution or quality
Result: Minimal CPU usage, can handle thousands of cameras
The 720p step over HLS
Transcoding starts only when a viewer picks 720p over HLS. The step is encoded by a separate ffmpeg process from this node's own RTSP restream, so recording and other viewers are not affected. The encoder runs while the step is watched, and at most transcodeMaxConcurrent run at once. See Choosing the quality.
Concurrent Processing
- Async architecture: Non-blocking operations for maximum efficiency
- Per-camera tasks: Each camera runs independently
- Broadcast distribution: Efficient frame sharing between consumers
- Non-blocking I/O: Network and disk operations don't block other cameras
Memory Usage
Per camera (~10 MB):
- Frame buffer for smooth distribution
- Minimal packet buffers
- Short-term write buffer
For 1000 cameras: ~10-12 GB RAM total
Scalability
Bottlenecks:
- Network I/O (4 Gbps for 1000 cameras @ 4 Mbps)
- Disk I/O (500 MB/s write for 1000 cameras)
- File descriptors (1 socket per camera)
- Memory (10 GB for 1000 cameras)
Solutions:
- Multiple 10G NICs or network interfaces
- NVMe SSD or RAID for disk writes
- Increase ulimit:
ulimit -n 100000 - 32-64 GB RAM
Recording and Delivery on Separate Servers
Recording and serving viewers can be split across servers: the camera is still connected once, and a separate server carries the viewer load.
Recording server (origin)
- Connects to cameras (RTSP)
- Records to disk (fMP4)
- Restreams over RTSP for the delivery server
Delivery server (edge)
- Takes the stream from the recording server, like from any camera
- Serves viewers over RTSP, HLS and WebRTC
Benefits:
- Single connection to camera
- Fault tolerance (the delivery server can fail independently)
- Scalable (add more delivery servers)
In a cluster, the recorder and streamer node roles do the same — see Clustering.
Example configuration
Recording server:
yaml
rtsp:
enabled: true # internal restream
port: 8554
cameras:
camera_001:
source: "rtsp://camera-ip/stream1"
record: true # enable recordingDelivery server:
yaml
rtsp:
enabled: true # for clients
port: 8554
cameras:
camera_001:
source: "rtsp://origin-server:8554/camera_001" # from Origin
record: false # restream only