mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +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, | ||||
|   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 = [ | ||||
| @ -166,6 +174,7 @@ export default function HlsVideoPlayer({ | ||||
|         autoPlay | ||||
|         controls={false} | ||||
|         playsInline | ||||
|         muted | ||||
|         onPlay={() => { | ||||
|           setIsPlaying(true); | ||||
| 
 | ||||
| @ -280,6 +289,22 @@ function VideoControls({ | ||||
|     [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) { | ||||
|     return; | ||||
|   } | ||||
| @ -288,6 +313,25 @@ function VideoControls({ | ||||
|     <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`} | ||||
|     > | ||||
|       <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} /> | ||||
|       <div className="cursor-pointer" onClick={onTogglePlay}> | ||||
|         {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