Use query parameters for the media MJPEG feed endpoint

This commit is contained in:
Rui Alves 2024-09-21 14:01:03 +01:00
parent c33327175a
commit d1146a9d27
2 changed files with 32 additions and 28 deletions

View File

@ -23,9 +23,20 @@ class MediaLatestFrameQueryParams(BaseModel):
height: Optional[int] = None height: Optional[int] = None
class MediaEventsSnapshotQueryParams(BaseModel): class MediaEventsSnapshotQueryParams(BaseModel):
download: bool = False, download: bool = False
timestamp: Optional[int] = None, timestamp: Optional[int] = None
bbox: Optional[int] = None, bbox: Optional[int] = None
crop: Optional[int] = None, crop: Optional[int] = None
height: Optional[int] = None, height: Optional[int] = None
quality: Optional[int] = 70, quality: Optional[int] = 70
class MediaMjpegFeedQueryParams(BaseModel):
fps: int = 3
height: int = 360
bbox: Optional[int] = None
timestamp: Optional[int] = None
zones: Optional[int] = None
mask: Optional[int] = None
motion: Optional[int] = None
regions: Optional[int] = None

View File

@ -8,7 +8,6 @@ import os
import subprocess as sp import subprocess as sp
import time import time
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from typing import Optional
from urllib.parse import unquote from urllib.parse import unquote
import cv2 import cv2
@ -23,6 +22,7 @@ from tzlocal import get_localzone_name
from frigate.api.defs.media_query_parameters import ( from frigate.api.defs.media_query_parameters import (
MediaEventsSnapshotQueryParams, MediaEventsSnapshotQueryParams,
MediaLatestFrameQueryParams, MediaLatestFrameQueryParams,
MediaMjpegFeedQueryParams,
) )
from frigate.api.defs.tags import Tags from frigate.api.defs.tags import Tags
from frigate.config import FrigateConfig from frigate.config import FrigateConfig
@ -52,22 +52,15 @@ def secure_filename(file_name: str):
def mjpeg_feed( def mjpeg_feed(
request: Request, request: Request,
camera_name: str, camera_name: str,
fps: int = 3, params: MediaMjpegFeedQueryParams = Depends(),
height: int = 360,
bbox: Optional[int] = None,
timestamp: Optional[int] = None,
zones: Optional[int] = None,
mask: Optional[int] = None,
motion: Optional[int] = None,
regions: Optional[int] = None,
): ):
draw_options = { draw_options = {
"bounding_boxes": bbox, "bounding_boxes": params.bbox,
"timestamp": timestamp, "timestamp": params.timestamp,
"zones": zones, "zones": params.zones,
"mask": mask, "mask": params.mask,
"motion_boxes": motion, "motion_boxes": params.motion,
"regions": regions, "regions": params.regions,
} }
if camera_name in request.app.frigate_config.cameras: if camera_name in request.app.frigate_config.cameras:
# return a multipart response # return a multipart response
@ -75,8 +68,8 @@ def mjpeg_feed(
imagestream( imagestream(
request.app.detected_frames_processor, request.app.detected_frames_processor,
camera_name, camera_name,
fps, params.fps,
height, params.height,
draw_options, draw_options,
), ),
media_type="multipart/x-mixed-replace;boundary=frame", media_type="multipart/x-mixed-replace;boundary=frame",
@ -194,7 +187,7 @@ def latest_frame(
cv2.COLOR_YUV2BGR_I420, cv2.COLOR_YUV2BGR_I420,
) )
height = int(height or str(frame.shape[0])) height = int(params.height or str(frame.shape[0]))
width = int(height * frame.shape[1] / frame.shape[0]) width = int(height * frame.shape[1] / frame.shape[0])
frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_AREA) frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_AREA)
@ -760,7 +753,7 @@ def label_thumbnail(request: Request, camera_name: str, label: str):
@router.get("/media/camera/{camera_name}/label/{label}/clip.mp4") @router.get("/media/camera/{camera_name}/label/{label}/clip.mp4")
def label_clip(camera_name: str, label: str): def label_clip(request: Request, camera_name: str, label: str):
label = unquote(label) label = unquote(label)
event_query = Event.select(fn.MAX(Event.id)).where( event_query = Event.select(fn.MAX(Event.id)).where(
Event.camera == camera_name, Event.has_clip == True Event.camera == camera_name, Event.has_clip == True
@ -771,7 +764,7 @@ def label_clip(camera_name: str, label: str):
try: try:
event = event_query.get() event = event_query.get()
return event_clip(event.id) return event_clip(request, event.id)
except DoesNotExist: except DoesNotExist:
return JSONResponse( return JSONResponse(
content={"success": False, "message": "Event not found"}, status_code=404 content={"success": False, "message": "Event not found"}, status_code=404
@ -1050,7 +1043,7 @@ def event_snapshot(
@router.get("/media/events/{event_id}/clip.mp4") @router.get("/media/events/{event_id}/clip.mp4")
def event_clip(event_id: str, download: bool = False): def event_clip(request: Request, event_id: str, download: bool = False):
try: try:
event: Event = Event.get(Event.id == event_id) event: Event = Event.get(Event.id == event_id)
except DoesNotExist: except DoesNotExist:
@ -1070,7 +1063,7 @@ def event_clip(event_id: str, download: bool = False):
end_ts = ( end_ts = (
datetime.now().timestamp() if event.end_time is None else event.end_time datetime.now().timestamp() if event.end_time is None else event.end_time
) )
return recording_clip(event.camera, event.start_time, end_ts, download) return recording_clip(request, event.camera, event.start_time, end_ts, download)
headers = { headers = {
"Content-Description": "File Transfer", "Content-Description": "File Transfer",