mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-08 20:25:26 +03:00
Use preview thumbnails
This commit is contained in:
parent
9b9808ca38
commit
7b1c7f9be9
@ -1,14 +1,7 @@
|
|||||||
import VideoPlayer from "./VideoPlayer";
|
import VideoPlayer from "./VideoPlayer";
|
||||||
import React, {
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from "react";
|
|
||||||
import { useApiHost } from "@/api";
|
import { useApiHost } from "@/api";
|
||||||
import Player from "video.js/dist/types/player";
|
import Player from "video.js/dist/types/player";
|
||||||
import { AspectRatio } from "../ui/aspect-ratio";
|
|
||||||
import { LuPlayCircle } from "react-icons/lu";
|
|
||||||
import { isCurrentHour } from "@/utils/dateUtil";
|
import { isCurrentHour } from "@/utils/dateUtil";
|
||||||
import { isSafari } from "@/utils/browserUtil";
|
import { isSafari } from "@/utils/browserUtil";
|
||||||
|
|
||||||
@ -116,10 +109,9 @@ export default function PreviewThumbnailPlayer({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AspectRatio
|
<div
|
||||||
ref={relevantPreview ? inViewRef : null}
|
ref={relevantPreview ? inViewRef : null}
|
||||||
ratio={16 / 9}
|
className="relative w-full h-full"
|
||||||
className="bg-black flex justify-center items-center"
|
|
||||||
onMouseEnter={() => onPlayback(true)}
|
onMouseEnter={() => onPlayback(true)}
|
||||||
onMouseLeave={() => onPlayback(false)}
|
onMouseLeave={() => onPlayback(false)}
|
||||||
>
|
>
|
||||||
@ -134,7 +126,9 @@ export default function PreviewThumbnailPlayer({
|
|||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
/>
|
/>
|
||||||
</AspectRatio>
|
<div className="absolute top-0 left-0 right-0 rounded-2xl z-10 w-full h-[30%] bg-gradient-to-b from-black/20 to-transparent pointer-events-none" />
|
||||||
|
<div className="absolute bottom-0 left-0 right-0 rounded-2xl z-10 w-full h-[10%] bg-gradient-to-t from-black/20 to-transparent pointer-events-none" />
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,15 +192,13 @@ function PreviewContent({
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<div className="w-full">
|
|
||||||
<VideoPlayer
|
<VideoPlayer
|
||||||
options={{
|
options={{
|
||||||
preload: "auto",
|
preload: "auto",
|
||||||
aspectRatio: "16:9",
|
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
controls: false,
|
controls: false,
|
||||||
muted: true,
|
muted: true,
|
||||||
|
fluid: true,
|
||||||
loadingSpinner: false,
|
loadingSpinner: false,
|
||||||
poster: relevantPreview
|
poster: relevantPreview
|
||||||
? ""
|
? ""
|
||||||
@ -242,11 +234,6 @@ function PreviewContent({
|
|||||||
playerRef.current = null;
|
playerRef.current = null;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
{relevantPreview && (
|
|
||||||
<LuPlayCircle className="absolute z-10 left-1 bottom-1 w-4 h-4 text-white text-opacity-60" />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import TimeAgo from "@/components/dynamic/TimeAgo";
|
import TimeAgo from "@/components/dynamic/TimeAgo";
|
||||||
|
import PreviewThumbnailPlayer from "@/components/player/PreviewThumbnailPlayer";
|
||||||
import ActivityIndicator from "@/components/ui/activity-indicator";
|
import ActivityIndicator from "@/components/ui/activity-indicator";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||||
@ -14,7 +15,10 @@ export default function Events() {
|
|||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
const [severity, setSeverity] = useState<ReviewSeverity>("alert");
|
const [severity, setSeverity] = useState<ReviewSeverity>("alert");
|
||||||
|
|
||||||
const { data: reviewSegments } = useSWR<ReviewSegment[]>("review");
|
const { data: reviewSegments } = useSWR<ReviewSegment[]>([
|
||||||
|
"review",
|
||||||
|
{ limit: 500 },
|
||||||
|
]);
|
||||||
|
|
||||||
const previewTimes = useMemo(() => {
|
const previewTimes = useMemo(() => {
|
||||||
if (!reviewSegments) {
|
if (!reviewSegments) {
|
||||||
@ -89,7 +93,7 @@ export default function Events() {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button className="mx-1" variant="secondary">
|
<Button className="mx-1" variant="secondary">
|
||||||
<LuCalendar className=" mr-[10px]" />
|
<LuCalendar className=" mr-[10px]" />
|
||||||
Fab 13
|
Fab 17
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="mx-1" variant="secondary">
|
<Button className="mx-1" variant="secondary">
|
||||||
<LuFilter className=" mr-[10px]" />
|
<LuFilter className=" mr-[10px]" />
|
||||||
@ -101,10 +105,35 @@ export default function Events() {
|
|||||||
<div className="flex flex-wrap gap-2 mt-2">
|
<div className="flex flex-wrap gap-2 mt-2">
|
||||||
{reviewSegments?.map((value) => {
|
{reviewSegments?.map((value) => {
|
||||||
if (value.severity == severity) {
|
if (value.severity == severity) {
|
||||||
|
const detectConfig = config.cameras[value.camera].detect;
|
||||||
|
const relevantPreview = Object.values(allPreviews || []).find(
|
||||||
|
(preview) =>
|
||||||
|
preview.camera == value.camera &&
|
||||||
|
preview.start < value.start_time &&
|
||||||
|
preview.end > value.end_time
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-[234px] w-[416px] bg-blue-500 rounded-lg">
|
<div
|
||||||
|
className="relative h-[234px] rounded-2xl overflow-hidden"
|
||||||
|
style={{
|
||||||
|
aspectRatio: detectConfig.width / detectConfig.height,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{relevantPreview ? (
|
||||||
|
<PreviewThumbnailPlayer
|
||||||
|
relevantPreview={relevantPreview}
|
||||||
|
camera={value.camera}
|
||||||
|
startTs={value.start_time}
|
||||||
|
isMobile={false}
|
||||||
|
eventId=""
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
{value.camera} {value.data.objects}
|
{value.camera} {value.data.objects}
|
||||||
<div className="absolute left-1 right-1 bottom-0 flex justify-between">
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="absolute left-1 right-1 bottom-1 flex justify-between">
|
||||||
<TimeAgo time={value.start_time * 1000} />
|
<TimeAgo time={value.start_time * 1000} />
|
||||||
{formatUnixTimestampToDateTime(value.start_time, {
|
{formatUnixTimestampToDateTime(value.start_time, {
|
||||||
strftime_fmt:
|
strftime_fmt:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user