summaryrefslogtreecommitdiff
path: root/apps/web
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web')
-rw-r--r--apps/web/src/components/editor/properties-panel/index.tsx2
-rw-r--r--apps/web/src/stores/playback-store.ts32
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);