go2rtc: auto-reconcile streams so live/recording self-heal

Live and recording both read from the go2rtc restream. If go2rtc's
runtime stream table gets emptied (camera clear via API, go2rtc restart
with a stale/empty config, or a silently-failed startup sync_all), every
restream returns 404 and both live and recording go dark until a manual
`docker restart nvr-go2rtc`.

Add a background Reconciler that every 30s diffs the desired streams
against go2rtc /api/streams and PUTs only the missing ones (existing
streams are left untouched so active producers/consumers are not
disrupted). VERSION -> 0.0.115.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 12:53:02 +05:00
parent 346d3b5b96
commit 00cfca1a57
4 changed files with 79 additions and 1 deletions
+3
View File
@@ -48,9 +48,11 @@ async def lifespan(app: FastAPI):
os.makedirs(runtime.config.storage.path, exist_ok=True)
await go2rtc.sync_all(runtime.config) # потоки (вкл. <cam>_main) в go2rtc для рестрима
runtime.reconciler = go2rtc.Reconciler(runtime.config) # самовосстановление потоков go2rtc
runtime.supervisor.start_all()
runtime.indexer.start()
runtime.retention.start()
runtime.reconciler.start()
log.info("NVR запущен: камер=%d, хранилище=%s",
len(runtime.config.cameras), runtime.config.storage.path)
@@ -58,6 +60,7 @@ async def lifespan(app: FastAPI):
yield
finally:
log.info("остановка NVR…")
await runtime.reconciler.stop()
await runtime.indexer.stop()
await runtime.retention.stop()
await runtime.supervisor.stop_all()