This document defines the default RTSPanda streaming profile and tuning knobs for latency, stability, and scaling.
Before this update, streaming config had drift across files:
- Runtime template in
backend/internal/streams/mediamtx.goused:sourceOnDemand: nohlsAlwaysRemux: yeshlsSegmentCount: 7
- Reference template in
mediamtx/mediamtx.yml.tmpland internal notes expected:sourceOnDemand: yeshlsAlwaysRemux: nohlsSegmentCount: 3
That mismatch changed behavior in production-like runs: higher steady RTSP fan-out, larger HLS buffers, and conflicting memory assumptions.
Source of truth: backend/internal/streams/mediamtx.go (generated at runtime to DATA_DIR/mediamtx.yml).
Global defaults:
MEDIAMTX_SOURCE_ON_DEMAND=trueMEDIAMTX_SOURCE_ON_DEMAND_CLOSE_AFTER=10sMEDIAMTX_HLS_ALWAYS_REMUX=falseMEDIAMTX_HLS_SEGMENT_COUNT=3MEDIAMTX_HLS_SEGMENT_DURATION=2sMEDIAMTX_HLS_PART_DURATION=200ms- Per-path transport defaults remain:
rtspTransport: tcprtspAnyPort: yes
Latency:
hlsSegmentCount=3+hlsPartDuration=200mskeeps playback startup and live edge tighter than a larger segment window.
Stability:
rtspTransport=tcpavoids common UDP RTP breakage in Docker/NAT/camera-vendor networks.hlsSegmentDuration=2sis conservative enough to reduce segment churn while remaining responsive.
Scaling:
sourceOnDemand=trueprevents opening RTSP sessions for cameras nobody is watching.hlsAlwaysRemux=falseavoids continuous remux work for idle paths.
All values are optional environment variables on the backend process (rtspanda service in compose).
| Variable | Default | Allowed / Guidance | Tradeoff |
|---|---|---|---|
MEDIAMTX_SOURCE_ON_DEMAND |
true |
true/false |
false gives fastest instant viewing, but scales poorly with many cameras. |
MEDIAMTX_SOURCE_ON_DEMAND_CLOSE_AFTER |
10s |
1s to 5m |
Higher reduces reconnect churn; lower releases camera sessions faster. |
MEDIAMTX_HLS_ALWAYS_REMUX |
false |
true/false |
true reduces first-view delay but keeps idle remux work active. |
MEDIAMTX_HLS_SEGMENT_COUNT |
3 |
2 to 10 |
Higher smooths bad networks but increases memory and latency. |
MEDIAMTX_HLS_SEGMENT_DURATION |
2s |
1s to 10s |
Lower can reduce latency but increases CPU/IO churn. |
MEDIAMTX_HLS_PART_DURATION |
200ms |
100ms to 2s, must be < segment duration |
Lower can improve live edge but increases part cadence overhead. |
If an env value is invalid, RTSPanda logs a warning and falls back to safe defaults.
After start, verify DATA_DIR/mediamtx.yml matches expected values.
Docker:
docker exec rtspanda sh -lc "sed -n '1,160p' /data/mediamtx.yml"Local run:
Get-Content .\data\mediamtx.ymlCheck one path through mediamtx API:
curl -s http://127.0.0.1:9997/v3/config/get | jq '.paths | to_entries[] | select(.key|startswith("camera-")) | .value | {sourceOnDemand, sourceOnDemandCloseAfter, rtspTransport, rtspAnyPort, record}'- Backend startup logs now print the resolved streaming profile once.
- mediamtx metrics endpoint should answer on
127.0.0.1:9998/metrics.
- Open one camera: stream should become online and HLS playlist should load.
- Close viewer tab for >10s: camera path should stop pulling source when
sourceOnDemand=true. - Reopen viewer: stream should recover without manual reset.
- Defaults are conservative and do not require additional secrets or files.
- Invalid env overrides do not crash startup; they degrade to defaults with explicit warnings.
- The same profile is used for both initial YAML render and runtime path add/update API calls, preventing drift over process lifetime.