用户端
落地页、登录注册、歌曲上传、生成主谱、阅读器、编辑器、曲库、账户中心和购买套餐入口。
Architecture Document
本项目是一个面向歌曲上传、AI 乐谱生成、歌词同步、自动分谱、线上曲库、额度计费和后台管理的单体 Node.js 应用。后端集中在 server.js,前端静态页面在 public/,AI 转谱与音频分析能力由 tools/ 下的 Python 脚本配合完成。
当前版本已经具备上传、生成、分谱、歌词、账户、套餐、后台、OSS、备份清理等能力。真实微信/支付宝回调、正式短信/邮件服务商、版权投诉闭环仍属于外部配置或后续扩展项。
落地页、登录注册、歌曲上传、生成主谱、阅读器、编辑器、曲库、账户中心和购买套餐入口。
Node.js 单体服务处理认证、任务队列、AI 调用、文件下载鉴权、OSS 同步、订单和后台管理。
用户、订单、额度、流水保存在 PostgreSQL;任务文件在本地共享存储,并按条件同步到 OSS。
请求从浏览器进入 Nginx/ECS,再到 Node 服务。Node 服务根据业务场景访问 PostgreSQL、OSS、本地 storage 和 Python AI 工具。
该项目没有拆成多个微服务,当前是“单体服务 + 后台任务 + 外部存储”的结构。优点是部署简单,后续可以把 AI Worker 单独拆出。
下面是当前实现中最重要的四条链路:注册登录、生成乐谱、线上曲库、付费下载。
jyi_session Cookie。storage/uploads。taskQueue。source.wav。source.wav 同步到 OSS。download_credits。核心代码集中在以下目录。storage/ 是运行时数据目录,部署脚本已排除它,防止发版覆盖线上数据。
当前后端没有拆文件,模块边界主要通过函数族体现。后续代码量继续增长时,建议按这些边界拆分。
| 模块 | 主要函数/文件 | 职责 | 后续拆分建议 |
|---|---|---|---|
| 认证与会话 | currentUser、createSession、sendEmailCode | 登录、注册、验证码、Cookie 会话。 | 拆成 auth.service.js |
| 任务队列 | enqueueTask、drainTaskQueue、processTask | AI 任务排队、状态、重试、进度。 | 拆成独立 Worker 或 BullMQ。 |
| AI 转谱 | tools/transcribe_score.py、tools/analyze_audio.py | 分析音频、生成主谱、导出文件。 | 独立 AI Worker 服务。 |
| 分谱 | startPartJob、generatePartScores、instrument_parts.py | 总谱拆分、乐器识别、声部 PDF/MIDI。 | 拆为 part-score 服务。 |
| 歌词 | readLyricsForTask、fetchOnlineLyrics、saveManualLyrics | 本地歌词、联网搜索、手动保存、时间轴建议。 | 增加歌词源适配器。 |
| OSS | uploadFileToOss、syncTaskArtifactsToOss、ossDownloadUrl | 上传任务产物、生成签名下载 URL。 | 拆成 storage adapter。 |
| 订单与额度 | createPlanOrder、markOrderPaid、consumeCredit | 套餐、订单、额度扣减、退款登记。 | 接入真实支付回调。 |
| 后台管理 | admin.js、/api/admin/* | 用户、邀请、订单、财务、曲库审核、系统监控。 | 增加筛选、分页、操作确认。 |
线上优先使用 PostgreSQL;开发环境可回退 SQLite。下表列出当前 schema 中的核心表。
| 表名 | 用途 | 关键字段 |
|---|---|---|
users | 用户基础数据。 | email、phone、role、status、password_hash |
invite_codes | 邀请码。 | code、order_id、max_uses、used_count、status |
purchase_requests | 购买邀请码申请。 | email、phone、note、status、order_id |
plans | 套餐和价格。 | price_cents、score_credits、enhanced_credits、download_credits |
invite_orders | 订单主表。 | order_no、user_id、plan_id、amount_cents、status |
payments | 支付记录。 | provider、provider_trade_no、status、paid_at |
ledger_entries | 财务流水。 | direction、amount_cents、memo |
refunds | 退款登记。 | order_id、amount_cents、status、reason |
user_quotas | 用户额度。 | score_credits、enhanced_credits、download_credits、task_quota |
usage_events | 额度使用事件。 | song_key、type、free、metadata_json |
user_entitlements | 套餐权益发放记录。 | order_id、plan_id、expires_at |
ai_tasks | AI 任务镜像。 | status、step、progress、metadata_json |
audit_logs | 后台审计日志。 | actor_user_id、action、target_type、detail_json |
除公开接口外,/api/*、/audio/*、/view/*、/download/* 默认要求登录。后台接口要求 super_admin。
| 方法 | 路径 | 权限 | 用途 | 主要参数/返回 |
|---|---|---|---|---|
| GET | /api/health | 公开 | 健康检查。 | 返回服务、队列、任务、内存、OSS/DB 状态。 |
| GET | /api/plans | 公开 | 套餐和价格。 | 返回活动价套餐、免费生成次数。 |
| GET | /api/auth/me | 公开 | 读取当前登录用户。 | 返回 user、admin、quota、entitlement。 |
| POST | /api/auth/email-code | 公开 | 发送邮箱验证码。 | body: email、purpose。 |
| POST | /api/auth/phone-code | 公开 | 发送手机验证码。 | body: phone、purpose。 |
| POST | /api/auth/register | 公开 | 注册并登录。 | body: email、phone、password、inviteCode、验证码、acceptTerms。 |
| POST | /api/auth/login | 公开 | 密码或验证码登录。 | body: login、password 或 code。 |
| POST | /api/auth/logout | 登录 | 退出登录。 | 清理 session cookie。 |
| PATCH | /api/auth/profile | 登录 | 更新昵称。 | body: name。 |
| POST | /api/auth/purchase-invite | 公开 | 提交购买邀请码申请。 | body: email、phone、note。 |
| POST | /api/auth/oauth/:provider | 公开 | 第三方登录预留。 | 当前返回 501,需要配置 OAuth。 |
| GET | /api/me/purchases | 登录 | 我的购买申请和订单。 | 返回 requests、orders。 |
| GET | /api/me/entitlements | 登录 | 我的额度权益。 | 返回 quota、订阅状态、最近生成次数。 |
| POST | /api/orders | 登录 | 创建套餐订单。 | body: planId;当前支付方式为 manual。 |
| PUT | /api/uploads?name=... | 登录 | 上传音频文件。 | 返回服务器本地 path、bytes。 |
| GET | /api/library | 登录 | 线上曲库。 | 返回已审核公开的无损 OSS 曲目。 |
| GET | /api/engines | 登录 | AI 环境检测。 | Basic Pitch、librosa、pretty_midi、music21、Demucs 等状态。 |
| GET | /api/tasks | 登录 | 任务历史。 | query: limit;返回任务摘要。 |
| POST | /api/tasks | 登录 | 创建 AI 转谱任务。 | body: path、mode;可能返回 402 需要额度。 |
| GET | /api/tasks/:id | 登录 | 读取任务详情。 | 返回任务、报告、输出文件。 |
| GET | /api/tasks/:id/preview | 登录 | 读取可编辑音符预览。 | 解析 MusicXML 返回 notes。 |
| GET | /api/tasks/:id/pages | 登录 | 生成/读取乐谱 SVG 页。 | 返回 pages。 |
| GET | /api/tasks/:id/layout | 登录 | 乐谱布局时间轴。 | 返回 measure/page layout。 |
| GET | /api/tasks/:id/lyrics | 登录 | 读取歌词。 | 同名 LRC/KRC、内嵌歌词、缓存歌词。 |
| POST | /api/tasks/:id/lyrics | 登录 | 保存手动歌词。 | body: text。 |
| POST | /api/tasks/:id/lyrics-search | 登录 | 联网搜索歌词。 | LRCLIB、酷狗等候选,保存缓存。 |
| GET | /api/tasks/:id/performers | 登录 | 读取/推断演唱者。 | 返回 performers。 |
| POST | /api/tasks/:id/no-vocals | 登录 | 生成去人声音轨。 | 优先复用 stem cache。 |
| POST | /api/tasks/:id/rerun | 登录 | 重新生成任务。 | body: mode;可能扣主谱/增强额度。 |
| POST | /api/tasks/:id/transpose | 登录 | 生成转调谱。 | body: semitones。 |
| GET | /api/tasks/:id/parts | 登录 | 读取分谱目录。 | 返回总谱、声部分谱、MIDI、排练音频。 |
| POST | /api/tasks/:id/parts | 登录 | 提交分谱任务。 | 进入 part job。 |
| GET | /api/tasks/:id/parts/job | 登录 | 读取分谱任务状态。 | 返回 progress、step、status。 |
| POST | /api/tasks/:id/sync | 登录 | 保存歌词/乐谱同步校准。 | body: lyricsOffsetMs、lyricsScale、scoreOffsetMs、scoreScale。 |
| GET | /audio/:id/source | 登录 | 播放源音频。 | 返回 audio stream。 |
| GET | /audio/:id/no-vocals | 登录 | 播放去人声音频。 | 返回 audio stream。 |
| GET | /view/:id/:file | 登录 | 在线预览谱面文件。 | 优先 OSS redirect。 |
| GET | /download/:id/:file | 登录 | 下载单个文件。 | 无损源音频会校验下载额度。 |
| GET | /download-all/:id | 登录 | 打包下载任务文件。 | 包含无损源音频时校验下载额度。 |
| GET | /api/admin/users | 超管 | 用户列表。 | 返回用户和额度摘要。 |
| PATCH | /api/admin/users/:id | 超管 | 调整用户角色/状态。 | body: role、status。 |
| POST | /api/admin/quotas/:userId | 超管 | 手动调整额度。 | body: scoreCredits、enhancedCredits、downloadCredits、taskQuota、reason。 |
| GET | /api/admin/invites | 超管 | 邀请码列表。 | 返回 invite codes。 |
| POST | /api/admin/invites | 超管 | 创建邀请码。 | body: note、maxUses、expiresAt。 |
| PATCH | /api/admin/invites/:id | 超管 | 启停邀请码。 | body: status、note。 |
| GET | /api/admin/purchase-requests | 超管 | 购买申请列表。 | 返回 requests。 |
| PATCH | /api/admin/purchase-requests/:id | 超管 | 审核购买申请。 | approved 会自动建单。 |
| GET | /api/admin/orders | 超管 | 订单列表。 | 返回订单和邀请码。 |
| POST | /api/admin/orders | 超管 | 手动建单。 | body: email、phone、planId、amountCents。 |
| POST | /api/admin/orders/:id/mark-paid | 超管 | 标记订单已支付。 | 发放额度、权益或邀请码。 |
| POST | /api/admin/orders/:id/refund | 超管 | 登记退款。 | body: amountCents、reason;写入 refunds 和 ledger。 |
| GET | /api/admin/library | 超管 | 线上曲库审核池。 | 返回无损已完成任务。 |
| POST | /api/admin/library/:id/publish | 超管 | 审核曲库公开状态。 | body: status=approved/rejected/pending。 |
| GET | /api/admin/finance | 超管 | 财务概览。 | summary、ledger、payments、refunds。 |
| GET | /api/admin/system | 超管 | 系统监控。 | 队列、任务、存储占用、集成状态、近期错误。 |
线上目录使用 release 切换模式,当前代码指向 /opt/jyi-ai-music-score/current,共享数据保存在 /opt/jyi-ai-music-score/shared。
本地执行 deploy/push-release.sh,脚本 rsync 到服务器 releases 目录,再由 release-switch.sh 切换 current 并重启服务。
jyi-score.service 托管 Node 服务,Nginx 负责域名和端口代理。
jyi-score-backup-postgres.timer 每天备份数据库;jyi-score-cleanup-storage.timer 每天清理缓存和异常任务。
/opt/jyi-ai-music-score/shared/backups/postgres。下面这些不是“页面没写”,而是需要外部配置、商户资料或更大工程拆分才能可靠上线。