diff --git a/bun.lockb b/bun.lockb
index ef47415..9febfb2 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index db822f6..d203dc2 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"private": false,
"module": "index.ts",
"type": "module",
- "workspaces": ["packages/web", "packages/core", "packages/electron"],
+ "workspaces": ["packages/web", "packages/core"],
"scripts": {
"electron:dev": "bun --filter 'electron' dev",
"web:dev": "bun --filter 'web' dev",
@@ -37,7 +37,6 @@
"concurrently": "^9.0.1",
"cross-env": "^7.0.3"
},
- "dependencies": {},
"trustedDependencies": [
"svelte-preprocess"
]
diff --git a/packages/core/components/displayFPS.svelte b/packages/core/components/displayFPS.svelte
new file mode 100644
index 0000000..8ee6ca0
--- /dev/null
+++ b/packages/core/components/displayFPS.svelte
@@ -0,0 +1,135 @@
+
+
+
+ {fps} fps
+ Frame Time: {frameTime.toFixed(2)} ms
+ 1% Low: {onePercentLow} fps
+
+fps
+
+frametime
+
diff --git a/packages/core/components/lyrics/lyricLine.svelte b/packages/core/components/lyrics/lyricLine.svelte
index ed1684c..55317aa 100644
--- a/packages/core/components/lyrics/lyricLine.svelte
+++ b/packages/core/components/lyrics/lyricLine.svelte
@@ -38,6 +38,7 @@
let isCurrentLyric = false;
function updateY(timestamp: number) {
+ if (stopped) return;
if (lastUpdateY === undefined) {
lastUpdateY = new Date().getTime();
}
@@ -52,6 +53,7 @@
}
function updateX(timestamp: number) {
+ if (stopped) return;
if (lastUpdateX === undefined) {
lastUpdateX = timestamp;
}
@@ -70,6 +72,7 @@
* @param {number} pos - X offset, in pixels
*/
export const setX = (pos: number) => {
+ stopped = true;
positionX = pos;
};
@@ -78,6 +81,7 @@
* @param {number} pos - Y offset, in pixels
*/
export const setY = (pos: number) => {
+ stopped = true;
positionY = pos;
};
diff --git a/packages/core/components/lyrics/newLyrics.svelte b/packages/core/components/lyrics/newLyrics.svelte
index 55463a2..45d5644 100644
--- a/packages/core/components/lyrics/newLyrics.svelte
+++ b/packages/core/components/lyrics/newLyrics.svelte
@@ -4,6 +4,7 @@
import LyricLine from './lyricLine.svelte';
import createLyricsSearcher from '@core/lyrics/lyricSearcher';
import userAdjustingProgress from '@core/state/userAdjustingProgress';
+ import DisplayFps from '../displayFPS.svelte';
// constants
const viewportHeight = document.documentElement.clientHeight;
@@ -16,11 +17,16 @@
document.body.style.overflow = 'hidden';
// Props
- let { originalLyrics, progress, player, showInteractiveBox } : {
- originalLyrics: LyricData,
- progress: number,
- player: HTMLAudioElement | null,
- showInteractiveBox: boolean
+ let {
+ originalLyrics,
+ progress,
+ player,
+ showInteractiveBox
+ }: {
+ originalLyrics: LyricData;
+ progress: number;
+ player: HTMLAudioElement | null;
+ showInteractiveBox: boolean;
} = $props();
// States
@@ -76,15 +82,28 @@
for (let i = 0; i < lyricElements.length; i++) {
const currentLyricComponent = lyricComponents[i];
const lyric = originalLyrics.scripts[i];
+ const lyricBeforeProgress = lyric.end < progress;
+ const lyricInProgress = lyric.start <= progress && progress <= lyric.end;
+ const lyricWillHigherThanViewport = lyricTopList[i + 3] - relativeOrigin < 0;
+ const lyricWillLowerThanViewport = lyricTopList[i - 3] - relativeOrigin > lyricsContainer?.getBoundingClientRect().height!;
+
let delay = 0;
- if (progress > lyric.end) {
+ if (lyricBeforeProgress) {
delay = 0;
- } else if (lyric.start <= progress && progress <= lyric.end) {
- delay = 0.042;
+ } else if (lyricInProgress) {
+ delay = 0.03;
} else {
delay = Math.min(Math.min(currentLyricDuration, 0.6), 0.067 * (i - currentLyricIndex + 1.2));
}
- currentLyricComponent.update({ x: 0, y: lyricTopList[i] - relativeOrigin }, delay);
+
+ // if it's not in the viewport, we need to use animations
+ if (lyricWillHigherThanViewport || lyricWillLowerThanViewport) {
+ currentLyricComponent.update({ x: 0, y: lyricTopList[i] - relativeOrigin }, delay);
+ }
+ // if it's still in the viewport, we need to use spring animation
+ else {
+ currentLyricComponent.update({ x: 0, y: lyricTopList[i] - relativeOrigin }, delay);
+ }
}
}
@@ -111,11 +130,16 @@
});
function handleScroll(deltaY: number) {
+ if (lyricComponents[0].getInfo().y > 0 && deltaY < 0) {
+ deltaY = 0;
+ }
+ if (lyricComponents[lyricComponents.length - 1].getInfo().y < 100 && deltaY > 0) {
+ deltaY = 0;
+ }
for (let i = 0; i < lyricElements.length; i++) {
const currentLyricComponent = lyricComponents[i];
const currentY = currentLyricComponent.getInfo().y;
scrolling = true;
- currentLyricComponent.stop();
currentLyricComponent.setY(currentY - deltaY);
currentLyricComponent.syncSpringWithDelta(deltaY);
}
@@ -200,21 +224,19 @@
lastEventProgress = progress;
if (!lyricChanged || scrolling) return;
if (!lyricIndexDeltaTooBig && deltaInRange) {
- console.log("Event: regular move");
+ console.log('Event: regular move');
console.log(new Date().getTime(), lastSeekForward);
computeLayout();
- }
- else if ($userAdjustingProgress) {
+ } else if ($userAdjustingProgress) {
if (deltaTooBig && lyricChanged) {
- console.log("Event: seek forward");
+ console.log('Event: seek forward');
seekForward();
} else if (deltaIsNegative && lyricChanged) {
- console.log("Event: seek backward");
+ console.log('Event: seek backward');
seekForward();
}
- }
- else {
- console.log("Event: regular move");
+ } else {
+ console.log('Event: regular move');
computeLayout();
}
});
@@ -253,16 +275,23 @@
{#if debugMode}
+ right-0 font-mono"
+ >
progress: {progress.toFixed(2)}, nextUpdate: {nextUpdate}, scrolling: {scrolling}, current: {currentLyricIndex},
uap: {$userAdjustingProgress}
+
+
+
{/if}
{#if originalLyrics && originalLyrics.scripts}
{#each lyricLines as lyric, i}
-
+
{/each}
{/if}
diff --git a/packages/core/package.json b/packages/core/package.json
index a4831a4..9893000 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -27,13 +27,12 @@
},
"dependencies": {
"@alikia/aqualyrics": "npm:@jsr/alikia__aqualyrics",
- "@applemusic-like-lyrics/core": "^0.1.3",
- "@applemusic-like-lyrics/lyric": "^0.2.2",
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0",
"@types/bun": "^1.1.6",
"bezier-easing": "^2.1.0",
+ "chart.js": "^4.4.7",
"jotai": "^2.8.0",
"jotai-svelte": "^0.0.2",
"jss": "^10.10.0",
diff --git a/packages/web/package.json b/packages/web/package.json
index 5b613dd..f8f03ee 100644
--- a/packages/web/package.json
+++ b/packages/web/package.json
@@ -37,8 +37,6 @@
},
"dependencies": {
"@alikia/aqualyrics": "npm:@jsr/alikia__aqualyrics",
- "@applemusic-like-lyrics/core": "^0.1.3",
- "@applemusic-like-lyrics/lyric": "^0.2.4",
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0",
diff --git a/packages/web/src/routes/play/[id]/+page.svelte b/packages/web/src/routes/play/[id]/+page.svelte
index 59ec353..0db0d20 100644
--- a/packages/web/src/routes/play/[id]/+page.svelte
+++ b/packages/web/src/routes/play/[id]/+page.svelte
@@ -209,7 +209,7 @@
if (audioPlayer === null) return;
if ($userAdjustingProgress === false) currentProgress = audioPlayer.currentTime;
progressBarRaw.set(audioPlayer.currentTime);
- }, 50);
+ }, 20);
}
onMount(() => {
diff --git a/tsconfig.base.json b/tsconfig.base.json
index a768407..75dbf4d 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -13,7 +13,8 @@
"sourceMap": true,
"strict": true,
"types": ["bun"]
- }
+ },
+ "exclude": ["node_modules", "build", "dist", "tmp"]
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
//