Skip to content
abloom25Public

About

基于 Vue 3、TypeScript、Pinia 和 SCSS 的沉浸式单页音乐播放器。所有远程歌单和本地音乐会合并为一个匿名曲库,页面不会显示歌单名称、平台或来源。

Topics

Resources

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

 

History

136 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Meliora

Meliora

沉浸式 · 视听一体的网页音乐播放器

License: AGPL v3 Vue 3 Vite TypeScript PWA PRs Welcome

特性 · 快速开始 · 管理后台 · 快捷键 · 部署 · 开发 · 路线图

在线预览 · 反馈问题 · 贡献指南


✨ 特性

视听一体

  • 🎨 滚动节拍预分析:默认基础模式,沿用 HPSS 节奏包络。开播后在浏览器 Worker 中优先构建当前位置前方的一段; 分段就绪即开始高亮,缓冲够用便暂停计算,继续播放或拖动进度后从已有窗口续建,支持四档闪烁密度与延迟微调。 当前歌曲优先,空闲时串行准备上一首/下一首的开头,切歌复用已完成结果;常听歌曲的已完成窗口可保存在本机并续建。
  • 🥁 可选增强模型:设置中可选择 Beat This! Small 或标准版,由用户手动下载启用,模型保存在本机; 模型预测节拍位置,原算法提供闪光强度与持续声部,无需后端推理。Small 约 12.7 MB,标准版约 85.3 MB, 首次使用另需约 28.3 MB 共享运行组件;可删除本机模型并随时切回基础模式。
  • 💾 预分析资源范围:只有 DSP/模型计算按窗口滚动,音频仍需整曲下载和解码,首次分析可能额外读取一次音频。 音频内容校验后优先恢复持久缓存,覆盖当前缓冲需求时跳过解码与模型准备;频谱使用有容量上限的窗口缓存。 当前限制为时长不超过 10 分钟、文件不超过 64 MiB;无法完整读取的流媒体跳过高亮,播放不受影响。
  • 🌈 动态背景:封面模糊渲染 + 可调节模糊/饱和度/节奏亮度,支持关闭
  • 🎵 零延迟切歌:三 Audio 池 + 预加载槽 + 平滑切歌淡入淡出

歌词体验

  • 📜 逐字歌词:接入 AMLL TTML DB 社区逐词歌词库,英文按词、中文按字随演唱推进点亮; 网易云与 QQ 曲目还会按歌曲 ID 获取平台原生 YRC/QRC,保留翻译与罗马音。 三源并行、先到先显示,优先采用 AMLL,其次平台逐字歌词,没有逐字数据时回落为整行高亮; 也支持增强型 LRC
  • 🎭 对唱与和声:对唱双声部左右分栏同时高亮,背景和声在所属句子唱到时从下沿探出、唱完收回
  • 🌊 弹簧牵引滚动:每行一根弹簧、沿运动方向逐行错峰起步,换行与拖动进度条都不会顿挫; 可调弹簧松紧、字号,支持译文与罗马音
  • 🔍 进度条歌词预览:悬停进度条即可看到该时刻的歌词,含对唱、和声与逐字进度快照(设置中开启)
  • ℹ️ 歌曲信息:设置中显示歌曲、歌手、专辑、时长和实际歌词来源;异步加载使用占位与淡入过渡
  • 🪟 歌词小窗:Document Picture-in-Picture 独立浮窗,支持在外部应用时查看歌词
  • ⚡ 歌词性能:长歌词按可见范围挂载,时间轴与布局局部更新;普通歌词等待时间边界,逐字扫光时才逐帧刷新, 暂停或页面隐藏时停止相应任务,歌词小窗使用独立调度。歌词请求优先保障当前播放,取消过期预加载。

歌词显示与动画效果参考了 Apple Music-like Lyrics(AMLL) 的实现思路,包括弹簧滚动、逐字高亮、对唱与和声,以及前奏和间奏的三点等待动画,并结合 Meliora 的布局与渲染方式进行了适配。

播放控制

  • 🎚️ 内置均衡器:10 频段增益调节 + 预设方案
  • ⏰ 定时关闭:倒计时自动停止播放
  • 🔀 播放模式:顺序 / 随机 / 单曲循环
  • ⏭️ 自动跳过:加载失败自动跳到下一首
  • 📊 本机听歌统计:按实际播放时长记录有效播放次数,常听歌曲可复用节拍缓存;设置中可查看和清除统计及缓存

沉浸模式

  • 📱 全屏模式:一键占满整个屏幕
  • 👻 自动隐藏:鼠标闲置 30 秒后只保留歌曲内容
  • 📳 触感反馈:移动端切歌/操作轻震动

平台集成

  • 📲 PWA 安装:可添加到桌面,支持离线启动
  • 🔒 MediaSession:锁屏 / 控制中心播放控制
  • 🔗 歌曲分享:Web Share API 分享当前曲目

曲库管理

  • 🌐 远程歌单:网易云 / QQ 音乐歌单,通过 Meting API 解析
  • ⏳ 渐进加载:已就绪的来源先显示,较慢来源继续加载,保留正在播放的曲目
  • 💾 本地音乐:上传音频/封面/歌词,自动合并去重
  • ⚙️ 可视化管理:完整的 Web 管理后台,无需编辑代码

无障碍

  • ♿ prefers-reduced-motion 支持
  • ⌨️ 完整键盘快捷键 + focus trap
  • 🎨 颜色 + 图标双重状态提示

🚀 快速开始

pnpm install
pnpm dev          # 仅前端(5175)
pnpm dev:full     # 前端 + 后端模拟(5175 + 8788)

需要 Node 22+ 与 pnpm 11.5.3+。

  • pnpm dev:仅启动 Vite 前端开发服务器,默认端口 5175,适合纯 UI 开发
  • pnpm dev:full:同时启动 Vite + Wrangler Pages Functions 本地模拟,/api/* 请求代理到 8788 端口,可完整测试管理后台(含 /setup 初始化流程)。Wrangler 使用 .wrangler/pages-dev-static 临时静态目录启动本地 Functions,静态页面仍由 Vite 提供,不依赖 dist 是否存在或是否最新。

本地后端可使用开发模式(.dev.vars 中 DEVELOPMENT=true),配置和密码不持久化,重启即重置。复制 .dev.vars.example 为 .dev.vars 并填入真实 GitHub Token、关闭 DEVELOPMENT 后可测试完整流程。

平台原生逐字歌词使用同源 /api/lyrics 接口,本地测试需启动 pnpm dev:full。 该接口沿用现有 API 环境检查与 ADMIN_DISABLED 开关;纯静态部署或 API 被关闭时,播放器仍使用 AMLL 与普通歌词。 浏览器会缓存命中结果 24 小时、明确未命中结果 15 分钟,网络故障不记为未命中。


⚙️ 管理后台

访问 https://你的域名/admin 进入管理后台。

首次使用

部署后首次访问 /admin 会进入 /setup 页面,设置管理员密码即可。密码经 PBKDF2 哈希后存储,后续可在后台「安全」页面修改。

后台功能

页面 功能
站点 站点名称、图标、Meting API 端点、API Token
歌单 添加/删除/启用网易云与 QQ 音乐歌单
本地音乐 上传音频/封面/歌词,编辑曲目信息
统计 Umami / Google Analytics 配置
高级 GitHub 代理、预发布更新、自定义 CSS / JS
安全 修改管理员密码
关于 版本信息、检查更新、同步上游代码

上传站点图标或本地音乐资源时,后台先创建不挂载到分支的暂存 Git Blob;只有点击保存后,加密的 public/config.json、全部暂存文件和配置中不再引用的旧资源才会通过同一个 Git Tree / Commit 原子写入目标分支。撤销或保存冲突不会提前覆盖、删除线上文件。提交成功后会触发部署平台自动重新构建;播放器公开配置在构建期写入前端 bundle,首屏不再请求管理 API,远程歌单仍按 apiEndpoint 与歌单 ID 实时请求 Meting API。

更新说明

管理后台「关于」页的一键更新用于同步官方上游版本,适合未修改源码、仅通过后台维护配置和曲库的部署。

用户只需要点击一次“更新”。后台会触发 GitHub Actions,Actions 在 meliora-update/* 临时分支里同步上游代码,运行依赖安装、测试、类型检查、Lint、格式检查与构建;验证通过后再合并目标分支最新提交并执行关键验证,无冲突才自动合并并推送回目标分支。

失败、冲突或推送被拒绝时目标分支保持不变,后台会显示运行状态、失败原因和 GitHub Actions 日志入口,不需要用户手动 merge。流程会保留 public/config.json、public/admin.json、public/music/、.github/workflows/、.prettierignore、.env、.env.local、.dev.vars 和构建产物等部署数据;.env.example、.dev.vars.example 等模板文件会随上游更新。

新版更新协议把工作流视为部署仓库自己的固定启动器:普通代码、UI、后端和依赖升级不会改写 .github/workflows/,因此只使用 Actions 自动提供的 GITHUB_TOKEN 即可推送验证后的业务代码,不需要再给 Actions 单独配置高权限 PAT。工作流本身若需要升级,必须单独手动同步;这不会阻塞日常版本更新。

**不向下兼容:**旧版部署需要手动同步或重新部署一次才能进入新版更新协议。进入新版后,日常上游升级为后台一键完成。

如果仓库启用了 branch protection 且禁止 github-actions[bot] push,自动合并会失败,需要允许 GitHub Actions 写入目标分支,或后续改用 PR auto-merge 模式。如果你已经修改过源码、样式、工作流或部署配置,请不要使用后台一键更新,应自行通过 Git 合并上游代码并处理冲突。


⌨️ 快捷键

快捷键 操作
Space 播放 / 暂停
← / → 后退 / 快进 5 秒
Shift + ←/→ 上一曲 / 下一曲
L 切换歌词面板
Esc 关闭抽屉 / 弹层

输入框中自动让出快捷键。


🌍 部署

一键部署到以下平台(点击图标,Fork 后自动构建):

平台 一键部署
Vercel Deploy
Netlify Deploy
Cloudflare Pages Deploy to Cloudflare Pages

环境变量

部署后在平台 Dashboard 的 Settings → Environment Variables 中配置环境变量:

变量 必填 说明
GH_TOKEN ✅ 部署运行时使用的 GitHub Personal Access Token。Fine-grained token 需要 Contents: Read and write + Actions: Write; classic token 可使用 repo 权限。无需再复制到 GitHub Actions Secrets
GH_REPO 条件 仓库标识,owner/repo 格式。Vercel 开启 System Environment Variables 后会从 VERCEL_GIT_REPO_OWNER / VERCEL_GIT_REPO_SLUG 自动推导,其他平台需填写
CONFIG_ENCRYPTION_KEY ✅ 配置加密密钥,32 位以上随机字符串。配置加密、Cookie 签名与构建期公开配置生成都依赖它,GH_TOKEN 可独立轮换而不影响已加密配置
GH_BRANCH ❌ 目标分支。优先使用显式值,Vercel 可从 VERCEL_GIT_COMMIT_REF 自动推导,其余情况默认 main
GITHUB_PROXY ❌ GitHub 代理,必须是公网 HTTPS URL。用于检查更新和 workflow 内拉取上游代码;触发 workflow 与查询 Actions 状态仍需部署环境可访问 api.github.com
ADMIN_DISABLED ❌ 设为 true/1/yes/on(大小写不敏感)时禁用管理后台,/admin 显示“已禁用”,除状态探针外所有 /api/* 返回 403
DEVELOPMENT ❌ 设为 true/1/yes/on(大小写不敏感)时进入开发模式:配置与密码不持久化、加密走明文降级

生成 CONFIG_ENCRYPTION_KEY:node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

CONFIG_ENCRYPTION_KEY 需要同时提供给平台的构建环境和 Functions/运行时环境。构建期会用它解密 public/config.json,生成前端公开配置;如果仓库中已有密文配置但构建阶段缺少该变量,构建会失败以避免站点静默变成空配置。

GitHub Actions 验证固定读取 .github/ci-public-config.json,不会解密生产配置,因此不需要把 CONFIG_ENCRYPTION_KEY 复制到 GitHub Secrets。生产平台构建仍会严格要求真实密钥。

🎉 零配置密码

首次部署后访问 /admin,会自动进入 /setup 页面设置管理员密码——无需在环境变量中预设任何密码。

  • 密码:通过 /setup 页面设置,经 PBKDF2(600k 迭代)哈希后存储在仓库 public/admin.json,后续可在后台修改
  • Cookie 签名密钥:从 CONFIG_ENCRYPTION_KEY 运行时派生(HMAC-SHA256(密钥, "meliora-cookie-signing")),不落盘、不出现在任何文件/响应/日志中
  • 密钥强度校验:初始化时若 CONFIG_ENCRYPTION_KEY 未设置或过弱(< 32 位 / 常见弱密钥),/setup 页面会显示警告并拒绝初始化,提示用户在部署平台配置后再试
  • 先到先得:部署后谁先访问 /setup 谁设置密码,设置后 /setup 自动关闭

🔒 配置文件加密

管理后台保存的所有配置(站点信息、API Token、歌单、Umami / GA ID 等)在写入 GitHub 仓库时全文 AES-GCM 256 加密,仓库中只存储 base64 密文。构建期会从中生成公开播放器配置,但 apiToken 不会进入前端 bundle。播放器仅支持无需鉴权的公开 Meting API,不依赖管理边缘函数代理音源。启用远程歌单且填写 API Token 时,保存与连通测试都会明确拒绝;已有配置仍可读取,请在后台清空 Token 并更换为公开接口,或禁用相关歌单。不要把私密 Token 拼进公开 API 端点。服务端连通测试也不能替代浏览器的跨域访问验证。

  • 加密密钥:从 CONFIG_ENCRYPTION_KEY 用 PBKDF2(100k 迭代)派生,密钥本身不落盘、不出现在任何文件中
  • 密钥解耦:CONFIG_ENCRYPTION_KEY 专用于加密与签名,GH_TOKEN 仅用于 GitHub API 读写,两者独立——GH_TOKEN 可随时轮换而不影响已加密的配置
  • 加密范围:public/config.json(站点配置)和 public/admin.json(密码哈希)均为密文存储
  • 构建期公开配置:构建脚本解密并清洗站点公开配置后写入前端 bundle;直接访问仓库文件或 /admin.json 只能看到密文
  • 本地开发:DEVELOPMENT=true 时不加密,明文存内存,方便调试

各平台说明

Vercel

已包含 vercel.json,导入仓库后自动部署。

  • 框架:Vite(自动识别)
  • 构建命令:pnpm build
  • 输出目录:dist
  • 安装命令:pnpm install --frozen-lockfile(配置文件已指定)
  • 安全头(CSP / X-Content-Type-Options / X-Frame-Options / Referrer-Policy / Permissions-Policy)、Service Worker 缓存策略、静态资源 immutable 缓存、SPA fallback 均已在 vercel.json 配置
Netlify

已包含 netlify.toml,接入仓库后自动识别。

  • 构建命令:pnpm build(配置文件已指定)
  • 发布目录:dist(配置文件已指定)
  • 运行环境:Node 22 + pnpm 11.5.3(配置文件已指定)
  • 安全头、Service Worker 缓存策略、静态资源 immutable 缓存、SPA fallback 均已配置
Cloudflare Pages

已包含 wrangler.toml,可通过控制台导入或 wrangler pages deploy dist 部署。

  • 构建命令:pnpm build
  • 输出目录:dist
  • wrangler.toml 已设置 pages_build_output_dir = "dist"
  • 安全头、Service Worker 缓存策略、静态资源 immutable 缓存、SPA fallback 通过 public/_headers 与 public/_redirects 配置,构建时会复制到 dist

所有平台配置统一:构建命令 pnpm build、输出目录 dist,并保持安全头与缓存策略一致。Node 版本遵循 package.json 的 engines 要求,Netlify 额外在 netlify.toml 中固定构建环境版本。


🛠️ 开发

pnpm dev          # 开发服务器(前端)
pnpm dev:full     # 开发服务器(前端 + 后端模拟)
pnpm test         # 单元测试
pnpm type-check   # 类型检查
pnpm lint         # ESLint
pnpm format       # Prettier
pnpm build        # 生产构建

开发模式下可在设置中开启调试面板,查看实际高亮、基础/Small/标准版对比曲线、预加载队列、歌词、小窗、网络与内存采样, 并手动导出节拍对比 JSON。生产构建不提供调试入口。

本地配置同步

DEVELOPMENT=true 时,管理后台的配置与密码仍由本地后端以内存模式处理,重启后会重置。为了让主页保持与生产一致的“构建期公开配置”读取方式,Vite 开发服务器会在后台保存配置成功后,把配置同步写入 .meliora/config.local.json,并重新生成 src/generated/public-config.ts。

  • .meliora/ 已加入 .gitignore,仅用于本地调试。
  • 主页不会请求运行时配置接口,仍然只读取生成后的公开配置。
  • 重新执行 pnpm generate:public-config:dev 时,如果 .meliora/config.local.json 存在,会优先用它生成本地公开配置。
  • 要测试真实生产链路,请关闭 DEVELOPMENT,配置真实 GH_TOKEN / GH_REPO / CONFIG_ENCRYPTION_KEY,让后台写入仓库后再构建。

项目结构

src/
├── app/             应用装配与平台、服务实现接线
├── components/      共享 UI 组件(ConfirmModal / ToggleSwitch / Toast 等)
├── composables/     业务 hook(useAudioPlayer / usePlayerLibrary 等)
├── core/            平台无关的音频、歌词、分析、主题与纯函数工具
├── platform/        平台实现、设置存储与浏览器能力
│   └── web/         Web Audio、节拍分析、歌词小窗、全屏、PWA 等
├── stores/          Pinia 状态管理
├── services/        远程 IO 抽象(Meting API / 歌词)
├── router/          播放器、管理后台与 404 路由
├── config/          音乐与歌词运行时配置取用口
├── generated/       构建期生成的公开配置、版本与后台环境状态
├── views/           播放器与 404 页面
├── workers/         Web Worker(主题色提取、封面背景渲染)
├── admin/           管理后台(独立子应用)
│   ├── components/  后台 UI 组件
│   ├── views/       后台页面(Setup / Login / Dashboard / About / 配置迁移)
│   ├── composables/ 后台鉴权、暂存、更新状态与消息
│   ├── services/    后台 API 服务
│   └── utils/       CSRF 请求管理
├── tests/           前端单元与交互测试
└── styles/          全局样式与播放器页面的 scoped SCSS

shared/              前后端共享的配置类型、校验与规则
scripts/             构建期配置、版本与 Service Worker 生成脚本

server/              Edge Functions 后端
├── core/            核心逻辑(路由 / 鉴权 / 配置 / 上传)
└── tests/           后端测试

api/                 Vercel Edge Function 入口
functions/           Cloudflare Pages Function 入口
netlify/             Netlify Function 入口

提交时 Husky 会自动运行 lint-staged 与 commitlint。提交信息遵循 Conventional Commits。


🤝 贡献

欢迎一切形式的贡献。详情请看 CONTRIBUTING.md;代码风格与设计规范请看 agent.md。


🙏 致谢

歌词效果与内容来源

  • Apple Music-like Lyrics(AMLL):感谢作者与贡献者公开歌词渲染和动画实现,为 Meliora 的歌词效果提供参考。
  • AMLL TTML DB:感谢社区的逐词歌词制作、校对与维护者,以及 AMLL API 和镜像服务的维护者,让播放器能够获取更丰富的逐字歌词。
  • Meting 及兼容 API 的维护者:感谢远程歌单解析工具与接口服务,用于获取歌曲信息、播放地址、封面和普通歌词。
  • 网易云音乐 与 QQ 音乐:感谢音乐与歌词资源。Meliora 当前支持通过 Meting 解析这两个平台的公开歌单,并按歌曲 ID 获取网易云 YRC、QQ QRC 及可用的翻译与罗马音。
  • Robotxm / ESLyric-LyricsSource:QQ QRC 解码实现改编自该项目,保留原作者署名、GPL-3.0 许可及其对 LDDC 的上游致谢。
  • 感谢音乐创作者、歌词贡献者,以及提供本地或自托管音频、封面和歌词的用户。

开发支持

特别感谢 @OnyxAxisOwO 提供 Opus 5 与 Fable 5.1。

特别感谢 @L33Z22L11 提供 GPT 6 Astra。

本项目在开发过程中由多个 AI 模型参与协作,以下排名与贡献不分先后,包括但不限于:

  • GLM 5.2
  • GLM 5.3 Flash
  • Opus 5
  • Fable 5.1
  • GPT 5.5
  • GPT 5.6 Sol
  • GPT 6 Astra
  • Kimi K3

📄 开源许可

GNU Affero General Public License v3.0 or later © abloom25

Beat This! 模型与转换自上游的处理逻辑遵循 MIT 许可,作者、固定版本和转换说明见 模型署名与完整许可。

AGPL-3.0 要求任何修改后部署到公网的衍生版本必须向用户提供完整源代码。如需闭源商业使用,请联系作者协商授权。


如果这个项目对你有帮助,欢迎点亮 ⭐ Star

Made with ♥️ by abloom25

About

基于 Vue 3、TypeScript、Pinia 和 SCSS 的沉浸式单页音乐播放器。所有远程歌单和本地音乐会合并为一个匿名曲库,页面不会显示歌单名称、平台或来源。

Topics

Resources

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages