mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-18 00:54:27 +03:00
add ability to continue playing stream in background
This commit is contained in:
parent
9aa81f3e08
commit
1309cb0d7f
@ -32,6 +32,7 @@ type LivePlayerProps = {
|
|||||||
useWebGL: boolean;
|
useWebGL: boolean;
|
||||||
windowVisible?: boolean;
|
windowVisible?: boolean;
|
||||||
playAudio?: boolean;
|
playAudio?: boolean;
|
||||||
|
playInBackground: boolean;
|
||||||
micEnabled?: boolean; // only webrtc supports mic
|
micEnabled?: boolean; // only webrtc supports mic
|
||||||
iOSCompatFullScreen?: boolean;
|
iOSCompatFullScreen?: boolean;
|
||||||
pip?: boolean;
|
pip?: boolean;
|
||||||
@ -53,6 +54,7 @@ export default function LivePlayer({
|
|||||||
useWebGL = false,
|
useWebGL = false,
|
||||||
windowVisible = true,
|
windowVisible = true,
|
||||||
playAudio = false,
|
playAudio = false,
|
||||||
|
playInBackground = false,
|
||||||
micEnabled = false,
|
micEnabled = false,
|
||||||
iOSCompatFullScreen = false,
|
iOSCompatFullScreen = false,
|
||||||
pip,
|
pip,
|
||||||
@ -202,6 +204,7 @@ export default function LivePlayer({
|
|||||||
camera={streamName}
|
camera={streamName}
|
||||||
playbackEnabled={cameraActive || liveReady}
|
playbackEnabled={cameraActive || liveReady}
|
||||||
audioEnabled={playAudio}
|
audioEnabled={playAudio}
|
||||||
|
playInBackground={playInBackground}
|
||||||
onPlaying={playerIsPlaying}
|
onPlaying={playerIsPlaying}
|
||||||
pip={pip}
|
pip={pip}
|
||||||
setFullResolution={setFullResolution}
|
setFullResolution={setFullResolution}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ type MSEPlayerProps = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
playbackEnabled?: boolean;
|
playbackEnabled?: boolean;
|
||||||
audioEnabled?: boolean;
|
audioEnabled?: boolean;
|
||||||
|
playInBackground?: boolean;
|
||||||
pip?: boolean;
|
pip?: boolean;
|
||||||
onPlaying?: () => void;
|
onPlaying?: () => void;
|
||||||
setFullResolution?: React.Dispatch<SetStateAction<VideoResolutionType>>;
|
setFullResolution?: React.Dispatch<SetStateAction<VideoResolutionType>>;
|
||||||
@ -26,6 +27,7 @@ function MSEPlayer({
|
|||||||
className,
|
className,
|
||||||
playbackEnabled = true,
|
playbackEnabled = true,
|
||||||
audioEnabled = false,
|
audioEnabled = false,
|
||||||
|
playInBackground = false,
|
||||||
pip = false,
|
pip = false,
|
||||||
onPlaying,
|
onPlaying,
|
||||||
setFullResolution,
|
setFullResolution,
|
||||||
@ -508,12 +510,22 @@ function MSEPlayer({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener("visibilitychange", listener);
|
if (!playInBackground) {
|
||||||
|
document.addEventListener("visibilitychange", listener);
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("visibilitychange", listener);
|
if (!playInBackground) {
|
||||||
|
document.removeEventListener("visibilitychange", listener);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [playbackEnabled, visibilityCheck, onConnect, onDisconnect]);
|
}, [
|
||||||
|
playbackEnabled,
|
||||||
|
visibilityCheck,
|
||||||
|
playInBackground,
|
||||||
|
onConnect,
|
||||||
|
onDisconnect,
|
||||||
|
]);
|
||||||
|
|
||||||
// control pip
|
// control pip
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,7 @@ import {
|
|||||||
FaMicrophone,
|
FaMicrophone,
|
||||||
FaMicrophoneSlash,
|
FaMicrophoneSlash,
|
||||||
} from "react-icons/fa";
|
} from "react-icons/fa";
|
||||||
|
import { CiStreamOff, CiStreamOn } from "react-icons/ci";
|
||||||
import { GiSpeaker, GiSpeakerOff } from "react-icons/gi";
|
import { GiSpeaker, GiSpeakerOff } from "react-icons/gi";
|
||||||
import { TbViewfinder, TbViewfinderOff } from "react-icons/tb";
|
import { TbViewfinder, TbViewfinderOff } from "react-icons/tb";
|
||||||
import { IoIosWarning, IoMdArrowRoundBack } from "react-icons/io";
|
import { IoIosWarning, IoMdArrowRoundBack } from "react-icons/io";
|
||||||
@ -220,6 +221,11 @@ export default function LiveCameraView({
|
|||||||
const [pip, setPip] = useState(false);
|
const [pip, setPip] = useState(false);
|
||||||
const [lowBandwidth, setLowBandwidth] = useState(false);
|
const [lowBandwidth, setLowBandwidth] = useState(false);
|
||||||
|
|
||||||
|
const [playInBackground, setPlayInBackground] = usePersistence<boolean>(
|
||||||
|
`${camera.name}-background-play`,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
const [fullResolution, setFullResolution] = useState<VideoResolutionType>({
|
const [fullResolution, setFullResolution] = useState<VideoResolutionType>({
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
@ -481,6 +487,8 @@ export default function LiveCameraView({
|
|||||||
streamName={streamName ?? ""}
|
streamName={streamName ?? ""}
|
||||||
setStreamName={setStreamName}
|
setStreamName={setStreamName}
|
||||||
preferredLiveMode={preferredLiveMode}
|
preferredLiveMode={preferredLiveMode}
|
||||||
|
playInBackground={playInBackground ?? false}
|
||||||
|
setPlayInBackground={setPlayInBackground}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
@ -513,6 +521,7 @@ export default function LiveCameraView({
|
|||||||
showStillWithoutActivity={false}
|
showStillWithoutActivity={false}
|
||||||
cameraConfig={camera}
|
cameraConfig={camera}
|
||||||
playAudio={audio}
|
playAudio={audio}
|
||||||
|
playInBackground={playInBackground ?? false}
|
||||||
micEnabled={mic}
|
micEnabled={mic}
|
||||||
iOSCompatFullScreen={isIOS}
|
iOSCompatFullScreen={isIOS}
|
||||||
preferredLiveMode={preferredLiveMode}
|
preferredLiveMode={preferredLiveMode}
|
||||||
@ -779,6 +788,8 @@ type FrigateCameraFeaturesProps = {
|
|||||||
streamName: string;
|
streamName: string;
|
||||||
setStreamName?: (value: string | undefined) => void;
|
setStreamName?: (value: string | undefined) => void;
|
||||||
preferredLiveMode: string;
|
preferredLiveMode: string;
|
||||||
|
playInBackground: boolean;
|
||||||
|
setPlayInBackground: (value: boolean | undefined) => void;
|
||||||
};
|
};
|
||||||
function FrigateCameraFeatures({
|
function FrigateCameraFeatures({
|
||||||
camera,
|
camera,
|
||||||
@ -789,6 +800,8 @@ function FrigateCameraFeatures({
|
|||||||
streamName,
|
streamName,
|
||||||
setStreamName,
|
setStreamName,
|
||||||
preferredLiveMode,
|
preferredLiveMode,
|
||||||
|
playInBackground,
|
||||||
|
setPlayInBackground,
|
||||||
}: FrigateCameraFeaturesProps) {
|
}: FrigateCameraFeaturesProps) {
|
||||||
const { payload: detectState, send: sendDetect } = useDetectState(
|
const { payload: detectState, send: sendDetect } = useDetectState(
|
||||||
camera.name,
|
camera.name,
|
||||||
@ -853,6 +866,14 @@ function FrigateCameraFeatures({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<CameraFeatureToggle
|
||||||
|
className="p-2 md:p-0"
|
||||||
|
variant={fullscreen ? "overlay" : "primary"}
|
||||||
|
Icon={playInBackground ? CiStreamOn : CiStreamOff}
|
||||||
|
isActive={playInBackground ?? false}
|
||||||
|
title={`${playInBackground ? "Disable" : "Enable"} Background Playback`}
|
||||||
|
onClick={() => setPlayInBackground(!playInBackground)}
|
||||||
|
/>
|
||||||
{Object.values(camera.live.streams).length > 1 && (
|
{Object.values(camera.live.streams).length > 1 && (
|
||||||
<Select
|
<Select
|
||||||
value={streamName}
|
value={streamName}
|
||||||
@ -952,6 +973,13 @@ function FrigateCameraFeatures({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<FilterSwitch
|
||||||
|
label="Play in Background"
|
||||||
|
isChecked={playInBackground}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
setPlayInBackground(checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{Object.values(camera.live.streams).length > 1 && (
|
{Object.values(camera.live.streams).length > 1 && (
|
||||||
<div className="mt-1 p-2">
|
<div className="mt-1 p-2">
|
||||||
<div className="mb-1 text-sm">Live stream selection</div>
|
<div className="mb-1 text-sm">Live stream selection</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user