cameras: split camera enable (Вкл) from REC (record-to-disk)

Add a separate `record` field so a camera can be registered but fully
off, or on but not recording:
- enabled (Вкл): camera on/off. Disabled = no go2rtc stream (no live),
  no recording; entry is just stored. build_streams/sync_all/reconcile
  skip disabled cameras; live grid shows "камера выключена".
- record (REC): write segments to disk. Recorder runs only when
  enabled AND record.

Unified POST /api/cameras/{id}/toggle {enabled?, record?} (replaces the
/record endpoint); go2rtc is touched only when `enabled` changes, so
flipping REC doesn't blip live. Camera table gets Вкл + Запись toggle
columns; add/edit forms get both switches.

load_config migrates the old schema (no `record` key): old `enabled`
meant "record" with live always on -> enabled=True, record=old enabled.

VERSION -> 0.0.126.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 18:35:26 +05:00
parent 7060f26e86
commit 24155a8492
7 changed files with 97 additions and 44 deletions
+6
View File
@@ -60,6 +60,8 @@ def _streams_for(cam: Camera) -> dict[str, str]:
def build_streams(config: Config) -> dict:
streams: dict = {}
for c in config.cameras:
if not c.enabled: # выключенная камера — без потоков (ни live, ни записи)
continue
for name, src in _streams_for(c).items():
streams[name] = [src]
return streams
@@ -120,6 +122,8 @@ async def sync_all(config: Config) -> None:
write_go2rtc_yaml(config)
base = config.live.go2rtc_url.rstrip("/")
for cam in config.cameras:
if not cam.enabled:
continue
for name, src in _streams_for(cam).items():
await _call("PUT", _put(base, name, src))
@@ -151,6 +155,8 @@ async def reconcile(config: Config) -> int:
return 0
added = 0
for cam in config.cameras:
if not cam.enabled: # выключенные камеры в go2rtc не держим
continue
for name, src in _streams_for(cam).items():
if name not in existing:
await _call("PUT", _put(base, name, src))