fix lịch ghi hình và ngày lưu
This commit is contained in:
@@ -21,6 +21,7 @@ from .models import (
|
||||
MediaMTXAddCameraRequest,
|
||||
MediaMTXCamera,
|
||||
MediaMTXConfigView,
|
||||
RecordDeleteAfterUpdate,
|
||||
RecordingToggle,
|
||||
ScheduleUpdate,
|
||||
SchedulerEnabled,
|
||||
@@ -111,9 +112,35 @@ def _set_recording_in_mediamtx_yml(enabled: bool) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def _parse_record_delete_after_days(value: object) -> Optional[int]:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
text = value.strip().lower()
|
||||
if text == "24h":
|
||||
return 1
|
||||
if text == "72h":
|
||||
return 3
|
||||
if text == "168h":
|
||||
return 7
|
||||
return None
|
||||
|
||||
|
||||
def _set_record_delete_after_days_in_mediamtx_yml(days: int) -> None:
|
||||
if days not in {1, 3, 7}:
|
||||
raise HTTPException(status_code=400, detail="invalid_record_delete_after_days")
|
||||
data = _load_mediamtx_yml()
|
||||
path_defaults = data.setdefault("pathDefaults", {})
|
||||
if not isinstance(path_defaults, dict):
|
||||
raise HTTPException(status_code=400, detail="invalid_mediamtx_path_defaults")
|
||||
path_defaults["recordDeleteAfter"] = f"{days * 24}h"
|
||||
data["pathDefaults"] = path_defaults
|
||||
_save_mediamtx_yml(data)
|
||||
|
||||
|
||||
def _build_mediamtx_view(data: dict, cfg: AppConfig) -> MediaMTXConfigView:
|
||||
path_defaults = data.get("pathDefaults") or {}
|
||||
record_enabled = bool(path_defaults.get("record", False))
|
||||
record_delete_after_days = _parse_record_delete_after_days(path_defaults.get("recordDeleteAfter"))
|
||||
|
||||
cameras: list[MediaMTXCamera] = []
|
||||
paths = data.get("paths") or {}
|
||||
@@ -130,6 +157,7 @@ def _build_mediamtx_view(data: dict, cfg: AppConfig) -> MediaMTXConfigView:
|
||||
api_url=cfg.mediamtx_api_url,
|
||||
webrtc_url=cfg.mediamtx_webrtc_url,
|
||||
record_enabled=record_enabled,
|
||||
record_delete_after_days=record_delete_after_days,
|
||||
cameras=cameras,
|
||||
)
|
||||
|
||||
@@ -314,6 +342,14 @@ async def set_mediamtx_recording(data: RecordingToggle) -> MediaMTXConfigView:
|
||||
return _build_mediamtx_view(payload, cfg)
|
||||
|
||||
|
||||
@app.post("/api/mediamtx/record-delete-after")
|
||||
async def set_record_delete_after(data: RecordDeleteAfterUpdate) -> MediaMTXConfigView:
|
||||
cfg = await store.load()
|
||||
_set_record_delete_after_days_in_mediamtx_yml(data.days)
|
||||
payload = _load_mediamtx_yml()
|
||||
return _build_mediamtx_view(payload, cfg)
|
||||
|
||||
|
||||
@app.post("/api/mediamtx/restart")
|
||||
async def restart_mediamtx() -> dict:
|
||||
return _restart_mediamtx()
|
||||
|
||||
@@ -61,8 +61,13 @@ class MediaMTXConfigView(BaseModel):
|
||||
api_url: str
|
||||
webrtc_url: str
|
||||
record_enabled: bool
|
||||
record_delete_after_days: Optional[int] = None
|
||||
cameras: list[MediaMTXCamera]
|
||||
|
||||
|
||||
class MediaMTXAddCameraRequest(BaseModel):
|
||||
rtsp_url: str = Field(min_length=1, max_length=2048)
|
||||
|
||||
|
||||
class RecordDeleteAfterUpdate(BaseModel):
|
||||
days: int = Field(ge=1, le=7)
|
||||
|
||||
@@ -40,7 +40,7 @@ class Scheduler:
|
||||
async def tick(self, schedule: Schedule) -> None:
|
||||
now = datetime.now()
|
||||
state = should_record_now(now, schedule)
|
||||
if self._last_state != state:
|
||||
await self.apply(state)
|
||||
self._last_state = state
|
||||
# Always enforce desired state to recover from external/manual drift.
|
||||
await self.apply(state)
|
||||
self._last_state = state
|
||||
|
||||
|
||||
Reference in New Issue
Block a user