移除中间态渲染 ( LyricManager.ts ) - 在 handleOnlineLyric 方法的 adoptQQMusic 流程中,移除了提前调用的 setFinalLyric 。 - 原逻辑 :获取到 QQ 音乐歌词 -> 排除处理 -> 立即显示 -> 返回上层 -> 上层再次处理 -> 再次显示 (导致抖动)。 - 新逻辑 :获取到 QQ 音乐歌词 -> 填充数据 -> 返回上层 -> 统一排除处理 -> 最终显示 (仅一次渲染)。#841
Conversation
- 重构时间解析函数,使用纯数学运算替代字符串操作以提高性能 - 移除全局正则表达式,改为在函数内局部使用避免状态污染 - 在解析过程中直接计算结束时间,消除二次遍历 - 优化歌词对齐算法,使用双指针实现 O(N) 复杂度 - 改进 QRC 格式解析,提前编译正则并优化 XML 内容提取 - 统一默认单词持续时间处理逻辑
- 在 DownloadManager 中添加 removeDownload 方法,支持从队列和 store 中移除任务 - 修复下载页面中播放全部按钮的逻辑,仅对已下载歌曲生效 - 优化下载中页面的封面显示逻辑,统一使用 getCover 方法 - 将 handleRemoveDownload 的参数类型扩展为 number | string 以支持多种 ID 类型
- 使用字符串补齐替代浮点数计算,避免时间解析的精度误差 - 将 alignLyrics 改为纯函数,不再修改输入数组 - 引入 XmlNode 辅助类重构 TTML 生成逻辑,提高可读性 - 优化 QRC 内容提取的正则表达式,增强健壮性
将 QRC 歌词解析中的 LyricContent 提取逻辑重构为策略模式,根据运行环境自动选择 DOM 或正则解析器,提高代码可维护性和跨环境兼容性。
- 导出 `getThemeFromColor` 工具函数用于颜色主题计算 - 新增 IPC 通信通道传递主题色数据 - 在任务栏歌词组件中根据主题色动态调整文本颜色 - 监听主题相关设置变化并实时更新任务栏歌词颜色
在设置中添加“任务栏歌词跟随主题色”选项,允许用户控制任务栏歌词颜色是否与应用主题同步。当关闭时,歌词将恢复为默认颜色。
使用Data URL替代Blob URL存储音乐封面,避免跨窗口或跨进程引用失效导致的封面闪烁和消失问题。移除对BlobURLManager的依赖,简化封面处理逻辑。
在任务栏歌词组件中添加设置选项,允许用户控制是否显示翻译歌词和罗马音歌词。通过 IPC 将设置同步到主进程,确保前后端状态一致。
当读取操作被中止时,未处理onabort事件可能导致Promise永远挂起。 添加onabort事件处理器来拒绝Promise,确保异常情况能被正确处理。
添加 Windows 和 macOS/Linux 系统的条件步骤,用于在 .env 文件不存在时从 .env.example 复制。这确保了 nightly 构建在不同操作系统上都能正确加载环境配置。
- 在 handleOnlineLyric 方法的 adoptQQMusic 流程中,移除了提前调用的 setFinalLyric 。 - 原逻辑 :获取到 QQ 音乐歌词 -> 排除处理 -> 立即显示 -> 返回上层 -> 上层再次处理 -> 再次显示 (导致抖动)。 - 新逻辑 :获取到 QQ 音乐歌词 -> 填充数据 -> 返回上层 -> 统一排除处理 -> 最终显示 (仅一次渲染)。
新增配置选项允许在当前歌曲播放时提前下载并缓存下一首歌曲的歌词,以提升歌词切换的流畅度。重构了歌词获取逻辑,将核心的在线歌词获取方法提取为独立函数,便于预加载功能复用。
- 在任务栏歌词组件中新增动态封面显示功能 - 添加动态封面获取逻辑,根据设置自动获取并更新 - 扩展 IPC 接口以支持动态封面数据传输 - 在音乐存储中增加动态封面状态管理
Summary of ChangesHello @kazukokawagawa, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求致力于提升歌词显示与管理系统,引入了多项新功能并优化了用户体验和性能。它通过集中化最终歌词渲染来解决歌词闪烁问题,新增了预加载下一首歌曲歌词的设置,并集成了动态封面支持。此外,任务栏歌词的自定义选项也得到了扩展,包括主题色同步以及对翻译和音译歌词显示更精细的控制。歌词解析和处理逻辑的重大重构也使得系统更加健壮和高效。 Highlights
Changelog
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
本次 PR 包含了一系列重要的优化和新功能,整体质量非常高。
核心亮点在于 LyricManager.ts 的重构,通过将歌词获取逻辑与状态更新分离,有效解决了歌词渲染抖动的问题,代码结构也变得更加清晰。lyricParser.ts 中的性能优化同样值得称赞,特别是 alignLyrics 函数从 O(N*M) 优化到 O(N+M),以及在多个解析函数中采用单次遍历(single-pass)的策略,显著提升了效率和代码健壮性。
新增的歌词预加载、动态封面、任务栏歌词主题色等功能,实现方式合理,考虑周全。将本地歌曲封面的处理从 Blob URL 切换到 Data URL 是一个很棒的修复,解决了跨窗口引用失效的问题。
总体而言,这是一次出色的代码提交,极大地提升了歌词系统的性能、稳定性和功能性。我只在 alignLyrics 函数中发现一个可以改进的地方,以处理匹配的准确性问题,具体见我的评论。
| const line = result[i]; | ||
| const other = otherLyrics[j]; | ||
| const diff = line.startTime - other.startTime; | ||
|
|
||
| if (Math.abs(diff) <= ALIGN_TOLERANCE_MS) { | ||
| // 匹配成功 | ||
| line[key] = other.words.map((word) => word.word).join(""); | ||
| i++; | ||
| j++; | ||
| } else if (diff < 0) { | ||
| // 当前歌词时间较早,移动当前指针 | ||
| i++; | ||
| } else { | ||
| // 目标歌词时间较早,移动目标指针 | ||
| j++; | ||
| } |
There was a problem hiding this comment.
当前的双指针算法虽然高效,但在某些边缘情况下可能会选择一个并非最优的匹配。例如,当一个时间轴上的点 A 同时与另一个时间轴上的点 B 和 C 都满足容差范围时,当前实现会贪心地选择它遇到的第一个匹配项(比如 B),即使 C 在时间上与 A 更接近。
为了提高匹配的准确性,同时保持 O(N+M) 的时间复杂度,我建议对算法进行微调:当找到一个潜在匹配时,继续向前查看(在 otherLyrics 中),只要后续行的匹配度更高(时间差更小),就继续移动 j 指针。直到找到局部最优匹配后,再进行匹配并同时推进 i 和 j。
这样可以确保每一行歌词都能与其在时间上最接近的翻译/音译行进行匹配,从而提高对齐的精确度。
const line = result[i];
const other = otherLyrics[j];
const diff = line.startTime - other.startTime;
if (diff > ALIGN_TOLERANCE_MS) {
// other is too early, advance j
j++;
} else if (diff < -ALIGN_TOLERANCE_MS) {
// line is too early, advance i
i++;
} else {
// Found a potential match. Let's see if the next `other` is an even better match.
if (j + 1 < otherLyrics.length) {
const nextOther = otherLyrics[j + 1];
const nextDiff = line.startTime - nextOther.startTime;
// If the next item is closer and also within tolerance, let's check it in the next iteration.
if (Math.abs(nextDiff) < Math.abs(diff)) {
j++;
continue;
}
}
// This is the best match we can find for `line` by moving `j` forward.
line[key] = other.words.map((word) => word.word).join("");
i++;
j++;
}
No description provided.