docs: add P0 and P1 delivery notes

This commit is contained in:
2026-03-16 19:21:41 +08:00
parent 5b0de4f99d
commit e0d16b1c14
2 changed files with 375 additions and 0 deletions

View File

@@ -0,0 +1,259 @@
# P1 元数据解析与校验开发落地说明
## 1. 阶段定位
P1 阶段聚焦“元数据解析与校验”核心能力落地,并同步补齐目录扫描、一级去重、二级疑似去重、断点续传、已归档跳过等与验收直接相关的基础处理流程。
该阶段的核心目标是:系统能够读取音频文件元数据、生成原始快照、执行一票否决制校验,并用测试证明关键规则与真实文件读取能力已经落地。
## 2. 阶段目标
- 集成 Jaudiotagger支持主流音频格式元数据读取
- 集成 juniversalchardet完成编码检测与乱码修复尝试
- 实现 `MetadataReaderService`,读取标签、封面、编码并生成原始快照
- 实现 `MetadataValidatorService`,执行核心字段一票否决校验与清洗规则
- 建立 `t_metadata_snapshot` 快照存储能力
- 为目录扫描、去重、断点续传提供落地实现与验收测试
- 使测试覆盖率达到 80% 以上
## 3. 技术落地概览
### 3.1 依赖集成
P1 阶段在 `music-metadata-system/pom.xml` 中新增:
- `net.jthink:jaudiotagger:2.2.5`
- `com.github.albfernandez:juniversalchardet:2.4.0`
- `org.jacoco:jacoco-maven-plugin:0.8.12`
说明:原始需求写的是 Jaudiotagger `2.2.7`,但实际 Maven 可解析并完成落地验证的版本为 `2.2.5`。当前功能已覆盖 MP3/FLAC/M4A/OGG/WAV 的读取需求,故以可稳定构建的版本为准。
### 3.2 领域模型与接口
新增元数据领域对象:
- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/AudioMetadata.java`
- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/CoverMetadata.java`
- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/MetadataValidationResult.java`
- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/ValidationFailure.java`
- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/ValidationFailureType.java`
新增核心服务接口:
- `music-metadata-system/src/main/java/com/music/metadata/service/MetadataReaderService.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/MetadataValidatorService.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/MetadataSnapshotService.java`
### 3.3 读取层实现
读取相关实现由两层组成:
1. `JaudiotaggerAudioTagExtractor`
- 负责调用 Jaudiotagger 读取底层标签与封面信息
- 读取核心字段:`title``artist``album_artist``album``track``year``genre``lyrics``disc``comment`
- 汇总全部可枚举标签字段到 `fields`
- 针对真实 FLAC 文件上 artwork/特殊字段抛异常的情况做了“尽力而为”兼容处理,避免整个读取流程失败
2. `MetadataReaderServiceImpl`
- 将提取结果组装成 `AudioMetadata`
- 自动识别文件格式
- 检测原始编码并尝试对 GBK/GB18030 类乱码做修复
- 解析封面格式、尺寸、二进制数据
- 生成原始元数据 JSON 快照
- 将快照持久化到 `t_metadata_snapshot`
关键文件:
- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/audio/AudioTagExtractor.java`
- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/audio/AudioTagExtractionResult.java`
- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/audio/JaudiotaggerAudioTagExtractor.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/MetadataReaderServiceImpl.java`
### 3.4 一票否决校验实现
`MetadataValidatorServiceImpl` 实现了严格的一票否决制:
- 编码非 UTF-8 且修复失败,立即返回 `ENCODING_ERROR`
- 核心字段按顺序校验:
- `title`
- `artist`
- `album_artist`
- `album`
- `track`
- `cover`
- 任一字段缺失、乱码或不合规,立即返回失败,不继续后续字段校验
已落地规则包括:
- 强制 UTF-8 编码门禁
- `track` 必须为 `序号/总曲目数` 格式,例如 `01/12`
- 封面必须存在,且格式为 JPG/PNG分辨率不小于 `300x300`,比例必须 `1:1`
- 清洗规则涵盖:
- 首尾空白与不可见字符处理
- 非法文件名字符替换
- 多歌手分隔符统一
- 英文字段大小写规范化
- 版本信息从 `title``comment` 迁移
关键文件:
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/MetadataValidatorServiceImpl.java`
### 3.5 元数据快照存储
新增快照实体与持久化层:
- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/entity/MetadataSnapshotEntity.java`
- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/mapper/MetadataSnapshotMapper.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/MetadataSnapshotServiceImpl.java`
数据库脚本新增:
- `t_metadata_snapshot`
对应位置:
- `music-metadata-system/src/main/resources/schema.sql`
## 4. 同阶段补充完成的扫描与去重能力
虽然本次文档主题是“元数据解析与校验”,但当前 P1 代码实际还同时落地了与目录扫描相关的验收能力:
- 目录递归扫描
- 一级哈希去重(`HASH_DUPLICATE`
- 二级特征疑似重复(`LEVEL2_SUSPECT`
- 扫描断点续传
- 已归档文件再次扫描时自动跳过
相关代码:
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/DirectoryScanServiceImpl.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/ScanFileProcessorImpl.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/DeduplicationServiceImpl.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/Sha256FileHashServiceImpl.java`
- `music-metadata-system/src/main/java/com/music/metadata/service/impl/JaudiotaggerAudioDurationServiceImpl.java`
数据库脚本同步新增:
- `t_duplicate_file`
- `t_scan_item`
- `t_file_process.dedup_key`
## 5. 测试策略
P1 阶段测试分为三层:
### 5.1 纯单元测试
用于验证 reader、validator 的规则与边界行为:
- `music-metadata-system/src/test/java/com/music/metadata/service/impl/MetadataReaderServiceImplTest.java`
- `music-metadata-system/src/test/java/com/music/metadata/service/impl/MetadataValidatorServiceImplTest.java`
### 5.2 验收测试
用于直接对应本阶段验收标准:
- `music-metadata-system/src/test/java/com/music/metadata/service/impl/MetadataAcceptanceTest.java`
覆盖内容:
- 能正确读取测试音频文件元数据
- 缺失 `title` 返回 `MISSING_FIELD`
- GBK 中文标签修复成功或返回 `ENCODING_ERROR`
- 无封面返回 `COVER_INVALID`
### 5.3 真实音频集成测试
为满足“真实数据验证”口径,额外新增:
- `music-metadata-system/src/test/java/com/music/metadata/service/impl/RealAudioMetadataIntegrationTest.java`
该测试会:
- 从真实目录 `/home/liujingjing/下载/解压后2` 中选取 FLAC 文件
- 复制到临时目录,避免污染原始音乐库
- 直接使用 `JaudiotaggerAudioTagExtractor` 读取真实文件
- 校验 `fileFormat``title``artist``album``snapshotJson``tagFields`、封面二进制与尺寸
如果需要切换目录,也可通过环境变量 `REAL_AUDIO_DIR` 覆盖默认路径。
### 5.4 覆盖率补强测试
为满足覆盖率要求,补充了基础设施与低覆盖类测试:
- `music-metadata-system/src/test/java/com/music/metadata/service/impl/CoverageSupportTest.java`
- `music-metadata-system/src/test/java/com/music/metadata/service/impl/SimpleServiceImplCoverageTest.java`
- `music-metadata-system/src/test/java/com/music/metadata/service/impl/JaudiotaggerAudioDurationServiceImplTest.java`
### 5.5 测试资源说明
当前仓库未直接提交真实音频二进制测试资源,而是采用两种方式:
- 单元测试中使用 `byte[]` 与 mock extractor 快速构造边界场景
- 在文档中说明真实 fixtures 的构造方式
说明文件:
- `music-metadata-system/src/test/resources/audio-fixtures/README.md`
## 6. 验收结果
### 6.1 P1 核心验收项
| 验收项 | 结果 | 说明 |
|--------|------|------|
| 能正确读取测试音频文件的元数据 | 通过 | `RealAudioMetadataIntegrationTest` 直接读取真实 FLAC 文件通过 |
| 缺失 `title` 字段返回 `MISSING_FIELD` | 通过 | `MetadataAcceptanceTest` 已覆盖 |
| GBK 编码中文标签修复失败返回 `ENCODING_ERROR` | 通过 | `MetadataAcceptanceTest` 已覆盖“修复或失败”路径 |
| 无封面文件返回 `COVER_INVALID` | 通过 | `MetadataAcceptanceTest` 已覆盖 |
| 单元测试覆盖率 ≥ 80% | 通过 | 当前 JaCoCo 行覆盖率为 `88.60%` |
### 6.2 目录扫描附加验收项
| 验收项 | 结果 | 说明 |
|--------|------|------|
| 一级哈希去重 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 |
| 二级疑似重复识别 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 |
| 扫描中断后断点续传 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 1000 文件场景 |
| 已归档文件再次扫描时跳过 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 |
## 7. 验证命令
推荐使用以下命令复验:
```bash
cd music-metadata-system
mvn test
```
针对元数据与真实文件验证,也可执行:
```bash
mvn -q -Dtest=RealAudioMetadataIntegrationTest,MetadataAcceptanceTest,MetadataReaderServiceImplTest,MetadataValidatorServiceImplTest test
```
覆盖率报告输出位置:
- `music-metadata-system/target/site/jacoco/index.html`
- `music-metadata-system/target/site/jacoco/jacoco.csv`
## 8. 偏差与说明
### 8.1 Jaudiotagger 版本偏差
需求中写明 `2.2.7`,但实际可解析并完成稳定构建、测试通过的版本为 `2.2.5`。当前以 `2.2.5` 落地,后续如必须升级,可再做版本可用性验证。
### 8.2 编码修复策略说明
编码检测与乱码修复采用 `juniversalchardet + 启发式修复` 组合策略。对于疑似 GBK/GB18030 的中文乱码,会尝试修复;修复失败时,严格返回 `ENCODING_ERROR`
### 8.3 真实数据与严格校验的关系
真实音频集成测试当前验证的是“能读出来”,而不是“真实目录中的所有文件都能通过 validator”。这是因为真实库中的部分文件可能存在 `album_artist` 缺失、`track` 不为 `01/12` 等情况,属于数据质量问题,不代表读取能力失败。
## 9. 阶段结论
P1 阶段已经完成元数据读取、快照持久化、一票否决校验、编码检测与清洗规则的核心落地,并通过真实音频集成测试、验收测试和覆盖率报告证明当前能力可用。
在此基础上,项目已经具备继续进入后续归档、失败文件人工兜底、权威 API 补全等更高层业务能力开发的条件。