网络元数据补全
网络元数据是「弱补全」。它不是第二个 metadata reader,也不能替代嵌入标签、sidecar 文件、文件夹结构或手动编辑。
网上搜到的歌名、封面怎么进曲库、怎么打分、什么时候能自动填、什么时候必须等人确认。一句话:暂时读不到 ≠ 真的没有。
曲目会持久化明确的就绪状态:
embedded_metadata_status:pending、reading、present、missing、errorembedded_cover_status:pending、reading、present、missing、errornetwork_metadata_status:none、pending、candidate_found、applied_missing_only、rejected、error
pending 和 reading 表示「还没读完」,不是「缺失」。网络补全不能把空字段、兜底显示值或缺失封面 id 当成「嵌入数据不存在」的证据。
阶段 A:本地 Metadata 读取
FileScanner发现文件。MetadataReader读嵌入标签,把嵌入 metadata 标成present、missing或error。CoverExtractor读嵌入/文件夹封面,把嵌入封面标成present、missing或error。- 本地 reader 跑完后才写
tracks和covers。
阶段 B:本地收尾
- 从本地行做专辑分组和艺术家刷新。
- 曲目和专辑立即可用。
- UI 不被网络补全卡住。
阶段 C:网络补全
- 只能手动触发。
- Provider 结果先进候选表。
- 高置信候选可以只填缺失字段。
- 低置信候选留着给人审。
- 被拒绝的候选会记下来,以后不再提示。
网络 metadata 候选在 network_metadata_candidates。
网络决策在 network_metadata_decisions,带 applied_fields_json,每条接受/拒绝/忽略都可审计。
网络封面候选在 network_cover_candidates。网络封面 URL 永远不会直接当 artwork 返回给 Renderer。接受的封面必须走封面缓存管线,变成本地 thumb、album、large 文件,由 covers 引用。
Metadata 优先级:
- manual
- embedded
- sidecar/info
- folder_structure
- network
- filename_fallback
网络只能写 title、artist、album、albumArtist、year、genre、trackNo、discNo,且必须同时满足:
embedded_metadata_status是missing或error- 候选分数至少
0.92才能自动 missing-only 应用 - 现有字段来源是
unknown、filename_fallback或network
网络不能覆盖 manual、embedded、sidecar 或 folder_structure。
文件名兜底不能覆盖 manual、embedded、sidecar、folder_structure 或 network。
封面优先级:
- manual
- embedded
- folder/front/cover
- network
- default
网络封面只能在这些条件下应用:
embedded_cover_status是missing或error- 当前封面来源是
default - 分数至少
0.92
网络封面永远不覆盖 manual、embedded 或 folder 封面。
matchScore.ts 里标题和艺术家权重最高,专辑中高,时长权重也很大。时长差超过 10 秒会把分数压到自动应用线以下。标题或艺术家相似度弱的话,候选到不了高置信。
阈值:
score >= 0.92:可以自动applyMissingOnly0.75 <= score < 0.92:可见候选,要用户确认score < 0.75:过滤掉或当低优先级
Providers
Section titled “Providers”Provider 边界是 NetworkMetadataProvider。
当前第一版 providers:
MockMetadataProvider:架构和测试NeteaseCloudMusicProvider:大陆友好的 metadata 候选QQMusicProvider:大陆友好的 metadata 和专辑封面 URL 候选MusicBrainzProvider:metadata 候选CoverArtArchiveProvider:封面边界占位
Providers 不会接进 MetadataReader。它们在 NetworkMetadataService 和 NetworkMetadataJobQueue 后面跑,并发最多 2,带超时、候选存储和失败隔离。
为什么能避开旧 ECHO 的坑
Section titled “为什么能避开旧 ECHO 的坑”旧 ECHO 可能还没读到嵌入标题/艺术家/封面,就假定没有,让文件名猜测或网络数据赢了。ECHO Next 把「就绪状态」和「字段值」分开存:
- 本地读取完成前,状态是
pending或reading。 - 嵌入 metadata 还在
pending或reading时,网络合并拒绝写 metadata。 - 嵌入封面还在
pending或reading时,网络合并拒绝写封面。 - 嵌入数据一旦
present,受保护字段来源会挡住网络覆盖。 - 只有确认
missing或 readererror才打开 missing-only 网络路径。
核心规则就一句:「暂时不可用」不等于「缺失」。别急着用网上的信息去猜你的歌。