feat: 添加网易云音乐同步到Navidrome的功能

新增NetEase-sync模块,实现将网易云音乐歌单同步到Navidrome的功能
修复iOS设备自动播放问题,优化播放器体验
This commit is contained in:
史悦
2026-01-12 17:59:31 +08:00
parent 4ea05279bd
commit 89a28e1bc5
7 changed files with 1196 additions and 22 deletions

141
Netease-sync/需求.md Normal file
View File

@@ -0,0 +1,141 @@
# 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`: 同步间隔(秒),默认 300
- `SYNC_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`
### 主要端点
1. **创建歌单**: `createPlaylist`
- 参数:`name`(歌单名称)、`songId`(歌曲 ID 列表,逗号分隔)
- 返回:创建的歌单 ID
2. **更新歌单**: `updatePlaylist`
- 参数:`playlistId`(歌单 ID`songIdToAdd`(要添加的歌曲 ID
3. **获取歌单列表**: `getPlaylists`
4. **搜索歌曲**: `search3`
- 参数:`query`(搜索关键词)
- 用于根据文件名查找 Navidrome 中的歌曲 ID
## 歌曲匹配策略
参考 sync-server 的去重逻辑,文件名格式为:`Artist - Name [source_id].ext`
匹配步骤:
1. 下载完成后Navidrome 会自动扫描新歌曲
2. 通过 `search3` 搜索文件名(如 `Artist - Name [netease_id]`)来获取 Navidrome 的歌曲 ID
3. 将网易云音乐歌曲 ID 映射到 Navidrome 歌曲 ID
## 数据结构
### 歌单列表 (playlists.json)
```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