# 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 补全等更高层业务能力开发的条件。