Simplify dynamic video player

This commit is contained in:
Nicolas Mowen 2024-03-28 13:34:13 -06:00
parent e8a6a99b46
commit 2e4ec3c02d
3 changed files with 59 additions and 58 deletions

View File

@ -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;
}
} }
}} }}
> >

View File

@ -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> </>
); );
} }

View File

@ -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 ?? []}