mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-01-22 20:18:30 +03:00
add endpoint
This commit is contained in:
parent
a636e37b6e
commit
97ee0c2f40
@ -25,7 +25,7 @@ from pydantic import ValidationError
|
|||||||
|
|
||||||
from frigate.api.auth import allow_any_authenticated, allow_public, require_role
|
from frigate.api.auth import allow_any_authenticated, allow_public, require_role
|
||||||
from frigate.api.defs.query.app_query_parameters import AppTimelineHourlyQueryParameters
|
from frigate.api.defs.query.app_query_parameters import AppTimelineHourlyQueryParameters
|
||||||
from frigate.api.defs.request.app_body import AppConfigSetBody
|
from frigate.api.defs.request.app_body import AppConfigSetBody, MediaSyncBody
|
||||||
from frigate.api.defs.tags import Tags
|
from frigate.api.defs.tags import Tags
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
from frigate.config.camera.updater import (
|
from frigate.config.camera.updater import (
|
||||||
@ -34,6 +34,7 @@ from frigate.config.camera.updater import (
|
|||||||
)
|
)
|
||||||
from frigate.ffmpeg_presets import FFMPEG_HWACCEL_VAAPI, _gpu_selector
|
from frigate.ffmpeg_presets import FFMPEG_HWACCEL_VAAPI, _gpu_selector
|
||||||
from frigate.models import Event, Timeline
|
from frigate.models import Event, Timeline
|
||||||
|
from frigate.record.util import sync_all_media
|
||||||
from frigate.stats.prometheus import get_metrics, update_metrics
|
from frigate.stats.prometheus import get_metrics, update_metrics
|
||||||
from frigate.util.builtin import (
|
from frigate.util.builtin import (
|
||||||
clean_camera_user_pass,
|
clean_camera_user_pass,
|
||||||
@ -602,6 +603,68 @@ def restart():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/media/sync", dependencies=[Depends(require_role(["admin"]))])
|
||||||
|
def sync_media(body: MediaSyncBody = Body(...)):
|
||||||
|
"""Sync media files with database - remove orphaned files.
|
||||||
|
|
||||||
|
Syncs specified media types: event snapshots, event thumbnails, review thumbnails,
|
||||||
|
previews, exports, and/or recordings.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
body: MediaSyncBody with dry_run flag and media_types list.
|
||||||
|
media_types can include: 'all', 'event_snapshots', 'event_thumbnails',
|
||||||
|
'review_thumbnails', 'previews', 'exports', 'recordings'
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON response with sync results for each requested media type.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
results = sync_all_media(
|
||||||
|
dry_run=body.dry_run, media_types=body.media_types, force=body.force
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if any operations were aborted or had errors
|
||||||
|
has_errors = False
|
||||||
|
for result_name in [
|
||||||
|
"event_snapshots",
|
||||||
|
"event_thumbnails",
|
||||||
|
"review_thumbnails",
|
||||||
|
"previews",
|
||||||
|
"exports",
|
||||||
|
"recordings",
|
||||||
|
]:
|
||||||
|
result = getattr(results, result_name, None)
|
||||||
|
if result and (result.aborted or result.error):
|
||||||
|
has_errors = True
|
||||||
|
break
|
||||||
|
|
||||||
|
content = {
|
||||||
|
"success": not has_errors,
|
||||||
|
"dry_run": body.dry_run,
|
||||||
|
"media_types": body.media_types,
|
||||||
|
"results": results.to_dict(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if has_errors:
|
||||||
|
content["message"] = (
|
||||||
|
"Some sync operations were aborted or had errors; check logs for details."
|
||||||
|
)
|
||||||
|
|
||||||
|
return JSONResponse(
|
||||||
|
content=content,
|
||||||
|
status_code=200,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error syncing media files: {e}")
|
||||||
|
return JSONResponse(
|
||||||
|
content={
|
||||||
|
"success": False,
|
||||||
|
"message": f"Error syncing media files: {str(e)}",
|
||||||
|
},
|
||||||
|
status_code=500,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/labels", dependencies=[Depends(allow_any_authenticated())])
|
@router.get("/labels", dependencies=[Depends(allow_any_authenticated())])
|
||||||
def get_labels(camera: str = ""):
|
def get_labels(camera: str = ""):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
class AppConfigSetBody(BaseModel):
|
class AppConfigSetBody(BaseModel):
|
||||||
@ -27,3 +27,16 @@ class AppPostLoginBody(BaseModel):
|
|||||||
|
|
||||||
class AppPutRoleBody(BaseModel):
|
class AppPutRoleBody(BaseModel):
|
||||||
role: str
|
role: str
|
||||||
|
|
||||||
|
|
||||||
|
class MediaSyncBody(BaseModel):
|
||||||
|
dry_run: bool = Field(
|
||||||
|
default=True, description="If True, only report orphans without deleting them"
|
||||||
|
)
|
||||||
|
media_types: List[str] = Field(
|
||||||
|
default=["all"],
|
||||||
|
description="Types of media to sync: 'all', 'event_snapshots', 'event_thumbnails', 'review_thumbnails', 'previews', 'exports', 'recordings'",
|
||||||
|
)
|
||||||
|
force: bool = Field(
|
||||||
|
default=False, description="If True, bypass safety threshold checks"
|
||||||
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user