Files
musicdl-catalog-sync-suite/Music_Server/docs/superpowers/specs/2026-04-19-musicfree-music-server-plugin-design.md

9.9 KiB
Raw Permalink Blame History

MusicFree Pure Music_Server Plugin Design

日期:2026-04-19 状态:已确认设计,待实现计划 范围:Music_Server 榜单详情接口补齐、MusicFreeMusic_Server 插件、旧插件兼容壳

1. 背景

当前 Music_Server 已经提供这些面向 MusicFree 的能力:

  • GET /mf/v1/recommend/tags
  • GET /mf/v1/recommend/sheets
  • GET /mf/v1/playlists/{id}
  • GET /mf/v1/playlists/{id}/tracks
  • GET /mf/v1/toplists
  • GET /mf/v1/search/songs
  • POST /mf/v1/media/resolve

同时,当前 MusicFree 使用的 netease_17000.js 仍然是旧的网易 relay 风格插件,内部直接调用旧服务端接口,并带有与本轮目标无关的能力:

  • album 搜索与详情
  • artist 搜索与作品
  • lyric
  • importMusicSheet
  • 旧的网易与 relay 回退逻辑

本轮要把插件收敛成“纯 Music_Server 插件”,并把服务端缺失的榜单详情链路补齐,使 MusicFree 可以完整走“搜歌、看歌单、看榜单、播放”这一条自有服务链路。

2. 目标

本轮目标:

  • Music_Server 补齐榜单详情与榜单歌曲分页接口
  • MusicFree 新增正式插件 music_server.js
  • 旧插件 netease_17000.js 保留为兼容壳,转发到新插件
  • 插件只依赖 Music_Server,不再直连旧网易 relay 或其他平台
  • 插件能力只保留当前服务端已支持的:
    • music 搜索
    • 推荐歌单
    • 歌单详情
    • 榜单列表与榜单详情
    • 播放解析

非目标:

  • 不做 album 搜索或专辑详情
  • 不做 artist 搜索或歌手作品页
  • 不做 lyric
  • 不做 importMusicSheet
  • 不做插件侧多平台回退
  • 不做插件直连网易、QQ、酷我等外部平台

3. 总体设计

采用“两端各补一小段”的方式完成:

  1. Music_Server

    • 保持现有 /mf/v1/* 结构不变
    • 新增榜单详情与榜单歌曲接口
    • 返回结构与歌单详情链路保持一致
  2. MusicFree 插件

    • 新增正式插件文件 music_server.js
    • 旧文件 netease_17000.js 退化为兼容壳
    • 所有方法仅调用 Music_Server
    • 仅负责请求与字段映射,不承担内容回源逻辑

这样做的原则是:

  • 服务端负责内容真相与业务契约
  • 插件只负责协议适配
  • 旧入口兼容,新入口语义清晰

4. Music_Server 设计

4.1 数据模型现状

catalog_read.db 现有导出脚本 export_catalog_read.py 已经包含:

  • catalog_toplists
  • catalog_toplist_tracks

因此本轮不需要改读模型导出结构,只需要把现有数据通过读取层和路由层暴露出来。

4.2 读取层补齐

catalog_reader.py 中新增两个能力:

  • get_toplist(toplist_id: str) -> ToplistRow | None
  • list_toplist_tracks(toplist_id: str, page: int, page_size: int) -> list[PlaylistTrackRow]

约束:

  • get_toplist()catalog_toplists 取单条
  • list_toplist_tracks()catalog_toplist_tracks 联结 catalog_tracks
  • 排序按 position asc
  • 返回的歌曲对象字段与 list_playlist_tracks() 保持一致:
    • song_id
    • name
    • singers
    • album
    • cover_url
    • duration_ms

4.3 路由层补齐

mf_catalog.py 中新增:

  • GET /mf/v1/toplists/{toplist_id}
  • GET /mf/v1/toplists/{toplist_id}/tracks?page=&page_size=

返回约束:

  • /mf/v1/toplists/{toplist_id}

    • 返回对象 shape 与 /mf/v1/playlists/{playlist_id} 一致
    • id 使用 catalogsync:toplist:{toplist_id}
    • platform 固定返回 catalogsync
  • /mf/v1/toplists/{toplist_id}/tracks

    • 返回对象 shape 与 /mf/v1/playlists/{playlist_id}/tracks 一致
    • 返回:
      • isEnd
      • musicList

错误语义:

  • 找不到榜单:404
  • 缺少或错误 Bearer Token401
  • 空榜单:200musicList: []

4.4 与现有接口的关系

本轮不改这些接口的既有行为:

  • GET /mf/v1/recommend/tags
  • GET /mf/v1/recommend/sheets
  • GET /mf/v1/playlists/{id}
  • GET /mf/v1/playlists/{id}/tracks
  • GET /mf/v1/toplists
  • GET /mf/v1/search/songs
  • POST /mf/v1/media/resolve

也不改导出脚本中的歌单、歌曲、文件位置逻辑。

5. MusicFree 插件设计

5.1 文件布局

插件文件放在 D:\source\MusicFree\keep-alive-master\Music_Free

本轮交付:

处理方式:

  • music_server.js 作为正式插件文件
  • netease_17000.js 只保留一层兼容壳:
    • module.exports = require("./music_server")

这样既保留旧入口,又让正式插件名称与实际能力一致。

5.2 插件元数据

建议插件元数据固定为:

  • platform: "Music_Server"
  • version: 本轮实现版本
  • author: 保留现有项目惯例
  • supportedSearchType: ["music"]

userVariables 只保留:

  • baseUrl
  • accessToken

规则:

  • baseUrl 指向 Music_Server 部署地址
  • accessToken 指向 Music_Server Bearer Token
  • 插件不内置 NAS 地址、旧 relay 地址或其他平台地址

5.3 请求层规则

插件请求层保持极薄:

  • 所有 JSON 业务请求带:
    • Authorization: Bearer <accessToken>
  • baseUrl 统一去掉尾部斜杠
  • 不在插件内保存本地数据库或缓存目录
  • 不做多平台搜索与回退

media/resolve 特殊规则:

  • stream.url 是相对路径,例如 /mf/v1/media/stream/...
    • 插件自动拼接为 ${baseUrl}${url}
  • stream.url 已是绝对地址
    • 直接原样使用

5.4 插件能力映射

插件仅实现并暴露这些方法:

  • search(query, page, "music")
    • 对应 GET /mf/v1/search/songs
  • getRecommendSheetTags()
    • 对应 GET /mf/v1/recommend/tags
  • getRecommendSheetsByTag(tag, page)
    • 对应 GET /mf/v1/recommend/sheets
  • getMusicSheetInfo(sheetItem, page)
    • 对应:
      • GET /mf/v1/playlists/{id}
      • GET /mf/v1/playlists/{id}/tracks
  • getTopLists()
    • 对应 GET /mf/v1/toplists
  • getTopListDetail(topListItem, page)
    • 对应:
      • GET /mf/v1/toplists/{id}
      • GET /mf/v1/toplists/{id}/tracks
  • getMediaSource(musicItem, quality)
    • 对应 POST /mf/v1/media/resolve

不再实现:

  • album
  • artist
  • lyric
  • importMusicSheet

5.5 稳定 ID 规则

插件与服务端之间继续使用稳定 public id:

  • 歌单:catalogsync:playlist:{playlist_id}
  • 榜单:catalogsync:toplist:{toplist_id}
  • 歌曲:catalogsync:song:{song_id}

插件只负责从 public id 解析出最后一段真实 id,然后发给服务端路由。

6. 字段映射

6.1 歌单与榜单对象

服务端返回的歌单、榜单对象直接映射成 MusicFree 的 sheetItem / topListItem 风格对象,核心字段统一为:

  • id
  • platform
  • title
  • coverImg
  • description
  • worksNum
  • playCount

6.2 歌曲对象

服务端返回的 musicItem 直接映射,核心字段:

  • id
  • platform
  • title
  • artist
  • album
  • artwork
  • duration

6.3 播放源对象

getMediaSource() 返回:

  • url
  • headers
  • quality

其中:

  • headers 来自服务端 stream.headers
  • quality 优先取服务端 selected_source.quality

7. 错误处理

7.1 插件配置错误

baseUrlaccessToken 为空:

  • 插件直接抛出明确错误
  • 不做隐式默认值兜底
  • 不静默退回旧服务

7.2 浏览型接口错误

对于这些接口:

  • 搜歌
  • 推荐歌单
  • 榜单列表

如果请求失败:

  • 插件返回空结果
  • 同时保留清晰错误信息,方便调试

7.3 详情接口错误

对于:

  • getMusicSheetInfo
  • getTopListDetail

若详情页或 tracks 请求失败:

  • 不伪造旧平台数据
  • 返回空 musicList
  • 第 1 页如果头信息获取失败,不补假数据

7.4 播放解析错误

/mf/v1/media/resolve 失败或无可播放地址:

  • getMediaSource() 返回 null
  • 不回退到旧网易、QQ、酷我逻辑

8. 测试设计

8.1 Music_Server 测试

Music_Server 仓库补这些测试:

  • CatalogReader
    • get_toplist()
    • list_toplist_tracks()
  • mf_catalog 路由
    • GET /mf/v1/toplists/{id}
    • GET /mf/v1/toplists/{id}/tracks

重点覆盖:

  • 正常返回 shape
  • 第 1 页与末页 isEnd
  • 404
  • 401

8.2 MusicFree 插件测试

MusicFree 仓库新增独立测试,测试目标是 music_server.js,不再复用旧 netease_17000.test.js 的网易 fallback 语义。

重点覆盖:

  • userVariables 只有 baseUrlaccessToken
  • supportedSearchType 只有 music
  • 搜歌走 /mf/v1/search/songs
  • 歌单详情走 /mf/v1/playlists/*
  • 榜单详情走 /mf/v1/toplists/*
  • getMediaSource() 正确处理相对流地址与绝对流地址
  • netease_17000.js 兼容壳导出与 music_server.js 相同插件对象

9. 验收标准

联调通过标准:

  • MusicFree 能搜歌
  • 能看推荐歌单
  • 能点进歌单并加载歌曲列表
  • 能看榜单列表
  • 能点进榜单并加载歌曲列表
  • 能播放 Music_Server 返回的流地址
  • 插件逻辑不再依赖旧网易 relay 搜索或播放路径

10. 实施边界

代码边界保持如下:

  • Music_Server 服务端代码只改 D:\source\musicdl-catalog-sync-worktrees\Music_Server
  • MusicFree 插件代码只改 D:\source\MusicFree\keep-alive-master\Music_Free
  • 不回到 D:\source\musicdl 老仓库实现服务逻辑

本 spec 只覆盖“纯 Music_Server 插件 + 服务端榜单详情补齐”这一小段工作,后续若要继续扩充 albumartistlyric,需要新 spec 或新实现计划单独推进。