Skip to content

feat(rtsp): startup preflight, profile locking, and reconnect hardening#23

Merged
lan17 merged 11 commits intomainfrom
lev/debugrtsp
Feb 12, 2026
Merged

feat(rtsp): startup preflight, profile locking, and reconnect hardening#23
lan17 merged 11 commits intomainfrom
lev/debugrtsp

Conversation

@lan17
Copy link
Copy Markdown
Owner

@lan17 lan17 commented Feb 12, 2026

Summary

This PR introduces mandatory RTSP startup preflight with profile locking, and hardens reconnect behavior so stream recovery does not depend on restarting HomeSec.

The net result is deterministic runtime behavior:

  • stream/profile negotiation happens at startup,
  • runtime uses only locked configurations,
  • reconnect can recover detect-stream routing without process restart.

What Changed

  • Added typed RTSP preflight modules with clear separation of concerns:
    • src/homesec/sources/rtsp/discovery.py
    • src/homesec/sources/rtsp/recording_profile.py
    • src/homesec/sources/rtsp/preflight.py
  • Integrated preflight into RTSP source startup with locked runtime profiles:
    • src/homesec/sources/rtsp/core.py
  • Enforced app-level fail-fast startup with per-source aggregation and cleanup:
    • src/homesec/app.py
  • Decoupled motion vs recording ffmpeg options so stage-specific args do not leak:
    • src/homesec/sources/rtsp/frame_pipeline.py
    • src/homesec/sources/rtsp/recorder.py

Preflight Behavior

For each RTSP camera at startup:

  1. Probe candidate streams with ffprobe (timeout-option fallback supported).
  2. Discover sibling stream URLs (including /stream2 from /stream1 patterns).
  3. Select motion stream (lower cost) and recording stream (higher quality).
  4. Negotiate recording profile in deterministic order:
    • mp4 + v:copy + a:copy (only when audio is MP4 copy-compatible)
    • mp4 + v:copy + a:aac
    • mp4 + v:copy + -an
  5. Validate session limits (dual-stream first, then single-stream fallback).
  6. Validate timestamp stability and auto-enable wallclock timestamp mode when needed.

If any camera preflight fails, startup exits non-zero.

Runtime Hardening Added In Follow-up Commits

  • Timeout capability cache for ffmpeg/ffprobe unsupported timeout options (process-wide), with graceful retry without those flags.
  • Stream2 discovery support for cameras exposing separate main/substream endpoints.
  • Reconnect fallback fix: when detect stream fails and fallback stream also fails, reconnect now probes detect stream again and exits fallback immediately once detect recovers.
  • Recorder/preflight validation and logging hardening updates.

Runtime Guarantees

  • No codec/container renegotiation during active motion recording.
  • Recorder and frame pipeline restarts use locked preflight-selected profiles.
  • Legacy stream.ffmpeg_flags on RTSP sources are warned-and-ignored when auto-preflight is active.

Why This Matters

  • Handles cameras with non-MP4-safe audio (e.g. pcm_alaw) without manual ffmpeg tuning.
  • Reduces risk of missing events by avoiding runtime negotiation.
  • Removes a reconnect failure mode where recovery required restarting HomeSec.

Test Coverage

Added focused tests:

  • tests/homesec/test_rtsp_discovery.py
  • tests/homesec/test_rtsp_preflight.py
  • tests/homesec/test_rtsp_recording_profile.py
  • tests/homesec/test_rtsp_startup_failfast.py
  • tests/homesec/rtsp/test_runtime.py::test_reconnect_retries_detect_stream_when_fallback_fails

Updated affected suites:

  • tests/homesec/rtsp/test_frame_pipeline.py
  • tests/homesec/rtsp/test_runtime.py
  • tests/homesec/test_app.py

Validation

  • make check
    • ruff check src tests
    • ruff format --check src tests
    • mypy --strict
    • pytest tests/homesec/ --cov=homesec --cov-report=term-missing
  • Current branch result: 344 passed.

Notes

  • RTSP transport scope remains TCP-first in this PR.
  • UDP transport negotiation remains deferred.

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 12, 2026

Codecov Report

❌ Patch coverage is 81.94103% with 147 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.71%. Comparing base (d6a31fe) to head (36f7e0b).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/homesec/sources/rtsp/preflight.py 81.92% 60 Missing ⚠️
src/homesec/sources/rtsp/core.py 52.94% 40 Missing ⚠️
src/homesec/sources/rtsp/discovery.py 80.58% 33 Missing ⚠️
src/homesec/sources/rtsp/capabilities.py 96.15% 3 Missing ⚠️
src/homesec/sources/rtsp/frame_pipeline.py 83.33% 3 Missing ⚠️
src/homesec/sources/rtsp/recorder.py 88.00% 3 Missing ⚠️
src/homesec/sources/rtsp/recording_profile.py 93.47% 3 Missing ⚠️
src/homesec/sources/rtsp/url_derivation.py 95.12% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #23      +/-   ##
==========================================
+ Coverage   81.53%   81.71%   +0.17%     
==========================================
  Files          64       69       +5     
  Lines        5247     5976     +729     
==========================================
+ Hits         4278     4883     +605     
- Misses        969     1093     +124     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@lan17 lan17 changed the title feat(rtsp): add mandatory startup preflight and profile locking feat(rtsp): startup preflight, profile locking, and reconnect hardening Feb 12, 2026
@lan17 lan17 merged commit e2f094e into main Feb 12, 2026
2 checks passed
@lan17 lan17 deleted the lev/debugrtsp branch February 12, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant