# MangTool —— 音乐文件一键导入工具 面向 Navidrome 音乐服务器的音频文件智能导入管线。 ## 一键导入工作流 将待处理的音频文件放入 `Input/` 目录,点击「开始一键导入」即可自动完成: 1. **扫描** — 递归扫描 Input 目录下的所有音频文件 2. **校验** — 检查 Title/Artist/Album 元数据是否完整,缺失文件移入 Rejected/MissingMetadata 3. **繁简转换** — 将繁体中文标签自动转为简体 4. **格式转换** — 将 WAV/APE/AIFF/WV/TTA 转为 FLAC(需 FFmpeg),失败文件移入 Rejected/ConversionFailed 5. **去重** — 基于 Artist+Album+Disc+Track+Title 归一化身份标识对比 Library 已有文件,重复移入 Rejected/Duplicate 6. **封面** — 专辑目录须有 `cover.jpg/png` 或音频含内嵌封面,二者皆无移入 Rejected/MissingCover 7. **入库** — 有效文件按 `Artist/Album (year)/NN - Title.ext` 布局移入 Library 8. **歌词(可选)** — 从侧车 `.lrc`、内嵌歌词或远程接口补齐歌词;**歌词的有/无/失败绝不影响音频入库**,仅计入报告统计 ## 目录结构 ``` BasePath/ ├── Input/ ← 放入待处理的音频文件 ├── Library/ ← 整理后的 Navidrome 兼容曲库 ├── .mangtool/ ← 任务生命周期状态(重启恢复用,勿手动改动) └── Rejected/ ← 被拒绝的文件按原因分类 ├── MissingMetadata/ ├── MissingCover/ ├── Duplicate/ ├── ConversionFailed/ ├── Unreadable/ ├── Other/ └── Reports/ ← 每次导入的结构化 JSON 报告(逐文件结果 + 歌词统计) ``` ## 可观测性与报告 - **导入报告**:每次导入在 `Rejected/Reports/` 写入一份结构化 JSON,含逐文件结果(`outcome`)与歌词来源/状态(`lyricSource`/`lyricStatus`),以及汇总的 `lyricsFound/lyricsMissing/lyricsFailed` 等计数。既有字段保持向后兼容。 - **UI 下载**:一键导入页可查看歌词「有/无/失败」实时统计,并「下载导入报告」(`GET /api/ingest/report/{taskId}`,`taskId` 传 `latest` 取最近一份)。 - **依赖自检**:`GET /api/health/dependencies` 报告 FFmpeg/FFprobe 是否可用及版本,便于部署自检与排障。 ## 任务生命周期、取消与恢复 - **取消**:`POST /api/ingest/cancel` 取消当前任务;取消只停止后续文件处理,**已入库(已移动)的文件不会被删除**,未处理文件保留在 `Input/` 供下次导入。 - **重启恢复**:任务生命周期与逐文件完成情况持久化在 `BasePath/.mangtool/ingest-tasks.json`。服务重启后,仍处于运行中的任务会被标记为 `interrupted`;由于已完成文件已移出 `Input/`,重新导入自然只处理未完成文件,不会重复搬运。 ## Library 健康检查(只读,修复需确认) - **只读扫描**:`POST /api/library/health/scan`(可选 `?checkDecode=true` 执行完整解码校验)统计缺元数据、缺封面、缺歌词、孤立侧车(无对应音频的 `.lrc`)与重复曲目,**绝不修改任何文件**。 - **确认后修复**:`POST /api/library/health/repair` 需请求体 `confirm=true` 才会执行(歌词回填、封面回填、删除孤立侧车、可选删除解码失败音频);`confirm=false` 仅演练,不改动磁盘。匹配到音频的侧车永不删除。 **修复示例(含封面回填)**: ```bash # 默认配置下不修改磁盘。加上 confirm=true 与 backfillCovers=true 即可安全回填封面与修复曲库 curl -X POST -H "Content-Type: application/json" -d '{"confirm": true, "backfillCovers": true}' http://localhost:8080/api/library/health/repair ``` ## 备份与恢复 导入是「移动」语义,请在批量导入前对关键目录做快照备份: - **必备**:`Library/`(成品曲库,含 `cover.jpg/png` 与 `.lrc`)。 - **建议**:`Rejected/`(含 `Reports/` 报告,便于追溯)与 `BasePath/.mangtool/`(任务状态)。 ```bash # 简易快照(示例) tar czf mangtool-backup-$(date +%Y%m%d).tgz -C /path/to/BasePath Library Rejected .mangtool ``` 恢复时将快照解压回原 `BasePath` 即可;Navidrome 直接扫描 `Library/` 目录,无需额外数据库。 ## 构建与运行 ```bash # 后端 cd backend && mvn clean package -DskipTests && mvn spring-boot:run # 前端(开发模式) cd frontend && npm ci && npm run dev # Docker cd docker && docker compose up -d --build ``` ## 一次性清理历史曲库 正常导入不会扫描或删除 `Library` 中的历史文件。升级后如需清理旧数据,先运行默认的预览模式: ```bash ./scripts/cleanup-library.sh --library /path/to/Library --dry-run ``` 确认输出后再显式执行: ```bash ./scripts/cleanup-library.sh --library /path/to/Library --execute ``` 脚本会优先把音频内嵌封面提取为专辑目录的 `cover.jpg/png`。只有目录和音频都没有封面时,才删除音频及同 basename 的 `.lrc`、`.cue`、`.json`、`.txt` 和图片 sidecar;不会删除公共 `cover.jpg/png` 或其他曲目文件。 ## 技术栈 - 后端:Spring Boot 2.7 + Java 8 + Maven - 前端:Vue 3 + Vite + TypeScript + Element Plus - 音频元数据:jaudiotagger - 繁简转换:opencc4j - 格式转换:FFmpeg ## Cover Art Settings - `MANGTOOL_COVER_ENABLED` (default: false) - Enable Cover Art Fetch - `MANGTOOL_MB_BASE_URL` (default: https://musicbrainz.org/ws/2) - `MANGTOOL_CAA_BASE_URL` (default: https://coverartarchive.org) - `MANGTOOL_MB_USER_AGENT` (default: MangTool/1.0 (https://gitea.mangmang.fun/LiuMangMang/MyTool)) - User-Agent for MusicBrainz API requests