custom hook and generic video player component

This commit is contained in:
Josh Hawkins 2024-10-13 11:43:34 -05:00
parent 3a403392e7
commit 238e489f55
2 changed files with 97 additions and 0 deletions

View File

@ -0,0 +1,52 @@
import React, { useState, useRef } from "react";
import { useVideoDimensions } from "@/hooks/use-video-dimensions";
import HlsVideoPlayer from "./HlsVideoPlayer";
import ActivityIndicator from "../indicators/activity-indicator";
type GenericVideoPlayerProps = {
source: string;
onPlaying?: () => void;
children?: React.ReactNode;
};
export function GenericVideoPlayer({
source,
onPlaying,
children,
}: GenericVideoPlayerProps) {
const [isLoading, setIsLoading] = useState(true);
const videoRef = useRef<HTMLVideoElement | null>(null);
const containerRef = useRef<HTMLDivElement | null>(null);
const { videoDimensions, setVideoResolution } =
useVideoDimensions(containerRef);
return (
<div ref={containerRef} className="relative flex h-full w-full flex-col">
<div className="relative flex flex-grow items-center justify-center">
{isLoading && (
<ActivityIndicator className="absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2" />
)}
<div
className="relative flex items-center justify-center"
style={videoDimensions}
>
<HlsVideoPlayer
videoRef={videoRef}
currentSource={source}
hotKeys
visible
frigateControls={false}
fullscreen={false}
supportsFullscreen={false}
onPlaying={() => {
setIsLoading(false);
onPlaying?.();
}}
setFullResolution={setVideoResolution}
/>
{!isLoading && children}
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,45 @@
import { useState, useMemo } from "react";
import { useResizeObserver } from "./resize-observer";
export type VideoResolutionType = {
width: number;
height: number;
};
export function useVideoDimensions(
containerRef: React.RefObject<HTMLDivElement>,
) {
const [{ width: containerWidth, height: containerHeight }] =
useResizeObserver(containerRef);
const [videoResolution, setVideoResolution] = useState<VideoResolutionType>({
width: 0,
height: 0,
});
const videoAspectRatio = useMemo(() => {
return videoResolution.width / videoResolution.height || 16 / 9;
}, [videoResolution]);
const containerAspectRatio = useMemo(() => {
return containerWidth / containerHeight || 16 / 9;
}, [containerWidth, containerHeight]);
const videoDimensions = useMemo(() => {
if (!containerWidth || !containerHeight)
return { width: "100%", height: "100%" };
if (containerAspectRatio > videoAspectRatio) {
const height = containerHeight;
const width = height * videoAspectRatio;
return { width: `${width}px`, height: `${height}px` };
} else {
const width = containerWidth;
const height = width / videoAspectRatio;
return { width: `${width}px`, height: `${height}px` };
}
}, [containerWidth, containerHeight, videoAspectRatio, containerAspectRatio]);
return {
videoDimensions,
setVideoResolution,
};
}