summaryrefslogtreecommitdiff
path: root/apps/web/src/core/managers/playback-manager.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-07 01:09:13 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-07 01:09:13 +0200
commite4b67094e757917588fb624a30aa046667403add (patch)
tree55452692eac69a5a63b58f2a5cdb701dd7023d68 /apps/web/src/core/managers/playback-manager.ts
parent79df73643185c02493364a077402726d1fa7b9ec (diff)
downloadopencut-e4b67094e757917588fb624a30aa046667403add.tar.gz
refactor: split effects and masks into dedicated rust crates, introduce MediaTime and FrameRate
Diffstat (limited to 'apps/web/src/core/managers/playback-manager.ts')
-rw-r--r--apps/web/src/core/managers/playback-manager.ts29
1 files changed, 18 insertions, 11 deletions
diff --git a/apps/web/src/core/managers/playback-manager.ts b/apps/web/src/core/managers/playback-manager.ts
index 6943f187..47909bfe 100644
--- a/apps/web/src/core/managers/playback-manager.ts
+++ b/apps/web/src/core/managers/playback-manager.ts
@@ -1,4 +1,6 @@
import type { EditorCore } from "@/core";
+import { TICKS_PER_SECOND } from "@/lib/wasm";
+import { roundToFrame } from "opencut-wasm";
export class PlaybackManager {
private isPlaying = false;
@@ -9,11 +11,12 @@ export class PlaybackManager {
private isScrubbing = false;
private listeners = new Set<() => void>();
private playbackTimer: number | null = null;
- private lastUpdate = 0;
+ private playbackStartWallTime = 0;
+ private playbackStartTime = 0;
constructor(private editor: EditorCore) {
this.editor.timeline.subscribe(() => {
- const maxTime = this.editor.timeline.getLastSeekableTime();
+ const maxTime = this.editor.timeline.getTotalDuration();
if (this.currentTime > maxTime && maxTime > 0) {
this.currentTime = maxTime;
this.notify();
@@ -22,7 +25,7 @@ export class PlaybackManager {
}
play(): void {
- const maxTime = this.editor.timeline.getLastSeekableTime();
+ const maxTime = this.editor.timeline.getTotalDuration();
if (maxTime > 0) {
if (this.currentTime >= maxTime) {
@@ -50,8 +53,12 @@ export class PlaybackManager {
}
seek({ time }: { time: number }): void {
- const maxTime = this.editor.timeline.getLastSeekableTime();
+ const maxTime = this.editor.timeline.getTotalDuration();
this.currentTime = Math.max(0, Math.min(maxTime, time));
+ if (this.isPlaying) {
+ this.playbackStartWallTime = performance.now();
+ this.playbackStartTime = this.currentTime;
+ }
this.notify();
window.dispatchEvent(
@@ -135,7 +142,8 @@ export class PlaybackManager {
cancelAnimationFrame(this.playbackTimer);
}
- this.lastUpdate = performance.now();
+ this.playbackStartWallTime = performance.now();
+ this.playbackStartTime = this.currentTime;
this.updateTime();
}
@@ -149,12 +157,11 @@ export class PlaybackManager {
private updateTime = (): void => {
if (!this.isPlaying) return;
- const now = performance.now();
- const delta = (now - this.lastUpdate) / 1000;
- this.lastUpdate = now;
-
- const newTime = this.currentTime + delta;
- const maxTime = this.editor.timeline.getLastSeekableTime();
+ const fps = this.editor.project.getActive()?.settings.fps;
+ const elapsedSeconds = (performance.now() - this.playbackStartWallTime) / 1000;
+ const rawTime = this.playbackStartTime + Math.round(elapsedSeconds * TICKS_PER_SECOND);
+ const newTime = fps ? (roundToFrame({ time: rawTime, rate: fps }) ?? rawTime) : rawTime;
+ const maxTime = this.editor.timeline.getTotalDuration();
if (maxTime > 0 && newTime >= maxTime) {
this.pause();