diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-04-07 01:09:13 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-04-07 01:09:13 +0200 |
| commit | e4b67094e757917588fb624a30aa046667403add (patch) | |
| tree | 55452692eac69a5a63b58f2a5cdb701dd7023d68 /apps/web/src/core/managers/playback-manager.ts | |
| parent | 79df73643185c02493364a077402726d1fa7b9ec (diff) | |
| download | opencut-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.ts | 29 |
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(); |
