music-organizer · diff
git:20260920.d4bf53a to git:20261008.aae65c7
3 added, 0 removed. Audit A to A.
---
name: music-organizer
description: Use when 用户想整理 NAS 上的音乐库 — "帮我整理音乐"、"歌曲散落一地"、"专辑没有封面"、"文件名带【FLAC】/320K 水印"、"曲目没有编号"、"路径和 ID3 标签对不上"。只读扫描按「歌手/专辑/曲目」三层结构做正向合规校验,内置最小 ID3v2 解析器可选对照路径与标签;LLM 出 old→new 计划,用户确认后由 Agent 执行。
触发词:音乐整理、音乐库归档、歌曲整理、专辑整理、曲目编号、专辑封面、ID3 标签、音乐文件名、水印文件名、FLAC 标签、歌手专辑结构、整轨镜像、CUE 分轨、music organizer、organize music、fix id3。
不适用:影视命名(走 media-naming)、照片视频按日期(走 photo-organizer)、内容级去重(走 dedup-finder)、下载区清理(走 download-cleaner)。
---
# Music Organizer — 音乐库正向合规整理
## 概述
**跨 NAS 通用**:扫描脚本跑在**本地挂载路径**上(SMB/NFS),纯 stdlib 零依赖,
不绑定任何品牌 API。内置**最小 ID3v2 解析器**(纯 Python,读 mp3 标签),
无需 mutagen/eyeD3 等第三方库。
对音乐库做**正向合规扫描**:定义合规结构(歌手/专辑/曲目)→ 不匹配即报问题。
**写操作不在脚本里** — 扫描出问题后,LLM 生成 `old → new` 计划,
经用户确认后由 Agent 执行(挂载盘 `mkdir`/`mv -n`,极空间也可走 `zs` CLI / MCP tool)。
## Prerequisites
```bash
open smb://<NAS_IP>/音乐 # 极空间/群晖/威联通/绿联等均支持 SMB
python3 --version # ≥3.9 即可,无第三方依赖
```
## 快速验证
```bash
python3 music_organizer.py scan --root /Volumes/nas/音乐 --sample 500
```
## 命令
| 命令 | 用途 |
|------|------|
| `scan --root PATH` | 正向合规扫描(只读) |
| `scan --root PATH --json --output F` | JSON 输出 |
| `--read-tags` | 读 mp3 ID3v2 标签,对照路径与标签一致性(较慢,默认最多 100 文件) |
| `--tag-limit N` | `--read-tags` 时最多读取的文件数 |
| `--max-depth N` / `--sample N` / `--top N` | 深度 / 文件数上限 / 每类显示条数 |
期望目录结构:
```
音乐/
周杰伦/ ← 歌手
范特西 (2001)/ ← 专辑(建议带年份)
01 爱在西元前.mp3 ← 曲目号前缀
02 简单爱.mp3
cover.jpg ← 专辑封面
范特西.cue ← 整轨镜像的 CUE(合法)
合辑/ ← 白名单功能区(不做歌手/专辑校验)
```
## 工作流
### 场景 1:用户说"帮我整理音乐库"
**步骤**:
1. **exec** `python3 music_organizer.py scan --root <挂载路径> --output /tmp/music-issues.json`
2. 读 JSON `stats`:歌手/专辑/曲目数、格式分布、缺封面专辑数、缺曲目号、水印名、散曲数
3. 汇报问题分布,**不做写操作** — 问用户从哪类开始
### 场景 2:用户说"按规范整理"
**步骤**:
1. 复用上一轮 JSON(或重新 scan)
2. 按下方「整理顺序」生成 `old → new` 计划,**先预览**:
- 散曲 → 建 `歌手/专辑/` 结构后归位(歌手/专辑名从标签或文件名推断,拿不准就问)
- 缺曲目号 → 按专辑曲目顺序补 `NN - ` 前缀
- 水印名 → 去掉 `【FLAC】`/`320K`/站点名等
3. 用户确认后执行(挂载模式):
```bash
mkdir -p "/Volumes/nas/音乐/周杰伦/范特西 (2001)"
mv -n "/Volumes/nas/音乐/爱在西元前.mp3" \
"/Volumes/nas/音乐/周杰伦/范特西 (2001)/01 爱在西元前.mp3"
```
- **必须 `mv -n`**;极空间用户也可走 `zs mkdir` / `zs mv` / `zs rename`
4. 重扫验证
### 场景 3:用户说"路径和标签对不上 / 帮我核对 ID3"
**步骤**:
1. **exec** `scan --root <路径> --read-tags --output /tmp/tags.json`
(标签对照只读 mp3;`--tag-limit` 控制读取量,SMB 上逐个读文件头较慢)
2. 过滤「路径与标签不符」「缺 ID3 标签」两类
3. **标签与路径冲突时以哪个为准,必须问用户** — 脚本只报差异,不猜
4. 需要写标签(补 TIT2/TPE1/TALB)时:本 skill 不写标签,
建议用户用 `eyeD3`/`mutagen`/MusicBrainz Picard(见已知 gap)
## 整理顺序(严格)
1. 删除垃圾(`.DS_Store`、`._*`、`.tmp`、下载残留)
2. 移出非音频文件(专辑目录里的 mp4/pdf 等,除非是封面/歌词/CUE/log)
3. 散曲归位:建 `歌手/专辑/` 结构(歌手/专辑从标签或文件名推断,拿不准问用户)
4. 缺歌手层的「伪专辑」→ 补一层歌手目录,或归入 `合辑/`
5. 曲目号规范化:补 `NN - ` 前缀(按专辑顺序;整轨镜像+CUE 跳过)
6. 清理水印/音质标签(`【FLAC】`、`320K`、站点名)
7. 同曲多格式 → 保留最高音质(无损 > 320K > 其他),其余用户确认去留
8. 补专辑封面(cover.jpg 或内嵌 APIC)
9. 重新 `scan` 验证
每一步都先出映射表预览,确认后再批量执行。
## 命名速查
| 对象 | 规范 | 示例 |
|------|------|------|
| 歌手目录 | 歌手名 | `周杰伦` |
| 专辑目录 | `专辑名 (年份)` | `范特西 (2001)` |
| 曲目文件 | `NN 标题.ext` 或 `NN - 标题.ext` | `01 爱在西元前.mp3` |
| 多碟 | `CD1/` `CD2/` 子目录,曲目号各自从 01 起 | `CD1/01 ….mp3` |
| 碟-轨合编 | `D-TT 标题.ext` | `1-01 爱在西元前.flac` |
| 封面 | `cover.jpg` / `folder.jpg` / 内嵌 APIC | — |
| 整轨镜像 | 单 `.flac/.ape/.wv` + `.cue`(合法,不强制分轨) | — |
- 禁止:文件名带 `【】`、`[FLAC]`、`320K`、`www.xxx.com`、站点/公众号水印
- 曲目号在前缀,不在结尾(`简单爱 01.mp3` → `01 简单爱.mp3`)
## 写操作通道
| 通道 | 适用 | 命令 |
|------|------|------|
| 挂载盘 shell | 任何 NAS | `mkdir -p` + `mv -n`(同共享内移动=服务端移动) |
+ | PowerShell(Windows) | 任何 NAS | `New-Item -ItemType Directory -Force` 建目录 + `Move-Item`(**不加 `-Force`** = 不覆盖);批量 `robocopy /MOV /XC /XN /XO` |
| `zs` CLI | 极空间(免挂载) | `zs mkdir` / `zs mv` / `zs rename`(见 zspace-nas skill) |
| MCP tool | 极空间 + MCP | `mkdir` / `move` / `rename`,弹 UI 二次确认 |
| 标签写入 | 任意 | **本 skill 不写标签**;用 `eyeD3`/`mutagen`/Picard |
+
+ > **Windows**:上表第一行是 POSIX 命令,PowerShell 里没有 `mv -n` / `mkdir -p`,照着执行会直接失败。完整对照(含中文路径要先 `chcp 65001`、用隔离目录代替删除)见 [skills/README.md](../README.md) 的「Windows 用户:执行阶段要换命令」;极空间用户可直接用 `zs mv` 绕开 shell 差异。
## 关键约束
1. **脚本只读**:无 apply / mv / rename 子命令;写操作由 Agent 在用户确认后执行
2. **先预览后执行**:永远先给 `old → new` 表;`mv` 一律带 `-n`
3. **标签只读且仅 mp3**:`--read-tags` 只解析 ID3v2(mp3);FLAC/M4A 标签见已知 gap
4. **标签 vs 路径冲突不自动裁决**:脚本只报差异,以哪个为准由用户定
5. **整轨镜像+CUE 合法**:不强制分轨,只做提示
6. **合辑/歌单等白名单目录**跳过歌手/专辑校验,避免误报
## 踩坑
| 坑 | 表现 | 解决 |
|----|------|------|
| ID3v2 版本差异 | v2.2 帧头 3 字节 / v2.3-4 是 4 字节,v2.4 用 synchsafe | 解析器已按版本分支处理 |
| 标签编码混乱 | latin-1/UTF-16/UTF-8 混用,中文乱码 | 按帧 encoding 字节解码;解不出返回空跳过 |
| APIC 大封面 | 内嵌封面几百 KB,`--read-tags` 读得慢 | `--tag-limit` 控制读取量;封面判定目录图片优先 |
| 曲目号误判 | `2001 太空漫游` 被当缺曲目号 | `TRACK_NO_OK` 只认 1-3 位纯数字前缀;年份开头会误报,人工复核 |
| 整轨镜像误报 | 单 flac+cue 被当「缺曲目号」 | `is_cue_sheet` 检测后跳过逐轨校验 |
## 已知 gap
- **标签只支持 mp3(ID3v2)**:FLAC(Vorbis Comment)、M4A(MP4 atom)、APE 标签未解析 —
需第三方库(mutagen),与「零依赖」冲突;要全格式标签用 Picard/eyeD3
- **不写标签**:本 skill 只读+报告;补标签/改标签交给专用工具
- **不联网查专辑信息**:歌手/专辑归类、年份补全靠文件名+标签+LLM 知识,冷门曲目需用户确认
- **曲目顺序**:补 `NN` 前缀的顺序靠标签 TRCK 或 LLM 推断,无权威曲目表时会不准
## 故障排查
| 现象 | 处理 |
|------|------|
| `--root 不是有效目录` | 确认已挂载:`ls /Volumes/` |
| `--read-tags` 很慢 | SMB 上逐文件读头;减小 `--tag-limit` 或不开该 flag |
| 大量「缺曲目号」误报 | 库里多用「标题 01」尾缀式;确认约定后按「曲目号在结尾」类批量改前缀 |
| 合辑被拆成一堆歌手 | `合辑/群星/VA` 已在白名单;自定义合辑目录名需加进 `WHITELIST_DIRS` |