summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorDevloperAmanSingh <amansinghneh211205@gmail.com>2025-06-25 13:27:48 +0530
committerDevloperAmanSingh <amansinghneh211205@gmail.com>2025-06-25 13:27:48 +0530
commitfe1a2542cc5e3b2a36ec44e51777bb45b1d6330f (patch)
treec6646bb215a231df098e093b5da53d371a994bf4 /apps
parent66eb6f13d52edfd7497d40315f16e490268632f4 (diff)
downloadopencut-fe1a2542cc5e3b2a36ec44e51777bb45b1d6330f.tar.gz
feat(video-player): enhance video player with mute functionality and improved event handling
Diffstat (limited to 'apps')
-rw-r--r--apps/web/src/components/ui/video-player.tsx196
1 files changed, 108 insertions, 88 deletions
diff --git a/apps/web/src/components/ui/video-player.tsx b/apps/web/src/components/ui/video-player.tsx
index 32a12916..d8a72e40 100644
--- a/apps/web/src/components/ui/video-player.tsx
+++ b/apps/web/src/components/ui/video-player.tsx
@@ -4,108 +4,128 @@ import { useRef, useEffect } from "react";
import { usePlaybackStore } from "@/stores/playback-store";
interface VideoPlayerProps {
- src: string;
- poster?: string;
- className?: string;
- clipStartTime: number;
- trimStart: number;
- trimEnd: number;
- clipDuration: number;
+ src: string;
+ poster?: string;
+ className?: string;
+ clipStartTime: number;
+ trimStart: number;
+ trimEnd: number;
+ clipDuration: number;
}
export function VideoPlayer({
- src,
- poster,
- className = "",
- clipStartTime,
- trimStart,
- trimEnd,
- clipDuration
+ src,
+ poster,
+ className = "",
+ clipStartTime,
+ trimStart,
+ trimEnd,
+ clipDuration,
}: VideoPlayerProps) {
- const videoRef = useRef<HTMLVideoElement>(null);
- const { isPlaying, currentTime, volume, speed } = usePlaybackStore();
+ const videoRef = useRef<HTMLVideoElement>(null);
+ const { isPlaying, currentTime, volume, speed, muted } = usePlaybackStore();
- // Calculate if we're within this clip's timeline range
- const clipEndTime = clipStartTime + (clipDuration - trimStart - trimEnd);
- const isInClipRange = currentTime >= clipStartTime && currentTime < clipEndTime;
+ // Calculate if we're within this clip's timeline range
+ const clipEndTime = clipStartTime + (clipDuration - trimStart - trimEnd);
+ const isInClipRange =
+ currentTime >= clipStartTime && currentTime < clipEndTime;
- // Sync playback events
- useEffect(() => {
- const video = videoRef.current;
- if (!video || !isInClipRange) return;
+ // Sync playback events
+ useEffect(() => {
+ const video = videoRef.current;
+ if (!video || !isInClipRange) return;
- const handleSeekEvent = (e: CustomEvent) => {
- // Always update video time, even if outside clip range
- const timelineTime = e.detail.time;
- const videoTime = Math.max(trimStart, Math.min(
- clipDuration - trimEnd,
- timelineTime - clipStartTime + trimStart
- ));
- video.currentTime = videoTime;
- };
+ const handleSeekEvent = (e: CustomEvent) => {
+ // Always update video time, even if outside clip range
+ const timelineTime = e.detail.time;
+ const videoTime = Math.max(
+ trimStart,
+ Math.min(
+ clipDuration - trimEnd,
+ timelineTime - clipStartTime + trimStart
+ )
+ );
+ video.currentTime = videoTime;
+ };
- const handleUpdateEvent = (e: CustomEvent) => {
- // Always update video time, even if outside clip range
- const timelineTime = e.detail.time;
- const targetTime = Math.max(trimStart, Math.min(
- clipDuration - trimEnd,
- timelineTime - clipStartTime + trimStart
- ));
+ const handleUpdateEvent = (e: CustomEvent) => {
+ // Always update video time, even if outside clip range
+ const timelineTime = e.detail.time;
+ const targetTime = Math.max(
+ trimStart,
+ Math.min(
+ clipDuration - trimEnd,
+ timelineTime - clipStartTime + trimStart
+ )
+ );
- if (Math.abs(video.currentTime - targetTime) > 0.5) {
- video.currentTime = targetTime;
- }
- };
+ if (Math.abs(video.currentTime - targetTime) > 0.5) {
+ video.currentTime = targetTime;
+ }
+ };
- const handleSpeed = (e: CustomEvent) => {
- video.playbackRate = e.detail.speed;
- };
+ const handleSpeed = (e: CustomEvent) => {
+ video.playbackRate = e.detail.speed;
+ };
- window.addEventListener("playback-seek", handleSeekEvent as EventListener);
- window.addEventListener("playback-update", handleUpdateEvent as EventListener);
- window.addEventListener("playback-speed", handleSpeed as EventListener);
+ window.addEventListener("playback-seek", handleSeekEvent as EventListener);
+ window.addEventListener(
+ "playback-update",
+ handleUpdateEvent as EventListener
+ );
+ window.addEventListener("playback-speed", handleSpeed as EventListener);
- return () => {
- window.removeEventListener("playback-seek", handleSeekEvent as EventListener);
- window.removeEventListener("playback-update", handleUpdateEvent as EventListener);
- window.removeEventListener("playback-speed", handleSpeed as EventListener);
- };
- }, [clipStartTime, trimStart, trimEnd, clipDuration, isInClipRange]);
+ return () => {
+ window.removeEventListener(
+ "playback-seek",
+ handleSeekEvent as EventListener
+ );
+ window.removeEventListener(
+ "playback-update",
+ handleUpdateEvent as EventListener
+ );
+ window.removeEventListener(
+ "playback-speed",
+ handleSpeed as EventListener
+ );
+ };
+ }, [clipStartTime, trimStart, trimEnd, clipDuration, isInClipRange]);
- // Sync playback state
- useEffect(() => {
- const video = videoRef.current;
- if (!video) return;
+ // Sync playback state
+ useEffect(() => {
+ const video = videoRef.current;
+ if (!video) return;
- if (isPlaying && isInClipRange) {
- video.play().catch(() => { });
- } else {
- video.pause();
- }
- }, [isPlaying, isInClipRange]);
+ if (isPlaying && isInClipRange) {
+ video.play().catch(() => {});
+ } else {
+ video.pause();
+ }
+ }, [isPlaying, isInClipRange]);
- // Sync volume and speed
- useEffect(() => {
- const video = videoRef.current;
- if (!video) return;
+ // Sync volume and speed
+ useEffect(() => {
+ const video = videoRef.current;
+ if (!video) return;
- video.volume = volume;
- video.playbackRate = speed;
- }, [volume, speed]);
+ video.volume = volume;
+ video.muted = muted;
+ video.playbackRate = speed;
+ }, [volume, speed, muted]);
- return (
- <video
- ref={videoRef}
- src={src}
- poster={poster}
- className={`w-full h-full object-cover ${className}`}
- playsInline
- preload="auto"
- controls={false}
- disablePictureInPicture
- disableRemotePlayback
- style={{ pointerEvents: 'none' }}
- onContextMenu={(e) => e.preventDefault()}
- />
- );
-} \ No newline at end of file
+ return (
+ <video
+ ref={videoRef}
+ src={src}
+ poster={poster}
+ className={`w-full h-full object-cover ${className}`}
+ playsInline
+ preload="auto"
+ controls={false}
+ disablePictureInPicture
+ disableRemotePlayback
+ style={{ pointerEvents: "none" }}
+ onContextMenu={(e) => e.preventDefault()}
+ />
+ );
+}