fix(music): preserve track identity and normalize resource metadata

This commit is contained in:
jxxghp
2026-09-09 15:52:16 +08:00
parent ca01cceed1
commit 658cd4a9be
8 changed files with 2182 additions and 82 deletions

View File

@@ -0,0 +1,87 @@
# 音乐全流程审计(2026-09-09)
## 结论
普通分轨专辑和独立单曲已接入通用搜索、订阅、下载、整理、刮削及媒体库刷新流程。
这不等于任意音乐资源都可以无人值守处理:整轨音频加 CUE、SACD ISO、多专辑全集、
演唱会视频,以及上游没有收录或缺少可靠署名的资源,仍有明确边界。
本轮基于后端 `ca01cceed13ff0060de22b733eb0fef08003e840` 和前端 `e5de69f4` 审查。
没有向真实下载器添加任务,也没有修改生产数据库或媒体库。实站请求只获取音乐列表;
识别请求使用公共 MusicBrainz 接口,单元测试全部使用隔离数据。
## 链路与边界
| 阶段 | 当前行为 | 需要保留的约束 |
| --- | --- | --- |
| 元数据搜索 | 前端专辑、单曲入口和 `useMediaSubscribe` 传递统一来源、ID、实体类型 | Recording 和 Release Group 不能互换;艺术家不能直接订阅 |
| 站点搜索 | `SearchMusicOwner` 生成标题、艺人及可信别名关键词;`match_music_resource` 核对名称、署名、分类和版本 | 缺艺术家、不同版本、关联专辑只能作为候选;单曲在专辑中的存在不是独立单曲资源 |
| 订阅 | 主动搜索与 RSS 均保留目标身份、暂停/取消状态和音质规则 | 专辑需有总曲目数;远端暂不可用时恢复已保存的订阅快照 |
| 下载 | 下载前解析种子文件清单,按盘号/曲序或曲名去重;专辑达到预期数量后才标记覆盖 | 这是文件清单层的覆盖确认,不是逐曲声纹验证;没有文件清单或曲目数未知不能确认整专 |
| 完成判定 | 专辑订阅消费下载层的 `confirmed_full_coverage`,单曲按成功添加下载任务处理 | “订阅完成”代表已提交符合条件的下载,不代表下载完成、整理成功和媒体库刷新完成 |
| 整理 | 恢复下载历史中的音乐上下文,保留逐曲标签/文件名;本地目录可按曲序、曲名、时长匹配发行版 | 路径不可读时不能假定读到了标签;不能把整张专辑的标题和单曲 ID 复制给每个文件 |
| 文件识别 | 指纹、标签、文件名分层识别,目录级匹配作为补充 | 需要可读取的音频、可用的指纹工具/服务及上游条目;失败时的本地展示对象不是远端识别成功 |
| 刮削 | 各文件独立处理标签、封面和歌词,沿用统一存储与事件流程 | 单曲 ID 不适用于整目录;歌词缺失或请求预算耗尽不代表音频整理失败 |
整轨+CUE 不会被自动拆成多首独立音轨;ISO 不属于普通可写标签音频。
多专辑合集无法仅凭种子主标题绑定成一个正确专辑,曲目数量也不能证明每首音频内容正确。
经典音乐的作曲家与演奏者署名、非官方译名、拼音全集命名需要额外可靠证据,不能靠放宽
艺术家/版本匹配来制造命中。
## 本轮修复
1. 专辑刮削合并曾将 Release Group ID 放入 `MetaMusic.media_id`,标签写入随后把它当作
`musicbrainz_trackid`。现在只保留文件自身的单曲身份,缺失时不以专辑 ID 补位。
验证覆盖“原本没有单曲 ID”和“已有有效单曲 ID”,并用真实 FLAC 完成写入、刮削、重读。
2. 明确的客串署名和影视主题曲/插曲注释不再阻断同一作品匹配。客串必须由候选署名确认;
Live、Remix、未知括号副标题和错误艺术家仍然被拒绝。
3. 标准 `CD - [WAV整轨+CUE] - 位深 - 采样率 - {厂牌目录} - 发布者` 尾链不再污染
专辑名;保留原始资源标题、年份和音质。副标题中的 `丨` 与普通竖线统一处理,避免把厂牌误识别为艺人。
4. 更新批量工具:保留主副标题,复用生产模块入口,移除已失效的私有参数;没有远端 ID 的
展示兜底不计命中。凭据按生产库注册域规则查询,避免 `pt.` 子域导致假报缺少 Cookie。
采样与识别可单独执行,运行配置隔离,分页失败保留已采数据。
## 可复用采样方式
在仓库虚拟环境中执行。数据库通过 SQLite 只读 URI 打开,Cookie 不写入报告。
默认数据库是本机 `~/Documents/moviepilot/user.db`,站点规则来自同工作区的
`MoviePilot-Build/sites/private`。可通过环境变量 `PROXY_HOST` 提供必要的访问代理。
```bash
.venv/bin/python scripts/music_recognize_batch_test.py --fetch-only --pages 1
.venv/bin/python scripts/music_recognize_batch_test.py --limit 30 --music-type album
.venv/bin/python scripts/music_recognize_batch_test.py --limit 30 --music-type recording
```
TSV 样本和 CSV 报告保存在 `config/temp/`,兼容旧版纯标题和两列 TSV。
复用资源列表只免去再次访问站点,识别仍会请求 MusicBrainz;这不是离线测试命令。
不指定实体时的“命中”只是模块返回远端候选,需额外检查实体、艺人和版本,不能作为准确率。
本次本地采样、公共响应录制、前后回放及完整检查日志保存在工作区
`.artifacts/music-audit-20260909/`。这些原始实站数据和运行状态不作为产品源码提交。
## 已确认的实站结果
只读采样得到 7 个站点的 206 条资源,保留主副标题。对全部样本运行修改前后的
离线解析:修正 `Jay` 的抓轨尾链,以及 `Duo Improbabile` 资源中被误作艺人的厂牌字段;
其余 204 条的名称、艺人、专辑、年份和格式字段未改变。这不是 206 条全部识别正确的声明。
`李佳薇 - 碧苍 (电视剧《与凤行》“碧海苍穹”主题曲)` 的真实 MusicBrainz 响应已保存为
`tests/fixtures/music_lifecycle_recording.json`。相同响应在基线的单曲模式无命中,修复后同步和
异步入口都命中 Recording `b64cad55-4c77-49cc-964a-fc3aaee5fa15`,无需回退到同名专辑。
该回归严格重放已录制请求,不访问外部服务。
元数据对照选择 29 条跨站点音频资源。MusicBrainz 连续返回 503 后停止新增请求,按同一份
公共响应记录离线回放,只有 16 条具备修改前后所需的完整响应。两版均有 10/16 条返回
远端候选,**本轮没有证明总体命中率上升**;已证明的是一条单曲身份纠正及两条解析字段修正。
其余 13 条包含网络失败、中断后尚未查询和修复后需要新查询的样本,统一标为不可评估,
没有计作识别失败或成功。复杂古典署名、英文译名括号、无分隔拼音全集等仍有未解决样本。
检查包括后端全量测试、音乐专项回归、前端 5 个音乐相关测试文件(87 项)、架构策略和
宿主快照、类型检查、复杂度、并发/异步/任务所有权/服务定位器/Ruff/Mypy 门禁,以及启动性能。
复杂度检查曾因刮削类注释净增一行触及既有上限而失败,已调整注释后通过,没有修改任何基线。
两个生成的真实 FLAC 文件已完成标签写入、专辑刮削和重新读取验证。
后端全量检查为 **9012 通过、9 跳过**;追加实站录制与双引擎回归后的音乐专项检查为
**822 通过**,其中本轮新增回归 20 项。前端为 **87 通过**,架构策略为 **165 通过**,
变更 Python 文件 Pylint 为 **10/10**,其余适用门禁通过。