mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-10 21:25:24 +03:00
Simplify dynamic video player
This commit is contained in:
parent
e8a6a99b46
commit
2e4ec3c02d
@ -201,15 +201,8 @@ function PreviewVideoPlayer({
|
|||||||
// canvas to cover preview transition
|
// canvas to cover preview transition
|
||||||
|
|
||||||
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||||
const [videoWidth, videoHeight] = useMemo(() => {
|
const [videoSize, setVideoSize] = useState<number[]>([0, 0]);
|
||||||
if (!previewRef.current) {
|
|
||||||
return [0, 0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [previewRef.current.videoWidth, previewRef.current.videoHeight];
|
|
||||||
// we know the video size will be known on load
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [loaded]);
|
|
||||||
// handle switching sources
|
// handle switching sources
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -218,9 +211,12 @@ function PreviewVideoPlayer({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (canvasRef.current) {
|
if (canvasRef.current) {
|
||||||
canvasRef.current
|
const context = canvasRef.current.getContext("2d");
|
||||||
.getContext("2d")
|
|
||||||
?.drawImage(previewRef.current, 0, 0, videoWidth, videoHeight);
|
if (context) {
|
||||||
|
context.drawImage(previewRef.current, 0, 0, videoSize[0], videoSize[1]);
|
||||||
|
}
|
||||||
|
|
||||||
setHasCanvas(true);
|
setHasCanvas(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +231,7 @@ function PreviewVideoPlayer({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`relative w-full rounded-2xl bg-black overflow-hidden ${className ?? ""} ${onClick ? "cursor-pointer" : ""}`}
|
className={`relative rounded-2xl bg-black overflow-hidden ${onClick ? "cursor-pointer" : ""} ${className ?? ""}`}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
{currentHourFrame && (
|
{currentHourFrame && (
|
||||||
@ -246,9 +242,9 @@ function PreviewVideoPlayer({
|
|||||||
)}
|
)}
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
width={videoWidth}
|
width={videoSize[0]}
|
||||||
height={videoHeight}
|
height={videoSize[1]}
|
||||||
className={`absolute h-full left-1/2 -translate-x-1/2 ${!loaded && hasCanvas ? "" : "hidden"}`}
|
className={`h-full absolute left-1/2 -translate-x-1/2 ${!loaded && hasCanvas ? "" : "hidden"}`}
|
||||||
/>
|
/>
|
||||||
<video
|
<video
|
||||||
ref={previewRef}
|
ref={previewRef}
|
||||||
@ -269,8 +265,15 @@ function PreviewVideoPlayer({
|
|||||||
previewRef.current?.pause();
|
previewRef.current?.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previewRef.current && startTime && currentPreview) {
|
if (previewRef.current) {
|
||||||
previewRef.current.currentTime = startTime - currentPreview.start;
|
setVideoSize([
|
||||||
|
previewRef.current.videoWidth,
|
||||||
|
previewRef.current.videoHeight,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (startTime && currentPreview) {
|
||||||
|
previewRef.current.currentTime = startTime - currentPreview.start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -41,26 +41,6 @@ export default function DynamicVideoPlayer({
|
|||||||
const apiHost = useApiHost();
|
const apiHost = useApiHost();
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
|
||||||
// playback behavior
|
|
||||||
|
|
||||||
const grow = useMemo(() => {
|
|
||||||
if (!config) {
|
|
||||||
return "aspect-video";
|
|
||||||
}
|
|
||||||
|
|
||||||
const aspectRatio =
|
|
||||||
config.cameras[camera].detect.width /
|
|
||||||
config.cameras[camera].detect.height;
|
|
||||||
|
|
||||||
if (aspectRatio > 2) {
|
|
||||||
return "";
|
|
||||||
} else if (aspectRatio < 16 / 9) {
|
|
||||||
return isDesktop ? "" : "aspect-tall";
|
|
||||||
} else {
|
|
||||||
return "aspect-video";
|
|
||||||
}
|
|
||||||
}, [camera, config]);
|
|
||||||
|
|
||||||
// controlling playback
|
// controlling playback
|
||||||
|
|
||||||
const playerRef = useRef<HTMLVideoElement | null>(null);
|
const playerRef = useRef<HTMLVideoElement | null>(null);
|
||||||
@ -169,9 +149,9 @@ export default function DynamicVideoPlayer({
|
|||||||
}, [controller, recordings]);
|
}, [controller, recordings]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`w-full relative ${className ?? ""}`}>
|
<>
|
||||||
<HlsVideoPlayer
|
<HlsVideoPlayer
|
||||||
className={isDesktop ? `w-full ${grow}` : "max-h-[50dvh]"}
|
className={isDesktop ? `w-full ${className}` : "max-h-[50dvh]"}
|
||||||
videoRef={playerRef}
|
videoRef={playerRef}
|
||||||
visible={!(isScrubbing || isLoading)}
|
visible={!(isScrubbing || isLoading)}
|
||||||
currentSource={source}
|
currentSource={source}
|
||||||
@ -195,7 +175,7 @@ export default function DynamicVideoPlayer({
|
|||||||
)}
|
)}
|
||||||
</HlsVideoPlayer>
|
</HlsVideoPlayer>
|
||||||
<PreviewPlayer
|
<PreviewPlayer
|
||||||
className={`${isScrubbing || isLoading ? "visible" : "hidden"} ${isDesktop ? `w-full ${grow}` : "max-h-[50dvh]"}`}
|
className={`${isScrubbing || isLoading ? "visible" : "hidden"} ${isDesktop ? `w-full ${className}` : "max-h-[50dvh]"}`}
|
||||||
camera={camera}
|
camera={camera}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
cameraPreviews={cameraPreviews}
|
cameraPreviews={cameraPreviews}
|
||||||
@ -205,6 +185,6 @@ export default function DynamicVideoPlayer({
|
|||||||
setPreviewController(previewController);
|
setPreviewController(previewController);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -194,23 +194,36 @@ export function RecordingView({
|
|||||||
|
|
||||||
// motion timeline data
|
// motion timeline data
|
||||||
|
|
||||||
|
const getCameraAspect = useCallback(
|
||||||
|
(cam: string) => {
|
||||||
|
if (!config) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const camera = config.cameras[cam];
|
||||||
|
|
||||||
|
if (!camera) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return camera.detect.width / camera.detect.height;
|
||||||
|
},
|
||||||
|
[config],
|
||||||
|
);
|
||||||
|
|
||||||
const mainCameraAspect = useMemo(() => {
|
const mainCameraAspect = useMemo(() => {
|
||||||
if (!config) {
|
const aspectRatio = getCameraAspect(mainCamera);
|
||||||
|
|
||||||
|
if (!aspectRatio) {
|
||||||
return "normal";
|
return "normal";
|
||||||
}
|
} else if (aspectRatio > 2) {
|
||||||
|
|
||||||
const aspectRatio =
|
|
||||||
config.cameras[mainCamera].detect.width /
|
|
||||||
config.cameras[mainCamera].detect.height;
|
|
||||||
|
|
||||||
if (aspectRatio > 2) {
|
|
||||||
return "wide";
|
return "wide";
|
||||||
} else if (aspectRatio < 16 / 9) {
|
} else if (aspectRatio < 16 / 9) {
|
||||||
return "tall";
|
return "tall";
|
||||||
} else {
|
} else {
|
||||||
return "normal";
|
return "normal";
|
||||||
}
|
}
|
||||||
}, [config, mainCamera]);
|
}, [getCameraAspect, mainCamera]);
|
||||||
|
|
||||||
const grow = useMemo(() => {
|
const grow = useMemo(() => {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
@ -335,8 +348,8 @@ export function RecordingView({
|
|||||||
key={mainCamera}
|
key={mainCamera}
|
||||||
className={
|
className={
|
||||||
isDesktop
|
isDesktop
|
||||||
? `flex justify-center mb-5 ${mainCameraAspect == "tall" ? "h-full" : "w-[78%]"}`
|
? `flex justify-center mb-5 ${mainCameraAspect == "tall" ? "h-[90%]" : mainCameraAspect == "wide" ? "w-full" : "w-[78%]"}`
|
||||||
: `w-full ${mainCameraAspect == "wide" ? "" : "aspect-video"}`
|
: `w-full ${mainCameraAspect == "wide" ? "aspect-wide" : "aspect-video"}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<DynamicVideoPlayer
|
<DynamicVideoPlayer
|
||||||
@ -367,13 +380,18 @@ export function RecordingView({
|
|||||||
{allCameras.map((cam) => {
|
{allCameras.map((cam) => {
|
||||||
if (cam !== mainCamera) {
|
if (cam !== mainCamera) {
|
||||||
return (
|
return (
|
||||||
<div key={cam}>
|
<div
|
||||||
|
key={cam}
|
||||||
|
className={`${mainCameraAspect == "wide" ? "h-full flex-grow" : ""}`}
|
||||||
|
style={{
|
||||||
|
aspectRatio:
|
||||||
|
mainCameraAspect == "wide"
|
||||||
|
? undefined
|
||||||
|
: getCameraAspect(cam),
|
||||||
|
}}
|
||||||
|
>
|
||||||
<PreviewPlayer
|
<PreviewPlayer
|
||||||
className={
|
className="h-full"
|
||||||
mainCameraAspect == "tall"
|
|
||||||
? "size-full"
|
|
||||||
: "size-full"
|
|
||||||
}
|
|
||||||
camera={cam}
|
camera={cam}
|
||||||
timeRange={currentTimeRange}
|
timeRange={currentTimeRange}
|
||||||
cameraPreviews={allPreviews ?? []}
|
cameraPreviews={allPreviews ?? []}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user