Skip to content

Commit

Permalink
Enable temporary caching of camera images to improve responsiveness o…
Browse files Browse the repository at this point in the history
…f UI (#15614)
  • Loading branch information
NickM-27 committed Jan 19, 2025
1 parent 7972f50 commit a75a191
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 7 deletions.
1 change: 1 addition & 0 deletions frigate/api/defs/query/media_query_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class MediaLatestFrameQueryParams(BaseModel):
regions: Optional[int] = None
quality: Optional[int] = 70
height: Optional[int] = None
store: Optional[int] = None


class MediaEventsSnapshotQueryParams(BaseModel):
Expand Down
18 changes: 14 additions & 4 deletions frigate/api/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,16 @@ def latest_frame(

frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_AREA)

ret, img = cv2.imencode(f".{extension}", frame, quality_params)
_, img = cv2.imencode(f".{extension}", frame, quality_params)
return Response(
content=img.tobytes(),
media_type=f"image/{mime_type}",
headers={"Content-Type": f"image/{mime_type}", "Cache-Control": "no-store"},
headers={
"Content-Type": f"image/{mime_type}",
"Cache-Control": "no-store"
if not params.store
else "private, max-age=60",
},
)
elif camera_name == "birdseye" and request.app.frigate_config.birdseye.restream:
frame = cv2.cvtColor(
Expand All @@ -199,11 +204,16 @@ def latest_frame(

frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_AREA)

ret, img = cv2.imencode(f".{extension}", frame, quality_params)
_, img = cv2.imencode(f".{extension}", frame, quality_params)
return Response(
content=img.tobytes(),
media_type=f"image/{mime_type}",
headers={"Content-Type": f"image/{mime_type}", "Cache-Control": "no-store"},
headers={
"Content-Type": f"image/{mime_type}",
"Cache-Control": "no-store"
if not params.store
else "private, max-age=60",
},
)
else:
return JSONResponse(
Expand Down
24 changes: 22 additions & 2 deletions web/src/components/camera/AutoUpdatingCameraImage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import CameraImage from "./CameraImage";

type AutoUpdatingCameraImageProps = {
Expand All @@ -8,6 +8,7 @@ type AutoUpdatingCameraImageProps = {
className?: string;
cameraClasses?: string;
reloadInterval?: number;
periodicCache?: boolean;
};

const MIN_LOAD_TIMEOUT_MS = 200;
Expand All @@ -19,6 +20,7 @@ export default function AutoUpdatingCameraImage({
className,
cameraClasses,
reloadInterval = MIN_LOAD_TIMEOUT_MS,
periodicCache = false,
}: AutoUpdatingCameraImageProps) {
const [key, setKey] = useState(Date.now());
const [fps, setFps] = useState<string>("0");
Expand All @@ -42,6 +44,8 @@ export default function AutoUpdatingCameraImage({
}, [reloadInterval]);

const handleLoad = useCallback(() => {
setIsCached(true);

if (reloadInterval == -1) {
return;
}
Expand All @@ -66,12 +70,28 @@ export default function AutoUpdatingCameraImage({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [key, setFps]);

// periodic cache to reduce loading indicator

const [isCached, setIsCached] = useState(false);

const cacheKey = useMemo(() => {
let baseParam = "";

if (periodicCache && !isCached) {
baseParam = "store=1";
} else {
baseParam = `cache=${key}`;
}

return `${baseParam}${searchParams ? `&${searchParams}` : ""}`;
}, [isCached, periodicCache, key, searchParams]);

return (
<div className={className}>
<CameraImage
camera={camera}
onload={handleLoad}
searchParams={`cache=${key}${searchParams ? `&${searchParams}` : ""}`}
searchParams={cacheKey}
className={cameraClasses}
/>
{showFps ? <span className="text-xs">Displaying at {fps}fps</span> : null}
Expand Down
3 changes: 2 additions & 1 deletion web/src/components/player/LivePlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,11 @@ export default function LivePlayer({
>
<AutoUpdatingCameraImage
className="size-full"
cameraClasses="relative size-full flex justify-center"
camera={cameraConfig.name}
showFps={false}
reloadInterval={stillReloadInterval}
cameraClasses="relative size-full flex justify-center"
periodicCache
/>
</div>

Expand Down

0 comments on commit a75a191

Please sign in to comment.