From 9d451b68185516a773b42222f0284e8a162a66f4 Mon Sep 17 00:00:00 2001
From: memdmp <memdmp@estrogen.zone>
Date: Thu, 31 Jul 2025 23:18:34 +0200
Subject: feat: some changes

---
 src/lib/Player/Player.svelte | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

(limited to 'src/lib/Player/Player.svelte')

diff --git a/src/lib/Player/Player.svelte b/src/lib/Player/Player.svelte
index f6df121..3d859ea 100644
--- a/src/lib/Player/Player.svelte
+++ b/src/lib/Player/Player.svelte
@@ -11,7 +11,7 @@
 	let video = $state(undefined as Video | undefined);
 	let frameCount = $state(0);
 	let playing = $state(false);
-	let playbackStarted = $state(0);
+	let playbackRelativeTo = $state(0);
 	let playbackFrameOffset = 0;
 	let renderPromise: Promise<void> | void = void 0;
 	let renderId = 0;
@@ -66,11 +66,18 @@
 	let playbackLoopId = 0;
 	const startPlaybackLoop = (id = ++playbackLoopId) => {
 		if (video && id === playbackLoopId) {
-			const ms = performance.now() - playbackStarted;
+			const ms = performance.now() - playbackRelativeTo;
 			let f = Math.floor((ms / 1000) * video.fps) + playbackFrameOffset;
 
+			if (audio) {
+				const desiredTime = frame / video.fps;
+				// If we get too out of lock-step with audio, we re-sync
+				if (Math.abs(desiredTime - audio.currentTime) > 0.3) audio.currentTime = desiredTime;
+			}
+
 			if (f > frameCount) {
 				f = frameCount;
+				playbackRelativeTo = 0;
 				playing = false;
 			}
 			frame = f;
@@ -79,12 +86,16 @@
 			);
 		}
 	};
+	// State Synchronisation effect & playback starter
 	$effect(() => {
 		if (playing) {
-			playbackStarted = performance.now();
+			if (frame === frameCount && playbackRelativeTo === 0) {
+				frame = 0;
+			}
+			playbackRelativeTo = performance.now();
 			playbackFrameOffset = frame;
 			startPlaybackLoop();
-		}
+		} else playbackRelativeTo = 0;
 	});
 	let loadedFrameTimestamp = false;
 	onMount(() => {
@@ -104,7 +115,7 @@
 			} catch (_) {}
 	});
 	$effect(() => {
-		if (audio && video && !playing) {
+		if (audio && video && !playing && !playbackFrameOffset) {
 			try {
 				const f = frame;
 				audio.currentTime = frame / video.fps;
@@ -144,7 +155,13 @@
 	}}
 />
 
-<Keybinds bind:frame {frameCount} fps={video?.fps} bind:playing bind:playbackStarted />
+<Keybinds
+	bind:frame
+	{frameCount}
+	fps={video?.fps}
+	bind:playing
+	bind:playbackStarted={playbackRelativeTo}
+/>
 
 <div class="p-2 w-screen h-screen relative flex flex-col">
 	<div class="flex-1 relative">
@@ -153,9 +170,9 @@
 				Your browser doesn't support the canvas API.
 			</canvas>
 			{#if audioSource}
-				<audio src={audioSource} bind:this={audio}></audio>
+				<audio src={audioSource} bind:this={audio} preload="auto"></audio>
 			{/if}
 		</div>
 	</div>
-	<FrameSlider bind:frame {frameCount} bind:playing bind:playbackStarted />
+	<FrameSlider bind:frame {frameCount} bind:playing bind:playbackStarted={playbackRelativeTo} />
 </div>
-- 
cgit v1.2.3

