diff options
| author | iza <59828082+izadoesdev@users.noreply.github.com> | 2025-06-23 17:53:13 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-23 17:53:13 +0300 |
| commit | 13817a5ff847762a3ac4eb7cb09d17012b59e520 (patch) | |
| tree | 7c9b5fc69bbe86dfa66746c6a61da57a951bd1e9 /apps/web/src/stores/playback-store.ts | |
| parent | c8f92a76e30fba860b30a9b528e5b42291d2d54a (diff) | |
| parent | 9c61b72bd401d2a50b876bb2afbd571f7403a8e4 (diff) | |
| download | opencut-13817a5ff847762a3ac4eb7cb09d17012b59e520.tar.gz | |
Merge pull request #15 from StarKnightt/feature/speed-control
Add video speed control and improve playback smoothness
Diffstat (limited to 'apps/web/src/stores/playback-store.ts')
| -rw-r--r-- | apps/web/src/stores/playback-store.ts | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/apps/web/src/stores/playback-store.ts b/apps/web/src/stores/playback-store.ts index 3c0bfdec..a4794b7f 100644 --- a/apps/web/src/stores/playback-store.ts +++ b/apps/web/src/stores/playback-store.ts @@ -6,15 +6,20 @@ interface PlaybackStore extends PlaybackState, PlaybackControls { setCurrentTime: (time: number) => void; } -let playbackTimer: NodeJS.Timeout | null = null; +let playbackTimer: number | null = null; const startTimer = (store: any) => { - if (playbackTimer) clearInterval(playbackTimer); + if (playbackTimer) cancelAnimationFrame(playbackTimer); - playbackTimer = setInterval(() => { + // Use requestAnimationFrame for smoother updates + const updateTime = () => { const state = store(); if (state.isPlaying && state.currentTime < state.duration) { - const newTime = state.currentTime + 0.1; + const now = performance.now(); + const delta = (now - lastUpdate) / 1000; // Convert to seconds + lastUpdate = now; + + const newTime = state.currentTime + (delta * state.speed); if (newTime >= state.duration) { state.pause(); } else { @@ -23,12 +28,16 @@ const startTimer = (store: any) => { window.dispatchEvent(new CustomEvent('playback-update', { detail: { time: newTime } })); } } - }, 100); + playbackTimer = requestAnimationFrame(updateTime); + }; + + let lastUpdate = performance.now(); + playbackTimer = requestAnimationFrame(updateTime); }; const stopTimer = () => { if (playbackTimer) { - clearInterval(playbackTimer); + cancelAnimationFrame(playbackTimer); playbackTimer = null; } }; @@ -38,6 +47,7 @@ export const usePlaybackStore = create<PlaybackStore>((set, get) => ({ currentTime: 0, duration: 0, volume: 1, + speed: 1.0, play: () => { set({ isPlaying: true }); @@ -64,10 +74,20 @@ export const usePlaybackStore = create<PlaybackStore>((set, get) => ({ set({ currentTime: clampedTime }); // Notify video elements to seek - window.dispatchEvent(new CustomEvent('playback-seek', { detail: { time: clampedTime } })); + const event = new CustomEvent('playback-seek', { detail: { time: clampedTime } }); + window.dispatchEvent(event); }, setVolume: (volume: number) => set({ volume: Math.max(0, Math.min(1, volume)) }), + + setSpeed: (speed: number) => { + const newSpeed = Math.max(0.1, Math.min(2.0, speed)); + set({ speed: newSpeed }); + + const event = new CustomEvent('playback-speed', { detail: { speed: newSpeed } }); + window.dispatchEvent(event); + }, + setDuration: (duration: number) => set({ duration }), setCurrentTime: (time: number) => set({ currentTime: time }), }));
\ No newline at end of file |
