diff --git a/frigate/api/app.py b/frigate/api/app.py index 0cbcba5a6..1bde7abd8 100644 --- a/frigate/api/app.py +++ b/frigate/api/app.py @@ -22,7 +22,6 @@ from werkzeug.middleware.proxy_fix import ProxyFix from frigate.api.auth import AuthBp, get_jwt_secret, limiter from frigate.api.defs.tags import Tags from frigate.api.event import EventBp -from frigate.api.export import ExportBp from frigate.config import FrigateConfig from frigate.const import CONFIG_DIR from frigate.embeddings import EmbeddingsContext @@ -45,7 +44,6 @@ logger = logging.getLogger(__name__) bp = Blueprint("frigate", __name__) bp.register_blueprint(EventBp) -bp.register_blueprint(ExportBp) bp.register_blueprint(AuthBp) router = APIRouter() diff --git a/frigate/api/defs/tags.py b/frigate/api/defs/tags.py index aeef87462..ee1ae9a64 100644 --- a/frigate/api/defs/tags.py +++ b/frigate/api/defs/tags.py @@ -8,3 +8,4 @@ class Tags(Enum): media = "Media" notifications = "Notifications" review = "Review" + export = "Export" diff --git a/frigate/api/export.py b/frigate/api/export.py index 0993a3a87..1d9d995f8 100644 --- a/frigate/api/export.py +++ b/frigate/api/export.py @@ -5,54 +5,50 @@ from pathlib import Path from typing import Optional import psutil -from flask import ( - Blueprint, - current_app, - jsonify, - make_response, - request, -) +from fastapi import APIRouter, Request +from fastapi.responses import JSONResponse from peewee import DoesNotExist +from frigate.api.defs.tags import Tags from frigate.const import EXPORT_DIR from frigate.models import Export, Recordings from frigate.record.export import PlaybackFactorEnum, RecordingExporter logger = logging.getLogger(__name__) -ExportBp = Blueprint("exports", __name__) +router = APIRouter(tags=[Tags.export]) -@ExportBp.route("/exports") +@router.get("/exports") def get_exports(): exports = Export.select().order_by(Export.date.desc()).dicts().iterator() - return jsonify([e for e in exports]) + return JSONResponse(content=[e for e in exports]) -@ExportBp.route( - "/export//start//end/", methods=["POST"] -) -@ExportBp.route( - "/export//start//end/", - methods=["POST"], -) -def export_recording(camera_name: str, start_time, end_time): - if not camera_name or not current_app.frigate_config.cameras.get(camera_name): - return make_response( - jsonify( +@router.post("/export/{camera_name}/start/{start_time}/end/{end_time}") +def export_recording( + request: Request, + camera_name: str, + start_time: float, + end_time: float, + body: dict = None, +): + if not camera_name or not request.app.frigate_config.cameras.get(camera_name): + return JSONResponse( + content=( {"success": False, "message": f"{camera_name} is not a valid camera."} ), - 404, + status_code=404, ) - json: dict[str, any] = request.get_json(silent=True) or {} + json: dict[str, any] = body or {} playback_factor = json.get("playback", "realtime") friendly_name: Optional[str] = json.get("name") if len(friendly_name or "") > 256: - return make_response( - jsonify({"success": False, "message": "File name is too long."}), - 401, + return JSONResponse( + content=({"success": False, "message": "File name is too long."}), + status_code=401, ) existing_image = json.get("image_path") @@ -69,15 +65,15 @@ def export_recording(camera_name: str, start_time, end_time): ) if recordings_count <= 0: - return make_response( - jsonify( + return JSONResponse( + content=( {"success": False, "message": "No recordings found for time range"} ), - 400, + status_code=400, ) exporter = RecordingExporter( - current_app.frigate_config, + request.app.frigate_config, camera_name, friendly_name, existing_image, @@ -90,58 +86,58 @@ def export_recording(camera_name: str, start_time, end_time): ), ) exporter.start() - return make_response( - jsonify( + return JSONResponse( + content=( { "success": True, "message": "Starting export of recording.", } ), - 200, + status_code=200, ) -@ExportBp.route("/export//", methods=["PATCH"]) -def export_rename(id, new_name: str): +@router.patch("/export/{id}/{new_name}") +def export_rename(event_id, new_name: str): try: - export: Export = Export.get(Export.id == id) + export: Export = Export.get(Export.id == event_id) except DoesNotExist: - return make_response( - jsonify( + return JSONResponse( + content=( { "success": False, "message": "Export not found.", } ), - 404, + status_code=404, ) export.name = new_name export.save() - return make_response( - jsonify( + return JSONResponse( + content=( { "success": True, "message": "Successfully renamed export.", } ), - 200, + status_code=200, ) -@ExportBp.route("/export/", methods=["DELETE"]) -def export_delete(id: str): +@router.delete("/export/{event_id}", methods=["DELETE"]) +def export_delete(event_id: str): try: - export: Export = Export.get(Export.id == id) + export: Export = Export.get(Export.id == event_id) except DoesNotExist: - return make_response( - jsonify( + return JSONResponse( + content=( { "success": False, "message": "Export not found.", } ), - 404, + status_code=404, ) files_in_use = [] @@ -158,11 +154,11 @@ def export_delete(id: str): continue if export.video_path.split("/")[-1] in files_in_use: - return make_response( - jsonify( + return JSONResponse( + content=( {"success": False, "message": "Can not delete in progress export."} ), - 400, + status_code=400, ) Path(export.video_path).unlink(missing_ok=True) @@ -171,12 +167,12 @@ def export_delete(id: str): Path(export.thumb_path).unlink(missing_ok=True) export.delete_instance() - return make_response( - jsonify( + return JSONResponse( + content=( { "success": True, "message": "Successfully deleted export.", } ), - 200, + status_code=200, ) diff --git a/frigate/api/fastapi_app.py b/frigate/api/fastapi_app.py index 7ba07c4e7..39c793dd3 100644 --- a/frigate/api/fastapi_app.py +++ b/frigate/api/fastapi_app.py @@ -3,7 +3,7 @@ import logging from fastapi import FastAPI from frigate.api import app as main_app -from frigate.api import media, notification, preview, review +from frigate.api import export, media, notification, preview, review from frigate.plus import PlusApi from frigate.ptz.onvif import OnvifController from frigate.stats.emitter import StatsEmitter @@ -31,6 +31,7 @@ def create_fastapi_app( app.include_router(preview.router) app.include_router(notification.router) app.include_router(review.router) + app.include_router(export.router) # App Properties app.frigate_config = frigate_config app.detected_frames_processor = detected_frames_processor