-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Symptom: Recordings page shows spinner forever, no errors in console (Chrome). Works in Safari.
Root cause: hls.js uses new Function() internally. CSP script-src blocks unsafe-eval. Chrome enforces CSP strictly; Safari doesn't.
Fix: RecordingPlayer only plays MP4 (progressive download via /api/v1/recordings/{id}/stream), NOT HLS. No hls.js in RecordingPlayer. Do NOT add hls.js to RecordingPlayer.
Chrome is strict about:
-
Range: bytes=0-→ MUST return206 Partial Content(Safari accepts200 OK) -
pix_fmt=yuvj420pfull-range color → rejects (Safari handles) - CSP
unsafe-eval→ blocks (Safari ignores)
Problem: Cameras may output HEVC or H.264 with pix_fmt=yuvj420p color_range=pc. Both cause Chrome playback failure.
Fix in recording engine:
- HEVC → transcode to H.264:
-c:v libx264 -preset ultrafast -crf 20 -pix_fmt yuv420p - H.264 → apply bitstream filter:
-bsf:v h264_metadata=video_full_range_flag=0 - Codec detected via ffprobe before FFmpeg command is built
Problem: Chrome sends Range: bytes=0- for video pre-flight. Returning 200 OK causes Chrome to reject/drop the stream.
Fix in recordings endpoint:
- Parse
Rangeheader via_parse_range() - Check
is_full_range(start==0, end==file_size-1) - Full range →
200 OK(progressive download, browser buffers as it streams) - Partial range →
206 Partial Content+Content-Range(seeking)
Content-Disposition: inline on video responses interferes with browser playback. Only use attachment for ?download=true.
Problem: FFmpeg crashes every few seconds on stream relay startup.
Fix (v0.01.14):
-
-stimeout→-timeout(FFmpeg 5.1.9 doesn't support-stimeout) - Removed
-reconnectflags (not supported for RTSP in FFmpeg 5.1.9) - Monitor loop:
returncode=0clean exits bypass circuit breaker, 5 quick reconnect attempts - Monitor loop:
returncode≠0errors get 3 attempts with transport fallback
- Frontend calls
POST /api/v1/cameras/{id}/live/start?stream=main|sub -
live_relay.pychecks stream-manager status first, then delegates - Stream-manager starts FFmpeg with libx264 transcode → pushes to MediaMTX
- MediaMTX creates HLS at
rtsp://nvr-mediamtx:8554/{camera_id} - Frontend polls
/hls/{cid}/index.m3u8then initializes HLS.js - Circuit breaker prevents rapid restarts (15s→120s cooldown for stream relay)
-
Idle reaper: stream-manager stops relays with zero MediaMTX readers for 10 min (
STREAM_IDLE_TIMEOUT_S)
Symptom: Server load avg > 30, AI RAM > 900MB
Fix (v0.01.15):
- Reduce AI FPS from 2 to 0.5
- Reduce ONNX threads from 2 to 1
- Lower MOG2 sensitivity from medium to low
- Reduce sub-stream bitrate from 2000k to 1000k
- Limit AI engine Docker CPU to 2 cores
Result: Load avg 41→21 (-48%), AI RAM 955MB→565MB (-41%)
| File | Purpose |
|---|---|
services/stream-manager/app/manager.py |
FFmpeg process lifecycle, circuit breaker, idle reaper |
services/stream-manager/app/relay_api.py |
HTTP API for relay start/stop/status |
services/api/app/services/live_relay.py |
Stream relay delegation to stream-manager |
services/recording-engine/app/main.py |
Recording loops (reconcile/catalog/retention/analytics) |
services/recording-engine/app/recorder.py |
Per-camera FFmpeg supervisor with auto-restart |
services/recording-engine/app/catalog.py |
Segment→DB registration + sync |
services/recording-engine/app/retention.py |
Circular + age-based cleanup |
services/ai-engine/app/main.py |
AI worker reconcile loop |
services/ai-engine/app/detector.py |
YOLOv8 ONNX post-processing + NMS |
services/ai-engine/app/frame_sampler.py |
Motion gate + dedup + event persist |