feat/motion-detection-improvements #8

Merged
elirtf merged 12 commits from feat/motion-detection-improvements into master 2026-06-08 15:16:20 +00:00
Owner
No description provided.
- Pre-seed labeled counters (frames_processed, recording_bytes)
  with inc(0) so time series exist from module load, preventing
  'No data' in Grafana panels
- Update cameras_online gauge from recorder main loop via
  fetch_stream_online_map(), so it refreshes every 10s regardless
  of camera recording policy
- Update Grafana dashboard queries to use camera!="_" filter
  for per-camera panels and use raw counters for stat panels
- Fix per-camera storage display: use clip_count (API field name)
  instead of event_clip_count (nonexistent) — was showing 0 clips
- Fix event clip playback: use eventUrl() instead of recordingsUrl()
  so motion clips are served from /api/events/ instead of
  /api/recordings/, and set direct:true so native <video> is used
  instead of hls.js (was causing infinite buffering)
- Add MQTT client with Home Assistant MQTT Discovery (motion binary sensors, online status)
- Add MQTT config UI (settings page, config schema, password masking)
- Publish motion events from processing engine and camera online status from health sampler
- Add /metrics endpoint to recorder (5055) and processor (5056) worker status servers
- Expose ports 5055/5056 in docker-compose.yml for external Prometheus scraping
- Fix non-go2rtc settings (including MQTT) not being persisted via Configuration page
- Remove duplicate Playback sidebar link (same destination as Recordings)
- Clean up worker_status_server.py exception handling with contextlib.suppress
- Encrypt NVR passwords at rest using Fernet symmetric encryption
  (app/encryption.py, OPUS_ENCRYPTION_KEY env var or auto-generated key)
- Add startup migration to encrypt existing plaintext passwords
- Mask RTSP credentials in /api/cameras/<id>/source endpoint
- Add logging to bare except:pass blocks across the codebase
- Deduplicate _transcode_source/_camera_transcode_value/_env_bool
  functions (go2rtc.py imports from go2rtc_config.py, both use
  utils.env_bool)
- Move MQTT publish outside db.atomic() transaction in health_sampler
- Force MQTT reconnect when broker settings change
- Cache ffprobe native codec detection per URL to avoid repeated probes
- Fix N+1 query in events-only buffer purge (single IN clause)
- Pin transitive dependencies (prometheus-client, pyyaml, werkzeug,
  psycopg2-binary, cryptography)
- Remove DAC_OVERRIDE from service defaults and nginx (least privilege)
- Drop ALL caps on go2rtc, add only CHOWN/NET_BIND_SERVICE/NET_RAW
- Add security headers middleware to Flask (XCTO, XFO, HSTS, RP, PP)
- Add security headers + server_tokens off to nginx
- Detect X-Forwarded-Proto for session cookie secure flag
- Add .env.example documenting all configurable env vars
- Fix Restart Engine to proxy POST through recorder container's HTTP
  restart endpoint instead of broken app.recorder import
- Rename reconcile-storage -> clean-stale-records API endpoint
- Add clean_stale_records() module with batch-delete for missing files
- Add do_POST /restart handler to worker status server
- Frontend: rename reconcileStorage -> cleanStaleRecords, update labels
- Add camera policy breakdown (continuous/motion-only/off) to settings
- Rename 'active recordings' -> 'Segment writers' with context
- Layout: 3-tile responsive grid instead of stacked full-width cards
- Storage header: 'X GB in recordings' to distinguish from disk gauge
- Clearer tooltip on Clean stale records button
- Add auto-calibration endpoint with streaming ndjson progress (POST /api/processing/calibrate)
- Create calibrate.py: frame sampling, noise analysis, scene classification, result merging
- Add calibration progress bar and per-NVR calibrate button in frontend
- Add sensitivity presets (Low/Medium/High/Custom) with dynamic per-detector parameter sections
- Add GroupStoragePathInput component for bulk storage path assignment
- Fix recordings not writing to NAS: clear stale camera storage_path values from DB
- Make docker-entrypoint chown on /recordings non-fatal for NFS mounts
- Fix go2rtc.yaml permissions so Flask app can update camera configs
- Add docs/recording-setup.md documenting NAS, recording modes, and troubleshooting
- Add scripts/mount-storage.sh helper for NFS/SMB mount setup
- Add camera storage_path support and database migration (017)
- Add test suite for recordings, cameras, and recorder retention
- Show detailed toast with changed params on calibration apply
- Backend: expose ice_servers from go2rtc settings for browser RTCPeerConnection
- useGo2rtcWs: shared hook for go2rtc WebSocket signaling with reconnection
- Go2rtcMsePlayer: native MSE via go2rtc WebSocket (no iframe, H.265 support)
- Go2rtcWebrtcPlayer: WebRTC via go2rtc WebSocket signaling (replaces WHIP POST)
- LivePlayer: use new components with multi-mode fallback chain
- Removes iframe-timeout guessing and hardcoded STUN
Features:
- Health dashboard at /health with gauges (CPU, disk, memory, recordings),
  summary pills, and per-camera health table (FPS/latency/bitrate/codec)
- Debounced notifications: per-camera notify_motion_cooldown setting (seconds)
- Dashboard simplified to simple grid with group filter (no widget system)
- Birdseye view component for all-camera mosaic (available for future use)
- Enhanced timeline with zoom slider (24h-1h), reason-based color-coded
  segments, event type filter pills, and pan bar
- DetectionOverlay canvas component for bounding box rendering on playback
- PlaybackViewer wired to accept detections array with visibility toggle
- RecordingsPage: reason filter state, detection toggle, connected to Timeline

Fixes:
- Health summary endpoint broken on peewee 4: row.camera.name not row.camera__name
- Gauge SVG NaN crash when value is non-numeric
- Added error/retry state to HealthDashboard
- Gauge units corrected (MB->GB, removed misleading CPU 'usage')
elirtf merged commit 8fdefe3aab into master 2026-06-08 15:16:20 +00:00
elirtf deleted branch feat/motion-detection-improvements 2026-06-08 15:16:20 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
elirtf/opus!8
No description provided.