# AM Music Deduper 轻量级家庭 NAS 音乐库去重服务,面向 `AllMusic/{username}/` 场景。 ## 处理模型 ```text AllMusic ↓ 文件稳定检测 ↓ L1:size + head/tail 64 KiB ↓ 完整 SHA-256 ├─ 相同 → Exact Duplicate → hard link └─ 不同 → duration ±3s → Chromaprint ├─ 高相似且版本一致 → hard link ├─ 中等相似/版本冲突 → review └─ 低相似 → 保留 ``` ### 关键安全规则 - SHA-256 是 Exact Duplicate 的最终依据;L1 只负责缩小候选范围。 - 不根据文件名、歌手、歌名、专辑或来源单独判重。 - 确认相同版本后,优先使用 hard link 保留每个用户原来的逻辑路径。 - 用户删除自己的路径不会影响其他 hard link;最后一个 link 删除后数据才释放。 - 不跨文件系统创建 hard link。 - 正在写入的文件必须先通过稳定性检查。 - L2 对版本标记冲突的文件进入 review,不自动合并。 - `--dry-run` 只报告/更新索引,不修改音乐文件。 - SQLite 是加速索引,文件系统是最终事实;数据库丢失后可以重新扫描。 ## CLI ```bash # 建立/更新索引,不修改音乐文件 am-deduper scan /music/AllMusic --db /data/dedupe.db # Exact + L2;首次执行建议 dry-run am-deduper dedupe /music/AllMusic --db /data/dedupe.db --dry-run # 确认后执行 am-deduper dedupe /music/AllMusic --db /data/dedupe.db # 长驻监听:默认只自动执行安全的 Exact hard-link am-deduper watch /music/AllMusic --db /data/dedupe.db # 开启 L2 自动 acoustic 匹配(建议在 dry-run 验证阈值后再启用) am-deduper watch /music/AllMusic --db /data/dedupe.db --l2 ``` ## Docker / Feiniu NAS 部署 wjyhk 负责构建镜像,推送到 Gitea Container Registry;NAS 只负责 pull + run,不在 NAS 上重新 build。 NAS 的 `AllMusic` 与 dedupe 数据建议分开: ```text NAS ├── AllMusic/ │ ├── admin/ │ ├── alice/ │ └── bob/ └── AppData/ └── am-deduper/ └── dedupe.db ``` 注意:如果以后启用 trash,trash 目录必须位于 `AllMusic` 所在同一文件系统内,不能把需要原子 rename/hard-link 语义的文件直接移动到 `/data`。 ### NAS `.env` ```dotenv AM_DEDUPER_IMAGE=//am-music-deduper: ALLMUSIC_PATH=/AllMusic DEDUPE_DATA_PATH=/AppData/am-deduper ``` ### NAS 部署 ```bash mkdir -p "$DEDUPE_DATA_PATH" docker login docker compose pull docker compose up -d ``` 查看日志: ```bash docker logs -f am-deduper ``` 首次上线建议先暂停 `watch`,执行一次完整 `scan` + `dedupe --dry-run`,确认候选数量与 review 项,再启用正式 dedupe;L2 自动处理单独验证后再打开 `--l2`。