From ed9bf9dce45efd1378d4e6710f0e121e8f96ef09 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 13 Mar 2024 15:47:55 -0600 Subject: [PATCH] Mute video by default and allow control of volume --- web/src/components/player/HlsVideoPlayer.tsx | 67 +++++++++++++++++++- web/src/components/ui/slider-volume.tsx | 26 ++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 web/src/components/ui/slider-volume.tsx diff --git a/web/src/components/player/HlsVideoPlayer.tsx b/web/src/components/player/HlsVideoPlayer.tsx index cbf5e2b5d..97c8d3f5b 100644 --- a/web/src/components/player/HlsVideoPlayer.tsx +++ b/web/src/components/player/HlsVideoPlayer.tsx @@ -17,8 +17,16 @@ import { DropdownMenuRadioItem, DropdownMenuTrigger, } 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 { Slider } from "../ui/slider-volume"; const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const; const unsupportedErrorCodes = [ @@ -86,6 +94,7 @@ export default function HlsVideoPlayer({ // controls const [isPlaying, setIsPlaying] = useState(true); + const [volume, setVolume] = useState(0.0); const [mobileCtrlTimeout, setMobileCtrlTimeout] = useState(); const [controls, setControls] = useState(isMobile); const [controlsOpen, setControlsOpen] = useState(false); @@ -117,7 +126,11 @@ export default function HlsVideoPlayer({ break; case "m": if (down && !repeat && videoRef.current) { - videoRef.current.muted = !videoRef.current.muted; + if (videoRef.current.muted) { + videoRef.current.volume = 1; + } else { + videoRef.current.volume = 0; + } } break; case " ": @@ -166,6 +179,8 @@ export default function HlsVideoPlayer({ autoPlay controls={false} playsInline + muted={volume == 0.0} + onVolumeChange={() => setVolume(videoRef.current?.volume ?? 0.0)} onPlay={() => { setIsPlaying(true); @@ -202,6 +217,7 @@ export default function HlsVideoPlayer({ void; @@ -221,6 +238,7 @@ type VideoControlsProps = { function VideoControls({ video, isPlaying, + volume, show, controlsOpen, setControlsOpen, @@ -280,6 +298,21 @@ function VideoControls({ [isPlaying, video], ); + // volume control + + const [showVolume, setShowVolume] = useState(false); + const VolumeIcon = useMemo(() => { + if (volume == 0) { + return MdVolumeOff; + } else if (volume <= 0.33) { + return MdVolumeMute; + } else if (volume <= 0.67) { + return MdVolumeDown; + } else { + return MdVolumeUp; + } + }, [volume]); + if (!video || !show) { return; } @@ -288,6 +321,36 @@ function VideoControls({
+
setShowVolume(true) : undefined} + onMouseOut={isDesktop ? () => setShowVolume(false) : undefined} + onClick={(e) => { + e.stopPropagation(); + + if (isDesktop) { + if (video.muted) { + video.volume = 1; + } else { + video.volume = 0; + } + } else { + setShowVolume(!showVolume); + } + }} + > + + {showVolume && ( + (video.volume = value[0])} + /> + )} +
{isPlaying ? ( diff --git a/web/src/components/ui/slider-volume.tsx b/web/src/components/ui/slider-volume.tsx new file mode 100644 index 000000000..1493488a3 --- /dev/null +++ b/web/src/components/ui/slider-volume.tsx @@ -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, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)); +Slider.displayName = SliderPrimitive.Root.displayName; + +export { Slider };