Create API to create gif from previews and show instead of still thumbnails (#9786)

* Start working on animation

* Change output file

* Create preview gif

* Show animated gif for event thumb

* Remove favorite

* Cleanup
This commit is contained in:
Nicolas Mowen
2024-02-11 06:23:45 -07:00
committed by GitHub
parent 9de09f6cdf
commit bcbea8da7d
4 changed files with 215 additions and 44 deletions

View File

@@ -0,0 +1,37 @@
import { baseUrl } from "@/api/baseUrl";
import { Event as FrigateEvent } from "@/types/event";
import TimeAgo from "../dynamic/TimeAgo";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
type AnimatedEventThumbnailProps = {
event: FrigateEvent;
};
export function AnimatedEventThumbnail({ event }: AnimatedEventThumbnailProps) {
return (
<Tooltip>
<TooltipTrigger asChild>
<div
className="relative rounded bg-cover aspect-video h-24 bg-no-repeat bg-center mr-4"
style={{
backgroundImage: `url(${baseUrl}api/events/${event.id}/preview.gif)`,
}}
>
<div className="absolute bottom-0 w-full h-6 bg-gradient-to-t from-slate-900/50 to-transparent rounded">
<div className="absolute left-1 bottom-0 text-xs text-white w-full">
<TimeAgo time={event.start_time * 1000} dense />
</div>
</div>
</div>
</TooltipTrigger>
<TooltipContent>
{`${event.label} ${
event.sub_label ? `(${event.sub_label})` : ""
} detected with score of ${(event.data.score * 100).toFixed(0)}% ${
event.data.sub_label_score
? `(${event.data.sub_label_score * 100}%)`
: ""
}`}
</TooltipContent>
</Tooltip>
);
}

View File

@@ -40,22 +40,23 @@ export default function LivePlayer({
const { activeMotion, activeAudio, activeTracking } =
useCameraActivity(cameraConfig);
const cameraActive = useMemo(() => activeMotion || activeTracking, [activeMotion, activeTracking])
const liveMode = useCameraLiveMode(cameraConfig, preferredLiveMode);
const [liveReady, setLiveReady] = useState(false);
useEffect(() => {
if (!liveReady) {
if (activeMotion && liveMode == "jsmpeg") {
if (cameraActive && liveMode == "jsmpeg") {
setLiveReady(true);
}
return;
}
if (!activeMotion && !activeTracking) {
if (!cameraActive) {
setLiveReady(false);
}
}, [activeMotion, activeTracking, liveReady]);
}, [cameraActive, liveReady]);
const { payload: recording } = useRecordingsState(cameraConfig.name);
@@ -167,7 +168,7 @@ export default function LivePlayer({
: "outline-0"
} transition-all duration-500 ${className}`}
>
{(showStillWithoutActivity == false || activeMotion || activeTracking) &&
{(showStillWithoutActivity == false || cameraActive) &&
player}
<div
@@ -179,7 +180,7 @@ export default function LivePlayer({
className="w-full h-full"
camera={cameraConfig.name}
showFps={false}
reloadInterval={30000}
reloadInterval={(cameraActive && !liveReady) ? 200 : 30000}
/>
</div>