mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Mute video by default and allow control of volume (#10435)
* Mute video by default and allow control of volume * Adjust volume behavior * Adjust volume behavior * Simplify more
This commit is contained in:
parent
c88a263a23
commit
8937e3fd59
@ -17,8 +17,16 @@ import {
|
|||||||
DropdownMenuRadioItem,
|
DropdownMenuRadioItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "../ui/dropdown-menu";
|
} from "../ui/dropdown-menu";
|
||||||
import { MdForward10, MdReplay10 } from "react-icons/md";
|
import {
|
||||||
|
MdForward10,
|
||||||
|
MdReplay10,
|
||||||
|
MdVolumeDown,
|
||||||
|
MdVolumeMute,
|
||||||
|
MdVolumeOff,
|
||||||
|
MdVolumeUp,
|
||||||
|
} from "react-icons/md";
|
||||||
import useKeyboardListener from "@/hooks/use-keyboard-listener";
|
import useKeyboardListener from "@/hooks/use-keyboard-listener";
|
||||||
|
import { Slider } from "../ui/slider-volume";
|
||||||
|
|
||||||
const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const;
|
const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const;
|
||||||
const unsupportedErrorCodes = [
|
const unsupportedErrorCodes = [
|
||||||
@ -166,6 +174,7 @@ export default function HlsVideoPlayer({
|
|||||||
autoPlay
|
autoPlay
|
||||||
controls={false}
|
controls={false}
|
||||||
playsInline
|
playsInline
|
||||||
|
muted
|
||||||
onPlay={() => {
|
onPlay={() => {
|
||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
|
|
||||||
@ -280,6 +289,22 @@ function VideoControls({
|
|||||||
[isPlaying, video],
|
[isPlaying, video],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// volume control
|
||||||
|
|
||||||
|
const VolumeIcon = useMemo(() => {
|
||||||
|
if (!video || video?.muted) {
|
||||||
|
return MdVolumeOff;
|
||||||
|
} else if (video.volume <= 0.33) {
|
||||||
|
return MdVolumeMute;
|
||||||
|
} else if (video.volume <= 0.67) {
|
||||||
|
return MdVolumeDown;
|
||||||
|
} else {
|
||||||
|
return MdVolumeUp;
|
||||||
|
}
|
||||||
|
// only update when specific fields change
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [video?.volume, video?.muted]);
|
||||||
|
|
||||||
if (!video || !show) {
|
if (!video || !show) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -288,6 +313,25 @@ function VideoControls({
|
|||||||
<div
|
<div
|
||||||
className={`absolute bottom-5 left-1/2 -translate-x-1/2 px-4 py-2 flex justify-between items-center gap-8 text-white z-50 bg-black bg-opacity-60 rounded-lg`}
|
className={`absolute bottom-5 left-1/2 -translate-x-1/2 px-4 py-2 flex justify-between items-center gap-8 text-white z-50 bg-black bg-opacity-60 rounded-lg`}
|
||||||
>
|
>
|
||||||
|
<div className="flex justify-normal items-center gap-2">
|
||||||
|
<VolumeIcon
|
||||||
|
className="size-5"
|
||||||
|
onClick={(e: React.MouseEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
video.muted = !video.muted;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{video.muted == false && (
|
||||||
|
<Slider
|
||||||
|
className="w-20"
|
||||||
|
value={[video.volume]}
|
||||||
|
min={0}
|
||||||
|
max={1}
|
||||||
|
step={0.02}
|
||||||
|
onValueChange={(value) => (video.volume = value[0])}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<MdReplay10 className="size-5 cursor-pointer" onClick={onReplay} />
|
<MdReplay10 className="size-5 cursor-pointer" onClick={onReplay} />
|
||||||
<div className="cursor-pointer" onClick={onTogglePlay}>
|
<div className="cursor-pointer" onClick={onTogglePlay}>
|
||||||
{isPlaying ? (
|
{isPlaying ? (
|
||||||
|
26
web/src/components/ui/slider-volume.tsx
Normal file
26
web/src/components/ui/slider-volume.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import * as SliderPrimitive from "@radix-ui/react-slider";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const Slider = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SliderPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SliderPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"relative flex w-full touch-none select-none items-center",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<SliderPrimitive.Track className="relative h-1 w-full grow overflow-hidden rounded-full bg-muted">
|
||||||
|
<SliderPrimitive.Range className="absolute h-full bg-white" />
|
||||||
|
</SliderPrimitive.Track>
|
||||||
|
<SliderPrimitive.Thumb className="block h-3 w-3 rounded-full bg-white ring-white focus:ring-white disabled:pointer-events-none disabled:opacity-50" />
|
||||||
|
</SliderPrimitive.Root>
|
||||||
|
));
|
||||||
|
Slider.displayName = SliderPrimitive.Root.displayName;
|
||||||
|
|
||||||
|
export { Slider };
|
Loading…
Reference in New Issue
Block a user