From 3c64f9cfa2a400b809d320b6799dd9d69b3abee1 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Thu, 31 Jul 2025 21:46:33 +0200 Subject: Merge pull request [#494](https://github.com/mazeincoding/AppCut/issues/494) --- apps/web/src/stores/playback-store.ts | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'apps/web/src/stores') diff --git a/apps/web/src/stores/playback-store.ts b/apps/web/src/stores/playback-store.ts index 543865f9..feea0f46 100644 --- a/apps/web/src/stores/playback-store.ts +++ b/apps/web/src/stores/playback-store.ts @@ -1,5 +1,7 @@ import { create } from "zustand"; import type { PlaybackState, PlaybackControls } from "@/types/playback"; +import { useTimelineStore } from "@/stores/timeline-store"; +import { useProjectStore } from "./project-store"; interface PlaybackStore extends PlaybackState, PlaybackControls { setDuration: (duration: number) => void; @@ -20,13 +22,33 @@ const startTimer = (store: () => PlaybackStore) => { lastUpdate = now; const newTime = state.currentTime + delta * state.speed; - if (newTime >= state.duration) { - // When video completes, pause and reset playhead to start + + // Get actual content duration from timeline store + const actualContentDuration = useTimelineStore + .getState() + .getTotalDuration(); + + // Stop at actual content end, not timeline duration (which has 10s minimum) + // It was either this or reducing default min timeline to 1 second + const effectiveDuration = + actualContentDuration > 0 ? actualContentDuration : state.duration; + + if (newTime >= effectiveDuration) { + // When content completes, pause just before the end so we can see the last frame + const projectFps = useProjectStore.getState().activeProject?.fps; + if (!projectFps) + console.error("Project FPS is not set, assuming 30fps"); + + const frameOffset = 1 / (projectFps ?? 30); // Stop 1 frame before end based on project FPS + const stopTime = Math.max(0, effectiveDuration - frameOffset); + state.pause(); - state.setCurrentTime(0); - // Notify video elements to sync with reset + state.setCurrentTime(stopTime); + // Notify video elements to sync with end position window.dispatchEvent( - new CustomEvent("playback-seek", { detail: { time: 0 } }) + new CustomEvent("playback-seek", { + detail: { time: stopTime }, + }) ); } else { state.setCurrentTime(newTime); -- cgit v1.3.1