4.6 KiB
4.6 KiB
Netease-sync 需求文档
项目概述
在当前目录下新建一个简单的 Node.js 项目,实现和 Navidrome 的联动,将网易云音乐歌单同步到 Navidrome。
核心功能
1. 歌单输入
- 前台页面支持输入网易云音乐的歌单 ID 或分享链接
- 支持从歌单 URL 中提取 ID(如
https://music.163.com/#/playlist?id=123456提取123456) - 只支持网易云音乐平台
2. 歌单读取
- 调用 TuneHub API 获取歌单详情
- API:
GET /api/?source=netease&id={playlistId}&type=playlist - 获取歌单名称、封面、描述、歌曲列表等元数据
3. 歌曲下载
- 调用现有的 sync-server 下载逻辑
- 包括元数据写入(title, artist, album, cover)
- 不创建歌单缓存 JSON 文件,避免和主 app 混淆
- 下载到 sync-server 的 music 目录(Navidrome 也读取此目录)
- 如果下载失败,尝试换源(根据 api.md 支持的平台:netease, kuwo, qq)
- 不重试,失败则跳过
4. Navidrome 歌单创建
- 使用 Navidrome 的 Subsonic API
- 在 Navidrome 中创建同名歌单
- 将下载的歌曲加入歌单
- 同步歌单的所有元数据(封面、描述等)
5. 同步策略
- 增量同步:只新增歌曲,不删除已有歌曲
- 通过网易云音乐歌曲 ID 判断,在本地维护一个映射表(netease_song_id -> navidrome_song_id)
- 定时同步:每 300 秒自动同步一次(可配置)
- 支持手动立即同步
6. 前端界面
- 显示已添加的歌单列表
- 显示每个歌单的同步状态(同步中/成功/失败)
- 显示上次同步时间
- 提供立即同步按钮
- 支持添加/删除歌单
配置项
Docker 环境变量
NAVIDROME_URL: Navidrome 服务器地址(如http://navidrome:4533)NAVIDROME_USERNAME: Navidrome 用户名NAVIDROME_PASSWORD: Navidrome 密码SYNC_INTERVAL: 同步间隔(秒),默认 300SYNC_SERVER_URL: sync-server 地址(如http://sync-service:3001)SYNC_SERVER_TOKEN: sync-server 的 token(用于 KV API)TUNEHUB_API_URL: TuneHub API 地址(如https://music-dl.sayqz.com)
技术架构
后端
- Node.js + Express
- 调用 sync-server 的 KV API 传递歌曲列表
- 调用 Navidrome Subsonic API 创建歌单
- 定时任务:每 N 秒检查并同步歌单
- 数据持久化:JSON 文件存储歌单列表和映射表
前端
- 简单的 HTML + JavaScript 页面
- 实时显示同步状态(WebSocket 或轮询)
- 添加/删除歌单功能
Subsonic API 集成
认证
所有 API 请求需要包含以下参数:
u: 用户名p: 密码(明文或 hex 格式)v: API 版本(如1.16.0)c: 客户端名称(如netease-sync)
主要端点
-
创建歌单:
createPlaylist- 参数:
name(歌单名称)、songId(歌曲 ID 列表,逗号分隔) - 返回:创建的歌单 ID
- 参数:
-
更新歌单:
updatePlaylist- 参数:
playlistId(歌单 ID)、songIdToAdd(要添加的歌曲 ID)
- 参数:
-
获取歌单列表:
getPlaylists -
搜索歌曲:
search3- 参数:
query(搜索关键词) - 用于根据文件名查找 Navidrome 中的歌曲 ID
- 参数:
歌曲匹配策略
参考 sync-server 的去重逻辑,文件名格式为:Artist - Name [source_id].ext
匹配步骤:
- 下载完成后,Navidrome 会自动扫描新歌曲
- 通过
search3搜索文件名(如Artist - Name [netease_id])来获取 Navidrome 的歌曲 ID - 将网易云音乐歌曲 ID 映射到 Navidrome 歌曲 ID
数据结构
歌单列表 (playlists.json)
{
"playlists": [
{
"id": "netease_123456",
"neteaseId": "123456",
"name": "歌单名称",
"cover": "封面URL",
"description": "歌单描述",
"navidromePlaylistId": "navidrome_playlist_id",
"lastSyncTime": "2025-01-12T10:00:00Z",
"syncStatus": "success",
"songMapping": {
"netease_song_id_1": "navidrome_song_id_1",
"netease_song_id_2": "navidrome_song_id_2"
}
}
]
}
换源逻辑
如果网易云音乐下载失败,尝试换源:
- 优先级:kuwo -> qq
- 每个平台只尝试一次,不重试
错误处理
- 某首歌下载失败,跳过继续下载其他歌曲
- 不重试
- 错误日志输出到 Docker 控制台,不存储
Navidrome 扫描延迟
- Navidrome 扫描新歌曲很快,不处理延迟
- 在添加到歌单时直接搜索歌曲 ID