Improve performance of image fetching (#13933)

This commit is contained in:
Nicolas Mowen 2024-09-24 08:50:20 -06:00 committed by GitHub
parent d17253b023
commit a8e2f97260
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -2,7 +2,6 @@
import base64 import base64
import glob import glob
import io
import logging import logging
import os import os
import subprocess as sp import subprocess as sp
@ -15,7 +14,7 @@ import numpy as np
import pytz import pytz
from fastapi import APIRouter, Path, Query, Request, Response from fastapi import APIRouter, Path, Query, Request, Response
from fastapi.params import Depends from fastapi.params import Depends
from fastapi.responses import FileResponse, JSONResponse, StreamingResponse from fastapi.responses import FileResponse, JSONResponse
from pathvalidate import sanitize_filename from pathvalidate import sanitize_filename
from peewee import DoesNotExist, fn from peewee import DoesNotExist, fn
from tzlocal import get_localzone_name from tzlocal import get_localzone_name
@ -61,7 +60,7 @@ def mjpeg_feed(
} }
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
return StreamingResponse( return Response(
imagestream( imagestream(
request.app.detected_frames_processor, request.app.detected_frames_processor,
camera_name, camera_name,
@ -173,8 +172,8 @@ def latest_frame(
ret, img = cv2.imencode( ret, img = cv2.imencode(
f".{extension}", frame, [int(cv2.IMWRITE_WEBP_QUALITY), quality] f".{extension}", frame, [int(cv2.IMWRITE_WEBP_QUALITY), quality]
) )
return StreamingResponse( return Response(
io.BytesIO(img.tobytes()), content=img.tobytes(),
media_type=f"image/{extension}", media_type=f"image/{extension}",
headers={"Content-Type": f"image/{extension}", "Cache-Control": "no-store"}, headers={"Content-Type": f"image/{extension}", "Cache-Control": "no-store"},
) )
@ -192,8 +191,8 @@ def latest_frame(
ret, img = cv2.imencode( ret, img = cv2.imencode(
f".{extension}", frame, [int(cv2.IMWRITE_WEBP_QUALITY), quality] f".{extension}", frame, [int(cv2.IMWRITE_WEBP_QUALITY), quality]
) )
return StreamingResponse( return Response(
io.BytesIO(img.tobytes()), content=img.tobytes(),
media_type=f"image/{extension}", media_type=f"image/{extension}",
headers={"Content-Type": f"image/{extension}", "Cache-Control": "no-store"}, headers={"Content-Type": f"image/{extension}", "Cache-Control": "no-store"},
) )
@ -751,8 +750,8 @@ def event_snapshot(
if params.download: if params.download:
headers["Content-Disposition"] = f"attachment; filename=snapshot-{event_id}.jpg" headers["Content-Disposition"] = f"attachment; filename=snapshot-{event_id}.jpg"
return StreamingResponse( return Response(
io.BytesIO(jpg_bytes), jpg_bytes,
media_type="image/jpeg", media_type="image/jpeg",
headers=headers, headers=headers,
) )
@ -785,8 +784,8 @@ def label_snapshot(request: Request, camera_name: str, label: str):
frame = np.zeros((720, 1280, 3), np.uint8) frame = np.zeros((720, 1280, 3), np.uint8)
ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70]) ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
return StreamingResponse( return Response(
io.BytesIO(jpg.tobytes()), jpg.tobytes,
media_type="image/jpeg", media_type="image/jpeg",
) )
@ -844,8 +843,8 @@ def event_thumbnail(
ret, jpg = cv2.imencode(".jpg", thumbnail, [int(cv2.IMWRITE_JPEG_QUALITY), 70]) ret, jpg = cv2.imencode(".jpg", thumbnail, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
thumbnail_bytes = jpg.tobytes() thumbnail_bytes = jpg.tobytes()
return StreamingResponse( return Response(
io.BytesIO(thumbnail_bytes), thumbnail_bytes,
media_type="image/jpeg", media_type="image/jpeg",
headers={ headers={
"Cache-Control": f"private, max-age={max_cache_age}" "Cache-Control": f"private, max-age={max_cache_age}"
@ -872,8 +871,8 @@ def label_thumbnail(request: Request, camera_name: str, label: str):
frame = np.zeros((175, 175, 3), np.uint8) frame = np.zeros((175, 175, 3), np.uint8)
ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70]) ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
return StreamingResponse( return Response(
io.BytesIO(jpg.tobytes()), jpg.tobytes,
media_type="image/jpeg", media_type="image/jpeg",
headers={"Cache-Control": "no-store"}, headers={"Cache-Control": "no-store"},
) )
@ -1007,8 +1006,8 @@ def grid_snapshot(
ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70]) ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
return StreamingResponse( return Response(
io.BytesIO(jpg.tobytes()), jpg.tobytes,
media_type="image/jpeg", media_type="image/jpeg",
headers={"Cache-Control": "no-store"}, headers={"Cache-Control": "no-store"},
) )
@ -1096,8 +1095,8 @@ def event_snapshot_clean(request: Request, event_id: str, download: bool = False
f"attachment; filename=snapshot-{event_id}-clean.png" f"attachment; filename=snapshot-{event_id}-clean.png"
) )
return StreamingResponse( return Response(
io.BytesIO(png_bytes), png_bytes,
media_type="image/png", media_type="image/png",
headers=headers, headers=headers,
) )
@ -1308,8 +1307,8 @@ def preview_gif(
gif_bytes = process.stdout gif_bytes = process.stdout
return StreamingResponse( return Response(
io.BytesIO(gif_bytes), gif_bytes,
media_type="image/gif", media_type="image/gif",
headers={ headers={
"Cache-Control": f"private, max-age={max_cache_age}", "Cache-Control": f"private, max-age={max_cache_age}",
@ -1545,8 +1544,8 @@ def preview_thumbnail(file_name: str):
status_code=404, status_code=404,
) )
return StreamingResponse( return Response(
io.BytesIO(jpg_bytes), jpg_bytes,
# FIXME: Shouldn't it be either jpg or webp depending on the endpoint? # FIXME: Shouldn't it be either jpg or webp depending on the endpoint?
media_type="image/webp", media_type="image/webp",
headers={ headers={