[2026-09-28] eagle: personal/tech/music-tags-repair-truenas.md
This commit is contained in:
1 parent
fadfb9f4d2
commit
ba364607e2
1 file changed
+184
-1
@@ -8,8 +8,16 @@ wave: 38
|
||||
diff_v6_md5: a2a777f65eb1b6c0729f16bbafe0acc6
|
||||
diff_v6_status: OK — 394 файла / 398 правок, покрытие ПОЛНОЕ (папок с разным album после дифа: 0; путей вне БД: 0). НЕ ПРИМЕНЁН, dry-run не запускался, апрува нет.
|
||||
diff_v6_last_good: DIFF-v6.csv (394/398); история бэкапов в блоке «СЕССИЯ 28»
|
||||
diff_v7_md5: 7047e5c4c320a839fe1568b2bf5761a9
|
||||
diff_v7_status: Собран 28 сен 01:15 через build_diff_v7.py. 204 строки (203 правки). НЕ ПРИМЕНЁН. Переработка v6 — расширен охват, схлопывание по (folder, field, old, new).
|
||||
diff_v7_vs_v6: "v6 требовал aa=='Various Artists' у ВСЕХ файлов папки → папки-сборники без этого тега не видел. v7 убрал это условие: берёт ЛЮБЫЕ папки >=2 файлов с разным album. Поэтому Sbornik_Novij_Rok перешёл из scope=outlier в scope=folder."
|
||||
diff_v7_open_defect: 🔴 ОДИНОЧКИ НЕ ПОКРЫТЫ. build_diff_v7.py правило A содержит `if len(fl) < 2: continue` → папки с 1 файлом пропускаются. Правило B правит только albumartist. Итог: 244 файла / 51 папка Infected Mushroom (распались на ~35 альбомов-одиночек) в v7 НЕ входят — тот же открытый класс, что и в v6.
|
||||
v6_coverage_measured: "398 правок / 394 файла / 116 папок; scope: outlier 86 · orphan 173 · infected 139; field: album 394 · albumartist 4. Пустых old/new = 0, old==new = 0, путей вне БД = 0 — файл чистый."
|
||||
v6_not_closed: 🔴 v6 покрывает 394 файла из 7808 в БД (5%). Не закрыто: (а) одиночки вне IM — 37 папок, где album != имя папки; (б) 109 файлов IM в 14 папках; (в) 492 однородные папки — НЕ пропуск (там old==new).
|
||||
single_folders_open: "37 папок-одиночек с расхождением album != имя папки (вычислено precise9.py по navidrome-fresh.db). НЕ внесены в DIFF-v6.csv — ждут решения Alex по правилу (A или B, см. блок ниже)."
|
||||
waits_decision: 🔴 ПРАВИЛО ДЛЯ ОДИНОЧЕК НЕ ВЫБРАНО. A: album = имя папки как есть (с годом и артистом) → 37 строк. B: album = имя папки БЕЗ года/артиста, а для одиночек album = имя РОДИТЕЛЬСКОЙ папки (как в правиле Alex для IM) → другой список и другое число. Запись в DIFF-v6.csv заблокирована до ответа.
|
||||
last_session: 28
|
||||
blocker: НЕТ apply-plan под DIFF-v6.csv (дифф собран из БД, не из плана). apply_tags_v2.py читает только /app/data/apply-plan.csv (14 колонок, путь с /storage/Music/). Нужен сборщик build_applyplan_v6.py в ~/Downloads/music-tags/ и план apply-plan-v7.csv (7807 строк). Затем апрув Alex → dry-run → apply.
|
||||
blocker: НЕТ apply-plan под DIFF-v6.csv (дифф собран из БД, не из плана). apply_tags_v2.py читает только /app/data/apply-plan.csv (14 колонок, путь с /storage/Music/). Нужен сборщик build_applyplan_v6.py в ~/Downloads/music-tags/ и план apply-plan-v7.csv (7807 строк). Затем апрув Alex → dry-run → apply. 🔴 УТОЧНИТЬ: apply-plan собирать от v6 или от v7 (v7 новее и шире — вероятно от v7).
|
||||
done_session28: удалена папка !Rock&Folk/Король и Шут/Король и шут-1 (17 файлов, 59 МБ); база navidrome.db НЕ тронута.
|
||||
tags:
|
||||
- music
|
||||
@@ -110,6 +118,53 @@ related:
|
||||
>
|
||||
> **Разложение 282 файлов:** `album` 183 · `artist` 155 · `albumartist` 158 · `track` 58.
|
||||
>
|
||||
> ### 📌 СБОРЩИКИ ДИФФА: `build_diff_v6.py` vs `build_diff_v7.py` (сессия 28)
|
||||
>
|
||||
> Оба лежат в `~/Downloads/music-tags/`. Оба читают **`navidrome-fresh.db`** (снимок БД, источник
|
||||
> истины = текущее состояние тегов), НЕ план и НЕ диск. Фильтр `path NOT LIKE '%backup%'`.
|
||||
> Формат вывода одинаков: `scope,folder,path,field,old,new`. Пути **БЕЗ** префикса `/storage/Music/`
|
||||
> (префикс добавляет только сборщик плана).
|
||||
>
|
||||
> **`build_diff_v7.py` — докстринг, 7 правил (единственное место, где они записаны):**
|
||||
> ```
|
||||
> 1. album = имя папки-владельца (ведущий '!' срезается; год/артист в имени не трогаем)
|
||||
> 2. albumartist = Infected Mushroom (в папке Infected Mushroom)
|
||||
> 3. artist = НЕ ТРОГАЕМ
|
||||
> 4. track = НЕ ТРОГАЕМ
|
||||
> 5. Правило применяется ТОЛЬКО к файлам, выбивающимся из папки:
|
||||
> - папка >=2 файлов и album разный -> выравниваем на имя папки
|
||||
> - папка ==1 файл -> НЕ ТРОГАЕМ (норма, папка-артист)
|
||||
> 6. Пути ровно как в БД (без префикса /storage/Music/)
|
||||
> 7. Схлопывание по (folder, field, old, new); сортировка по алфавиту полей
|
||||
> ```
|
||||
>
|
||||
> | | v6 | **v7** |
|
||||
> |---|---|---|
|
||||
> | Триггер | `aa == 'Various Artists'` у **ВСЕХ** файлов папки + album разный | **любые** папки ≥2 файлов с разным album |
|
||||
> | Infected Mushroom | `album` (разбор имени папки) + `albumartist` | только `albumartist` |
|
||||
> | `artist` / `track` | не трогает | не трогает |
|
||||
> | Схлопывание | ❌ нет | ✅ `(folder, field, old, new)` |
|
||||
> | Строк | 399 (398 правок, 394 файла) | 204 (203 правки) |
|
||||
> | md5 | `a2a777f65eb1b6c0729f16bbafe0acc6` | `7047e5c4c320a839fe1568b2bf5761a9` |
|
||||
>
|
||||
> **Почему v7 шире:** v6 требовал `Various Artists` у всех файлов папки → папки-сборники **без**
|
||||
> этого тега он не видел вовсе. v7 снял условие. Следствие: `!A Not sorted/Sbornik_Novij_Rok`
|
||||
> перешёл из `scope=outlier` в `scope=folder`.
|
||||
>
|
||||
> 🔴 **ГЛАВНОЕ ПРО v7: ОН НЕ ЗАКРЫВАЕТ ЗАДАЧУ ПОЛНОСТЬЮ.** Правило 5 (`if len(fl) < 2: continue`)
|
||||
> пропускает **папки с одним файлом**, а правило B у одиночек правит только `albumartist`,
|
||||
> не `album`. Значит **244 файла / 51 папка `Infected Mushroom`**, распавшиеся на ~35 альбомов-
|
||||
> одиночек (`Becoming Insane (Chemical Trolls Remix)`, `CDS`, `Promo`, `Unreleased Tracks` ×29 и др.),
|
||||
> в v7 **не входят** — это ровно тот же незакрытый класс дефекта, что зафиксирован выше по v6
|
||||
> (блок «ОТКРЫТЫЙ КЛАСС ДЕФЕКТА»). Правило Alex для одиночек записано ниже, строка «ПРАВИЛО ALEX
|
||||
> ДЛЯ ОДИНОЧЕК»: папка с 1 файлом → `album` = имя **РОДИТЕЛЬСКОЙ** папки.
|
||||
>
|
||||
> **Следствие для плана:** `apply-plan` надо собирать **от v7** (новее и шире), но перед этим
|
||||
> решить, добавлять ли в v7 правило для одиночек. Если добавлять — сборщик должен обходить
|
||||
> **ВСЕ** папки, включая `len(fl) == 1`, беря `album` из имени родительской папки.
|
||||
> ⚠️ Память по сборникам: правило «доминанта ≥60%» и `SKIP`-исключения **удалены** (Alex 27 сен) —
|
||||
> обходить все папки ≥2 файлов, `album` = имя папки-владельца без `!`.
|
||||
>
|
||||
> ### 🔴 RED FLAG: ПУТЬ В ПЛАНЕ ОБЯЗАН НАЧИНАТЬСЯ С `/storage/Music/`
|
||||
>
|
||||
> Первый dry-run дал **`к обработке: 0`, 282 MISSING, «путь вне /music»**.
|
||||
@@ -6133,6 +6188,134 @@ z Другое…/Pushnoy.ru/старые cur 'старые' -> new 'Pus
|
||||
> ⚠️ **mutagen на хосте NAS НЕТ** — читать теги с диска только внутри контейнера
|
||||
> `tagwriter:latest` (монтирование `${MUSIC}:/music:ro`).
|
||||
|
||||
## 31-я волна — ЗАМЕР ПОКРЫТИЯ v6/v7 И ПРАВИЛО ДЛЯ ОДИНОЧЕК (2026-09-28, сессия 28)
|
||||
|
||||
### Триггер
|
||||
|
||||
Alex: «по diff v6/v7 скоуп работ понятен? задача в доке?» → серия уточнений →
|
||||
**«в diff v6 реальные данные? они закрывают задачу?»** → **«что не закрыто? конкретно»** →
|
||||
**«добавь эти 9 файлов в v6 список. вручную»**.
|
||||
|
||||
### ✅ v6 — данные РЕАЛЬНЫЕ, файл чистый
|
||||
|
||||
Замер (`/usr/bin/python3` + `csv.DictReader`, `encoding="utf-8-sig"`):
|
||||
|
||||
```
|
||||
DIFF-v6.csv 399 строк / 398 правок / 394 файла / 116 папок
|
||||
scope: outlier 86 · orphan 173 · infected 139
|
||||
field: album 394 · albumartist 4
|
||||
пустых old: 0 | пустых new: 0 | old==new: 0 | путей вне БД: 0
|
||||
```
|
||||
|
||||
Сверка с `navidrome-fresh.db` (7808 файлов) — расхождений нет. **Файл годен.**
|
||||
|
||||
### 🔴 НО задачу v6 НЕ закрывает — 394 из 7808 файлов (5%)
|
||||
|
||||
| Срез | Всего | Покрыто v6 |
|
||||
|---|---:|---|
|
||||
| Файлов в БД | 7808 | **394** |
|
||||
| Папок всего | 628 | — |
|
||||
| Папок 2+ файлов | 575 | — |
|
||||
| Папок 2+ с **разным** album | 83 | **83** ✅ |
|
||||
| Папок 2+ однородных | 492 | 0 — **НЕ пропуск** (old==new) |
|
||||
| Папок-одиночек | 53 | 30 (частично) |
|
||||
| Файлов Infected Mushroom | 244 | 135 |
|
||||
| Папок IM (одиночек 27) | 51 | 37 |
|
||||
|
||||
**Вывод: v6 закрывает 83 неоднородные папки полностью. Незакрыто — одиночки.**
|
||||
|
||||
### 🔴 37 ПАПОК-ОДИНОЧЕК с расхождением `album != имя папки`
|
||||
|
||||
Вычислено `/tmp/precise9.py` (`mode=ro`), полный список:
|
||||
|
||||
```
|
||||
IM (27 папок, правила Alex из блока «ПРАВИЛО ALEX ДЛЯ ОДИНОЧЕК»):
|
||||
(2001) Infected Mushroom - Wider (Domestic RMX) TALB='Wider (Domestic RMX)'
|
||||
(2003) Fly Agaric - I See Myself (…Remix) TALB='Unreleased Tracks'
|
||||
(2003) Hallucinogen - Gamma Goblins (…remix) TALB='Unreleased Tracks'
|
||||
(2003) Infected Mushroom - Birthday (DJ Goni Peles) TALB='Birthday (DJ Goni Peles Remix)'
|
||||
(2003) Infected Mushroom - PGM (Delirious Remix) TALB='P.G.M. (Delirious Remix)'
|
||||
(2004) Astrix - Coolio (…Remix) TALB='Unreleased Tracks'
|
||||
(2004) IM - Elation Station (Beat Hackers Remix) TALB='Elation Station'
|
||||
(2004) IM - I Wish (Skazi Remix) TALB='I Wish [skazi Remix] CDS'
|
||||
(2004) IM - Shakawkaw (Vibe Tribe Rmx) TALB='Shakawkaw (Vibe Tribe Rmx)'
|
||||
(2005) IM - Chaplin (Eskimo Rmx) TALB='Chaplin (Eskimo Rmx)'
|
||||
(2005) IM - I'm The Superviz'a (Toxical Rmx) TALB='CDS'
|
||||
(2005) IM - In The Mix (N-Joy) TALB='In The Mix (N-Joy) 10-12'
|
||||
(2005) IM - Symphonatic (Silent Hill Rmx) TALB='Promo'
|
||||
(2005) IM - Wider (Astrix Rmx) TALB='Promo'
|
||||
(2005) Yahel And IM - Electro Panic (Psycraft Remix) TALB='Electro Panic (PsyCraft Remix)'
|
||||
(2006) IM - Im the Supervisor (Shift Rmx) TALB='Im The Supervisor Shift Rmx (CDS)'
|
||||
(2007) IM - Becoming Insane (Chemical Trolls Rmx) TALB='Becoming Insane (Chemical Trolls Remix)'
|
||||
(2007) IM - Bust a Move (Aya Remix) TALB='Unreleased Tracks'
|
||||
(2007) IM - Dancing With Kadafi (Future Prophecy) TALB='Dancing With Kadafi (…)'
|
||||
(2007) IM - Deeply Disturbed (Astrix Mix) TALB='Deeply Disturbed (Astrix Mix)'
|
||||
(2007) IM - Institute of Science (Multi System Rmx) TALB='Institute Of Science (…)'
|
||||
(2007) IM - Suliman (RAZ Rmx) TALB='Suliman (RAZ Rmx)'
|
||||
(2009) IM - DJ Times Shortlist TALB='DJ Times Shortlist-SAT-18-11'
|
||||
(2012) IM – U r so fucked (GANDI Remix) TALB='U r so fucked (GANDI Remix)'
|
||||
IM Vs. The Prodigy - Supervized Firestarter TALB='Supervized Firestarter (…)'
|
||||
ИСКЛЮЧЕНИЯ Alex: 2016 - Liquid Smoke (Single) → 'Liquid Smoke' (без WEB)
|
||||
2016 - Nutmeg (Single) → 'Nutmeg'
|
||||
|
||||
НЕ-IM одиночки с расхождением (10):
|
||||
!Pop, Club, Любэ TALB='Radio' (файл в КОРНЕ категории)
|
||||
!Pop, Club, Любэ/!Radio/z Старое/disk/4 INSTRUMENTAL TALB='RADIO 4 INSTRUMENTAL'
|
||||
!Pop, Club, Любэ/!Radio/z Старое/disk_v2/4 INSTRUMENTAL TALB='RADIO 4 INSTRUMENTAL'
|
||||
!Retro/Андрей Миронов TALB='Лучшие песни… Александра Зацепина к 100-летию'
|
||||
!Retro/Тамара Миансарова TALB='Храбрый Зайчик. Песни для детей'
|
||||
!Rock&Folk/Otava Yo TALB='Ой, Дуся, ой, Маруся'
|
||||
!Rock&Folk/Александр Пушной TALB='Лето прошло...'
|
||||
!Rock&Folk/Наутилус Помпилиус TALB='Золотой век' ← ВНИМАНИЕ: папка НЕ одиночка
|
||||
!Рэп TALB='Вдох-выдох' (файл в КОРНЕ категории)
|
||||
!Рэп/Eminem,50cent/The Slim Shady LP TALB='The Slim Shady LP CD1'
|
||||
```
|
||||
|
||||
> 🔴 **ПИТФОЛЛ: `!Rock&Folk/Наутилус Помпилиус` — НЕ одиночка.** 80 файлов, 9 подпапок
|
||||
> (`De Luxe collection` 20 · `Подъём` 12 · `Атлантида` 11 · `Gold Age` 10 · `Раскол` 10 ·
|
||||
> `1998 Яблокитай` 9 · `1989 …Столицы` 4 · `2000 - песни` 3). Одиночка — только
|
||||
> `Гудбай Америка.mp3` в корне папки (`TALB='Золотой век'`). Вывод «одиночка» из паттерна
|
||||
> пути **без подсчёта файлов** — ошибка; всегда считать `len(files)` в папке.
|
||||
|
||||
### 🔴 РАЗНОГЛАСИЕ ПРАВИЛ — запись в DIFF-v6.csv НЕ выполнена
|
||||
|
||||
Alex потребовал добавить одиночек в `DIFF-v6.csv` вручную. Измерение вскрыло, что
|
||||
**два разных правила дают два разных ответа**, и выбор — не моё решение:
|
||||
|
||||
| | Правило | Результат на `(2001) Infected Mushroom - Wider (Domestic RMX)` |
|
||||
|---|---|---|
|
||||
| **A** | `album` = имя папки **как есть** (с годом и артистом) | `2001) Infected Mushroom - Wider (Domestic RMX` |
|
||||
| **B** | `album` = имя папки **БЕЗ года и артиста**; для папок с 1 файлом — имя **РОДИТЕЛЬСКОЙ** папки | `Wider (Domestic RMX)`, а для IM → `Remixes` |
|
||||
|
||||
Правило **B** — это то, что записано в доке в блоке «ПРАВИЛО ALEX ДЛЯ ОДИНОЧЕК» (строка 188):
|
||||
`папка с 1 файлом -> album = имя РОДИТЕЛЬСКОЙ папки (Remixes, Mixes)`.
|
||||
|
||||
Правило **A** — то, что даёт автоматический проход `album = clean(имя папки)`.
|
||||
|
||||
**Число строк зависит от правила:** A → 37, B → другой список и другое число.
|
||||
|
||||
> 🔴 **БЛОКЕР: без ответа Alex (A или B) строки в `DIFF-v6.csv` НЕ вписаны.**
|
||||
> Вписать наугад = создать новый класс дефекта.
|
||||
|
||||
### 🔴 ПИТФОЛЛ: обрезанный вывод `head -N` принят за полный список
|
||||
|
||||
Первый проход дал «9 файлов брака» — это был результат `head -80` по списку 27 одиночек.
|
||||
Полный пересчёт тем же критерием дал **37**. **Правило: прежде чем называть Alex число —
|
||||
убедиться, что вывод не обрезан; считать длину в скрипте, а не глазами по хвосту.**
|
||||
|
||||
### 🛠 ИНСТРУМЕНТЫ ЭТОЙ ВОЛНЫ
|
||||
|
||||
| Файл | Назначение |
|
||||
|---|---|
|
||||
| `/tmp/read_9.py` | чтение 9 папок из БД (`mode=ro`) — `title/artist/album/album_artist/track_number` |
|
||||
| `/tmp/precise9.py` | ✅ **точный замер**: одиночки с `album != имя папки` + разбор Наутилуса по подпапкам |
|
||||
| `~/Downloads/music-tags/navidrome-fresh.db` | источник истины (локальный снимок БД Navidrome, 7808 файлов) |
|
||||
|
||||
Приём доступа к БД (без TCC-промптов и без записи в рабочую базу):
|
||||
```python
|
||||
con = sqlite3.connect("file:%s?mode=ro" % DB, uri=True)
|
||||
```
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[family/how-to/jellyfin-config]] — живой инстанс Jellyfin на Taiga, план добавления Music-библиотеки
|
||||
|
||||
Reference in new issue
Block a user