fork(fix): Clone AMLL 并修复 BUG

- 将AMLL Clone到本以地进行修复和优化(emm虽然这很不优雅但是暂时无时间做子模块和Fork)
- 修复在当前播放歌词行不可见的视口Seek会出现滚动偏移的问题
This commit is contained in:
lqtmcstudio
2026-06-07 00:02:14 +08:00
parent 783d2c3dee
commit 72f4510dc8
458 changed files with 86075 additions and 1665 deletions

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>AMLL Vue Wrapper Test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="src/test.ts" type="module" defer></script>
<style>
:root {
font-family:
-apple-system, BlinkMacSystemFont, "SF Pro Display", "PingFang SC", system-ui, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
body {
background: #222;
margin: 0;
}
</style>
</head>
<body style="height: 100vh; overflow: hidden;">
<div id="root" style="height: 100vh; overflow: hidden;"></div>
</body>
</html>

View File

@@ -0,0 +1,30 @@
{
"name": "@applemusic-like-lyrics/playground-vue",
"private": true,
"version": "0.0.0",
"type": "module",
"nx": {
"tags": [
"playground"
]
},
"scripts": {
"dev": "vite dev"
},
"devDependencies": {
"@applemusic-like-lyrics/core": "workspace:^",
"@applemusic-like-lyrics/lyric": "workspace:^",
"@applemusic-like-lyrics/vue": "workspace:^",
"@pixi/app": "^7.4.3",
"@pixi/core": "^7.4.3",
"@pixi/display": "^7.4.3",
"@pixi/filter-blur": "^7.4.3",
"@pixi/filter-color-matrix": "^7.4.3",
"@pixi/sprite": "^7.4.3",
"@vitejs/plugin-vue": "^6.0.7",
"@vitejs/plugin-vue-jsx": "^5.1.5",
"@vue/tsconfig": "^0.9.0",
"vite": "catalog:",
"vue": "^3.5.30"
}
}

View File

@@ -0,0 +1,125 @@
<template>
<BackgroundRender
:album="state.albumUrl"
:album-is-video="state.albumIsVideo"
ref="bgRef"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
/>
<LyricPlayer
:lyric-lines="lyricLines"
:current-time="state.currentTime"
ref="playerRef"
@line-click="e => { if (audioRef) audioRef.currentTime = (e.line.getLine().startTime / 1000) }"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; mix-blend-mode: plus-lighter;"
>
<template #bottom-line> Test Bottom Line </template>
</LyricPlayer>
<div
style="position: absolute; right: 0; bottom: 0; background-color: #0004; margin: 1rem; padding: 1rem; border-radius: 0.5rem; color: white; display: flex; flex-direction: column; gap: 0.5rem;"
>
<div>AMLL Vue 绑定调试页面</div>
<div>为了减少依赖,没有过多的调试设置。</div>
<div>更加详尽的调试可以直接使用 Core 模块调试。</div>
<button type="button" @click="onClickOpenAudio">加载音乐</button>
<button type="button" @click="onClickOpenAlbumImage">
加载专辑背景资源(图片/视频)
</button>
<button type="button" @click="onClickOpenTTMLLyric">加载歌词</button>
<audio
controls
ref="audioRef"
@play="onPlay"
:src="state.audioUrl"
preload="auto"
/>
</div>
</template>
<script setup lang="ts">
import type { LyricLine } from "@applemusic-like-lyrics/core";
import { parseTTML } from "@applemusic-like-lyrics/lyric";
import {
BackgroundRender,
type BackgroundRenderRef,
LyricPlayer,
type LyricPlayerRef,
} from "@applemusic-like-lyrics/vue";
import { onMounted, reactive, ref, shallowRef } from "vue";
const audioRef = ref<HTMLAudioElement>();
const state = reactive({
audioUrl: "",
albumUrl: "",
albumIsVideo: false,
currentTime: 0,
});
const lyricLines = shallowRef<LyricLine[]>([]);
const playerRef = ref<LyricPlayerRef>();
const bgRef = ref<BackgroundRenderRef>();
onMounted(() => {
console.log(playerRef.value);
console.log(bgRef.value);
});
function onPlay() {
const onFrame = () => {
if (audioRef.value && !audioRef.value.paused) {
state.currentTime = (audioRef.value.currentTime * 1000) | 0;
requestAnimationFrame(onFrame);
}
};
requestAnimationFrame(onFrame);
}
function onClickOpenAudio() {
const input = document.createElement("input");
input.type = "file";
input.accept = "audio/*";
input.onchange = () => {
const file = input.files?.[0];
if (file) {
if (state.audioUrl.trim().length > 0) {
URL.revokeObjectURL(state.audioUrl);
}
state.audioUrl = URL.createObjectURL(file);
state.albumIsVideo = file.type.startsWith("video/");
}
};
input.click();
}
function onClickOpenAlbumImage() {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/*,video/*";
input.onchange = () => {
const file = input.files?.[0];
if (file) {
if (state.albumUrl.trim().length > 0) {
URL.revokeObjectURL(state.albumUrl);
}
state.albumUrl = URL.createObjectURL(file);
}
};
input.click();
}
function onClickOpenTTMLLyric() {
const input = document.createElement("input");
input.type = "file";
input.accept = ".ttml,text/*";
input.onchange = async () => {
const file = input.files?.[0];
if (file) {
const text = await file.text();
const result = parseTTML(text);
console.log("parseTTML", result);
lyricLines.value = result.lines;
}
};
input.click();
}
</script>

View File

@@ -0,0 +1,5 @@
import "@applemusic-like-lyrics/core/style.css";
import { createApp } from "vue";
import TestApp from "./TestApp.vue";
createApp(TestApp).mount("#root");

View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -0,0 +1,9 @@
{
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"compilerOptions": {
"isolatedDeclarations": false,
"jsxImportSource": "vue",
"jsx": "preserve"
}
}

View File

@@ -0,0 +1,22 @@
import path from "node:path";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { defineConfig } from "vite";
export default defineConfig({
resolve: {
alias: {
"@applemusic-like-lyrics/core/style.css": path.resolve(
__dirname,
"../../core/src/styles/index.css",
),
"@applemusic-like-lyrics/vue": path.resolve(__dirname, "../../vue/src"),
"@applemusic-like-lyrics/core": path.resolve(__dirname, "../../core/src"),
"@applemusic-like-lyrics/lyric": path.resolve(
__dirname,
"../../lyric/src",
),
},
},
plugins: [vue(), vueJsx()],
});