mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Add ability to zoom in to live and recordings views (#10475)
* Make live view zoomable * Add zooming to full recordings
This commit is contained in:
parent
c66f552280
commit
f5a26c5962
14
web/package-lock.json
generated
14
web/package-lock.json
generated
@ -52,6 +52,7 @@
|
||||
"react-tracked": "^1.7.11",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"react-use-websocket": "^4.7.0",
|
||||
"react-zoom-pan-pinch": "^3.4.3",
|
||||
"recoil": "^0.7.7",
|
||||
"scroll-into-view-if-needed": "^3.1.0",
|
||||
"sonner": "^1.4.0",
|
||||
@ -6694,6 +6695,19 @@
|
||||
"react-dom": ">= 18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-zoom-pan-pinch": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.4.3.tgz",
|
||||
"integrity": "sha512-x5MFlfAx2D6NTpZu8OISqc2nYn4p+YEaM1p21w7S/VE1wbVzK8vRzTo9Bj1ydufa649MuP7JBRM3vvj1RftFZw==",
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
|
@ -57,6 +57,7 @@
|
||||
"react-tracked": "^1.7.11",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"react-use-websocket": "^4.7.0",
|
||||
"react-zoom-pan-pinch": "^3.4.3",
|
||||
"recoil": "^0.7.7",
|
||||
"scroll-into-view-if-needed": "^3.1.0",
|
||||
"sonner": "^1.4.0",
|
||||
|
@ -27,6 +27,7 @@ import {
|
||||
} from "react-icons/md";
|
||||
import useKeyboardListener from "@/hooks/use-keyboard-listener";
|
||||
import { Slider } from "../ui/slider-volume";
|
||||
import { TransformComponent, TransformWrapper } from "react-zoom-pan-pinch";
|
||||
|
||||
const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const;
|
||||
const unsupportedErrorCodes = [
|
||||
@ -169,48 +170,54 @@ export default function HlsVideoPlayer({
|
||||
}
|
||||
onClick={isDesktop ? undefined : () => setControls(!controls)}
|
||||
>
|
||||
<video
|
||||
ref={videoRef}
|
||||
className="size-full rounded-2xl"
|
||||
preload="auto"
|
||||
autoPlay
|
||||
controls={false}
|
||||
playsInline
|
||||
muted
|
||||
onPlay={() => {
|
||||
setIsPlaying(true);
|
||||
<TransformWrapper minScale={1.0}>
|
||||
<TransformComponent>
|
||||
<video
|
||||
ref={videoRef}
|
||||
className="size-full rounded-2xl"
|
||||
preload="auto"
|
||||
autoPlay
|
||||
controls={false}
|
||||
playsInline
|
||||
muted
|
||||
onPlay={() => {
|
||||
setIsPlaying(true);
|
||||
|
||||
if (isMobile) {
|
||||
setControls(true);
|
||||
setMobileCtrlTimeout(setTimeout(() => setControls(false), 4000));
|
||||
}
|
||||
}}
|
||||
onPlaying={onPlaying}
|
||||
onPause={() => {
|
||||
setIsPlaying(false);
|
||||
if (isMobile) {
|
||||
setControls(true);
|
||||
setMobileCtrlTimeout(
|
||||
setTimeout(() => setControls(false), 4000),
|
||||
);
|
||||
}
|
||||
}}
|
||||
onPlaying={onPlaying}
|
||||
onPause={() => {
|
||||
setIsPlaying(false);
|
||||
|
||||
if (isMobile && mobileCtrlTimeout) {
|
||||
clearTimeout(mobileCtrlTimeout);
|
||||
}
|
||||
}}
|
||||
onTimeUpdate={() =>
|
||||
onTimeUpdate && videoRef.current
|
||||
? onTimeUpdate(videoRef.current.currentTime)
|
||||
: undefined
|
||||
}
|
||||
onLoadedData={onPlayerLoaded}
|
||||
onEnded={onClipEnded}
|
||||
onError={(e) => {
|
||||
if (
|
||||
!hlsRef.current &&
|
||||
// @ts-expect-error code does exist
|
||||
unsupportedErrorCodes.includes(e.target.error.code) &&
|
||||
videoRef.current
|
||||
) {
|
||||
setUseHlsCompat(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
if (isMobile && mobileCtrlTimeout) {
|
||||
clearTimeout(mobileCtrlTimeout);
|
||||
}
|
||||
}}
|
||||
onTimeUpdate={() =>
|
||||
onTimeUpdate && videoRef.current
|
||||
? onTimeUpdate(videoRef.current.currentTime)
|
||||
: undefined
|
||||
}
|
||||
onLoadedData={onPlayerLoaded}
|
||||
onEnded={onClipEnded}
|
||||
onError={(e) => {
|
||||
if (
|
||||
!hlsRef.current &&
|
||||
// @ts-expect-error code does exist
|
||||
unsupportedErrorCodes.includes(e.target.error.code) &&
|
||||
videoRef.current
|
||||
) {
|
||||
setUseHlsCompat(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</TransformComponent>
|
||||
</TransformWrapper>
|
||||
<VideoControls
|
||||
video={videoRef.current}
|
||||
isPlaying={isPlaying}
|
||||
|
@ -55,6 +55,7 @@ import {
|
||||
MdZoomOut,
|
||||
} from "react-icons/md";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
||||
import useSWR from "swr";
|
||||
|
||||
type LiveCameraViewProps = {
|
||||
@ -263,16 +264,20 @@ export default function LiveCameraView({ camera }: LiveCameraViewProps) {
|
||||
aspectRatio: aspectRatio,
|
||||
}}
|
||||
>
|
||||
<LivePlayer
|
||||
key={camera.name}
|
||||
className={`${fullscreen ? "*:rounded-none" : ""}`}
|
||||
windowVisible
|
||||
showStillWithoutActivity={false}
|
||||
cameraConfig={camera}
|
||||
playAudio={audio}
|
||||
micEnabled={mic}
|
||||
preferredLiveMode={preferredLiveMode}
|
||||
/>
|
||||
<TransformWrapper minScale={1.0}>
|
||||
<TransformComponent>
|
||||
<LivePlayer
|
||||
key={camera.name}
|
||||
className={`m-1 ${fullscreen ? "*:rounded-none" : ""}`}
|
||||
windowVisible
|
||||
showStillWithoutActivity={false}
|
||||
cameraConfig={camera}
|
||||
playAudio={audio}
|
||||
micEnabled={mic}
|
||||
preferredLiveMode={preferredLiveMode}
|
||||
/>
|
||||
</TransformComponent>
|
||||
</TransformWrapper>
|
||||
</div>
|
||||
{camera.onvif.host != "" && <PtzControlPanel camera={camera.name} />}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user