mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
Merge pull request [#494](https://github.com/mazeincoding/AppCut/issues/494)
This commit is contained in:
@@ -67,7 +67,7 @@ export function PropertiesPanel() {
|
|||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<Label className="text-xs text-muted-foreground">Frame rate:</Label>
|
<Label className="text-xs text-muted-foreground">Frame rate:</Label>
|
||||||
<Select
|
<Select
|
||||||
value={(activeProject?.fps || 30).toString()}
|
value={(activeProject?.fps || "N/A").toString()}
|
||||||
onValueChange={handleFpsChange}
|
onValueChange={handleFpsChange}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-32 h-6 text-xs">
|
<SelectTrigger className="w-32 h-6 text-xs">
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import type { PlaybackState, PlaybackControls } from "@/types/playback";
|
import type { PlaybackState, PlaybackControls } from "@/types/playback";
|
||||||
|
import { useTimelineStore } from "@/stores/timeline-store";
|
||||||
|
import { useProjectStore } from "./project-store";
|
||||||
|
|
||||||
interface PlaybackStore extends PlaybackState, PlaybackControls {
|
interface PlaybackStore extends PlaybackState, PlaybackControls {
|
||||||
setDuration: (duration: number) => void;
|
setDuration: (duration: number) => void;
|
||||||
@@ -20,13 +22,33 @@ const startTimer = (store: () => PlaybackStore) => {
|
|||||||
lastUpdate = now;
|
lastUpdate = now;
|
||||||
|
|
||||||
const newTime = state.currentTime + delta * state.speed;
|
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.pause();
|
||||||
state.setCurrentTime(0);
|
state.setCurrentTime(stopTime);
|
||||||
// Notify video elements to sync with reset
|
// Notify video elements to sync with end position
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("playback-seek", { detail: { time: 0 } })
|
new CustomEvent("playback-seek", {
|
||||||
|
detail: { time: stopTime },
|
||||||
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
state.setCurrentTime(newTime);
|
state.setCurrentTime(newTime);
|
||||||
|
|||||||
Reference in New Issue
Block a user