AM Music Deduper

轻量级家庭 NAS 音乐库去重服务,面向 AllMusic/{username}/ 场景。

处理模型

AllMusic
  ↓
文件稳定检测(size + mtime)
  ↓
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,不自动合并。
  • SQLite 是加速索引,文件系统是最终事实;数据库丢失后可以重新扫描。
  • .dedupe 不参与音乐扫描,避免把内部文件再次处理。

CLI

# 建立/更新索引,不修改音乐文件
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 去重,之后自动执行安全的 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

Feiniu NAS 部署

生产环境采用 Gitea Container Registry → NAS 拉取镜像 → NAS 本地运行。 镜像由 wjyhk 构建并推送到 gitea.king.nyc.mn,Feiniu NAS 不需要本地 build。

建议目录:

NAS
├── Gitea Registry
│   └── gitea.king.nyc.mn/openclaw/am-deduper:v0.2.0
├── AllMusic/
│   ├── admin/
│   ├── alice/
│   └── bob/
└── AppData/
    └── am-deduper/
        └── dedupe.db

NAS .env

ALLMUSIC_PATH=<NAS绝对路径>/AllMusic
DEDUPE_DATA_PATH=<NAS绝对路径>/AppData/am-deduper

首次部署

先登录 Gitea Container Registry:

docker login gitea.king.nyc.mn

拉取生产镜像并准备数据目录:

docker pull gitea.king.nyc.mn/openclaw/am-deduper:v0.2.0
mkdir -p <NAS绝对路径>/AppData/am-deduper

然后使用 Compose 启动容器;当前 Compose 已配置 NAS 实际目录,并提供独立 Web 管理界面。首次执行建议先运行 scan 和 dry-run:

docker compose run --rm am-deduper scan /music/AllMusic --db /data/dedupe.db
docker compose run --rm am-deduper dedupe /music/AllMusic --db /data/dedupe.db --dry-run

确认 dry-run 输出后,再执行正式 Exact/L2:

docker compose run --rm am-deduper dedupe /music/AllMusic --db /data/dedupe.db

然后启动长期监听和 Web 管理界面:

docker compose up -d

Web UI 默认端口为 18080:

http://<NAS-IP>:18080/

管理界面包含:

  • Dashboard:文件数、Hard Link、审核数、索引大小、操作记录。
  • 重复组:查看 SHA-256 完全重复组及估算节省空间。
  • 待审核:查看相似度、候选文件,可人工确认或保留。
  • 任务:查看 scan / dry-run / dedupe 状态。
  • 历史:查看 Hard Link 操作,并对仍保持同 inode 的操作执行安全回滚。
  • 监听服务启动时会先做一次全量扫描与 Exact 去重;新文件稳定后也会自动索引并执行 Exact 去重。
  • 跨 Web 与 watcher 进程使用数据库锁,避免两个容器同时执行 Hard Link。
  • 文件被替换时会自动清空旧 SHA-256 / Chromaprint,防止旧内容哈希污染新文件。
  • 扫描会把数据库中已经不存在的文件标记为 missing,避免脏索引继续计入统计。
  • Web UI 的每个操作都有明确的启动、运行、完成/失败反馈,并保留任务结果。

Web UI 支持可选管理 Token。生产环境建议在 NAS 的 Compose 同目录 .env 中设置 AM_DEDUPER_TOKEN=<随机长字符串>;不要把 Token 提交到 Git。设置后 Web UI 会在首次访问 API 时要求输入 Token。若未设置 Token,则仅适合可信内网环境,不要直接暴露到公网。

更新版本:

修改 .env 中的 AM_DEDUPER_IMAGE(或直接修改 Compose 的默认版本),然后:

docker compose pull
docker compose up -d

当前生产镜像(推荐固定版本):

gitea.king.nyc.mn/openclaw/am-deduper:v0.2.0

兼容自动跟随最新版:gitea.king.nyc.mn/openclaw/am-deduper:latest

本次 v0.2.0 镜像 digest:

sha256:6c3854efc10d19c56c4e9d442180143d8d30ca3a5b2496ca10169f0a78352a65

wjyhk 已验证推送成功;当前镜像 digest:

sha256:96e0b87e454bc9fa96aa5171b117a029bbcef34d20099577db6442544ce5c9ee
S
Description
No description provided
Readme
107 KiB
Languages
Python 99.4%
Dockerfile 0.6%