Skip to content

Architecture

ChouChiu edited this page Sep 23, 2026 · 3 revisions

项目架构

Workspace 结构

项目为 Cargo workspace,包含 6 个 crate:

Lyrics-Helper/
├── Cargo.toml                     # workspace 根定义(虚拟 manifest)
└── crates/
    ├── lyrics-core/               # 基础数据模型、trait 与辅助工具
    │   └── src/
    │       ├── models/            # LyricsData, LineInfo, SyllableItem, TrackMetadata, 枚举
    │       ├── traits/            # LyricsParser, LyricsGenerator, LyricsDecrypter
    │       └── helpers/           # type_helper, offset_helper, chinese_helper, conventions, word_timing
    │           └── optimization/  # 歌词规整优化模块
    ├── lyrics-parsers/            # 格式解析器与 XML 提取工具 xml_utils
    ├── lyrics-generators/         # 格式生成器
    ├── lyrics-crypto/             # QRC/KRC 解密与网易云 eapi 参数加密
    ├── lyrics-search/             # 平台搜索与歌词检索(受 search feature 控制)
    │   └── src/
    │       ├── error.rs           # SearchError 错误类型
    │       ├── providers/web/     # 平台底层 HTTP 客户端与数据反序列化
    │       └── searchers/         # Searcher trait 实现、打分计算与渐进式搜索
    └── lyrics-helper/             # 顶层门面 crate
        ├── src/lib.rs             # 重新导出与顶层快捷入口
        ├── tests/                 # 集成测试与 fixtures 测试集
        └── examples/              # demo / search_test / search_lyrics_test

依赖关系与层次分工

lyrics-core
  ├─► lyrics-parsers
  ├─► lyrics-generators
  └─► lyrics-crypto

lyrics-core + lyrics-crypto + lyrics-parsers ─► lyrics-search
以上 5 个 crate(lyrics-search 可选)        ─► lyrics-helper

分层由各 crate 的 Cargo.toml 严格保证:底层 crate 不可感知上层 crate。需要跨模块复用的数据模型与工具函数统一下沉至 lyrics-core。

lyrics-search 依赖 lyrics-core(模型)、lyrics-crypto(QRC 歌词解密与 eapi 签名)以及 lyrics-parsers(用于解析 QQ 音乐的 XML 信封)。

外部依赖说明

Crate 外部依赖及用途
lyrics-core serde + serde_json(模型序列化与 JSON 判定)、regex(行格式识别)、quick-xml(XML 结构识别)、ferrous-opencc(中文繁简转换)
lyrics-parsers serde + serde_json、regex、quick-xml、base64
lyrics-generators 仅依赖 lyrics-core
lyrics-crypto flate2(zlib 解压缩)、base64、aes + md-5(网易云 eapi 加密)
lyrics-search 全部挂在 search feature 下:reqwest(0.13,启用 json / form / rustls)、tokio、async-trait、urlencoding、rand
lyrics-helper 门面重导出上述 crate

设计决策

门面模式

外部用户只需声明依赖 lyrics-helper。门面 crate 完成两项职责:

  1. 将各子 crate 挂载为独立模块(parsers、generators、decrypter、search、searchers、providers)。
  2. 将最常用入口(parse、parse_auto、generate_string、decrypt_qrc、decrypt_krc 等)及核心模型提到 crate 顶层。

Trait 抽象与查表分发

crates/lyrics-core/src/traits/ 定义统一契约:

  • LyricsParser:parse() + raw_type()
  • LyricsGenerator:generate() + lyrics_type()
  • LyricsDecrypter:decrypt() + decrypt_bytes()

各格式解析器与生成器均为零大小类型(ZST)。parser_for(raw_type) 与 generator_for(lyrics_type) 通过查表返回静态分发的 &'static dyn trait 对象。新增一种歌词格式只需编写对应格式模块、在宏声明中注册,并在查表中添加分支即可。

上游一致性与有意偏离

本项目主要逻辑对标 C# 项目 WXRIW/Lyricify-Lyrics-Helper。有意偏离上游的行为均有明确原因:

  • KRC 解密 BOM 识别:上游无条件丢弃解码后首字符,本库通过匹配 BOM 字节序列剥离,避免误伤无 BOM 正文。
  • SyllableItem 移除 PartialEq:上游 ISyllableInfo 亦无相等语义;移除按起止时间的粗暴相等比较,避免词内容不同的音节被误判为相等。
  • FullSyllableInfo 移除聚合缓存:取消 RefCell 缓存与 refresh_properties(),属性改为调用时即时推导,使整个数据模型天然支持多线程 Send + Sync。
  • 保留 QRC/KRC 行头时长:行头时长被记录为 LineInfo 自身的结束时间,防止以拉长末尾音节冒充行显示时间而破坏逐字高亮。
  • 书写约定与逐词计时:上游未包含的全新辅助模块,提供转录约定识别(helpers::conventions)与跨文档时间合并(helpers::word_timing)。

Feature 开关

搜索功能由 search feature 控制(默认开启):

# crates/lyrics-helper/Cargo.toml
[features]
default = ["search"]
search = ["lyrics-search"]

关闭该 feature 后,lyrics-search 编译为空 crate,门面不再导出任何网络相关模块:

cargo add lyrics-helper --no-default-features

Clone this wiki locally