diff options
Diffstat (limited to 'apps/web/src')
| -rw-r--r-- | apps/web/src/components/editor/properties-panel/index.tsx | 2 | ||||
| -rw-r--r-- | apps/web/src/stores/playback-store.ts | 32 |
2 files changed, 28 insertions, 6 deletions
diff --git a/apps/web/src/components/editor/properties-panel/index.tsx b/apps/web/src/components/editor/properties-panel/index.tsx index 720c4a26..f1b3f6a3 100644 --- a/apps/web/src/components/editor/properties-panel/index.tsx +++ b/apps/web/src/components/editor/properties-panel/index.tsx @@ -67,7 +67,7 @@ export function PropertiesPanel() { <div className="flex flex-col gap-1"> <Label className="text-xs text-muted-foreground">Frame rate:</Label> <Select - value={(activeProject?.fps || 30).toString()} + value={(activeProject?.fps || "N/A").toString()} onValueChange={handleFpsChange} > <SelectTrigger className="w-32 h-6 text-xs"> 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); |
