Skip to content

v0.29.0

Choose a tag to compare

@deltrivx deltrivx released this 30 Sep 15:24
· 6 commits to main since this release

ToneCore v0.29.0

修复歌词「提前跑完」:在线歌词改为按音频真实时长挑版本;顺带补齐曲库时长。

修复:歌词「提前跑完」

这个问题从 v0.26.0 就悬着,当时只测出了现象、没敢改。这次把根因链补齐了。

根因

  1. 在线歌词按歌名去搜,候选里混着翻唱 / 剪辑版;
  2. 旧逻辑是「遍历候选,取第一个有歌词的」—— 极易命中翻唱版;
  3. 翻唱版的时间轴与本地音频天然对不上。

实测数据(末行时间 ÷ 真实时长):

来源 曲目 比值 判定
online 黯然销魂 0.83 提前跑完
online 思念漫过海岸线 0.83 提前跑完
lrc-file / embedded 天堂岛之歌、要不然我们就这样一万年 0.91~0.94 正常
online 悬溺、三生三世 0.97~1.00 正常

跑偏的全部来自 online,这也解释了「只有个别歌正确」——
那些歌恰好命中了原版。

修法

fetchLyrics() 新增 targetDuration 参数:

  • 给了时长 → 收集全部候选的歌词,按「末行时间与音频长度的偏差」排序,取最优版本,
    而不是第一个碰巧有歌词的;
  • 偏差超过 25%(ratio < 0.75 或 > 1.35)→ 判定这批候选里没有匹配版本,宁可不用,也不把明显错位的歌词放上去;
  • 不传时长 → 退化为旧行为,兼容其它调用方。

LyricsService.probeDuration():用 music-metadata 读本地音频真实时长,
在走在线兜底前先取到,传给 fetchLyrics。

为什么不对本地来源做时长校验

同名 .lrc 与音频内嵌标签本就来自本地文件,时间轴应当可信。
给它们加校验只会让本可直接用的歌词被误弃 —— 所以校验只作用于在线兜底那一层。

变更:补齐曲库时长

上面那个修复需要一个前提:得知道音频的真实时长。而实测发现曲库 duration 全是 NULL。

原因是扫描入库时只顾着快速建索引,duration 直接写了 NULL。后果有两个:

  1. 界面时长一直显示 --:--;
  2. 歌词校验失去了参照(所以必须先修这个)。

新增 Library.backfillDurations(),在扫描后回填真实时长。要点:

  • 只处理 duration IS NULL 的行;
  • 解析失败保持 NULL,下轮扫描再试 —— 不写 0,否则 0 会被当成有效值而永远不再重试。

验证

npm run build     ✅ web + server 均通过
npm test          ✅ 15 项全过

需要你实测确认

这个修复依赖真实网络候选,本地没法自动断言,请在界面上验一首以前跑偏的歌(比如「黯然销魂」):

  1. 播放该曲 → 歌词应当跟着当前句走
  2. 若仍然错位,先看「歌词校准」里的偏移值是不是合理

如果有个别歌反而从正确变成没有歌词,说明这批候选里确实没有匹配版本(此时会返回空),
属于预期内的保守行为 —— 把歌名告诉我,我单独查。

待办

  • 酷我(kw)在线搜索封面:该平台不返回封面地址
  • 音源状态显示口径
  • 锁屏不显示动态歌词:Media Session API 不提供歌词接口,属浏览器能力边界,非 bug