[2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/tech/id3-tag-repair.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-27 15:04:49 +06:00
1 parent 85f0f009dd
commit 62c21e4d33
2 files changed
+136 -9

No files matched your search

@@ -4,7 +4,7 @@ created: '2026-09-27'
updated: '2026-09-27'
type: plan
namespace: personal
status: session13-collapse-fixed-radio-album-fixed-disk-naming-open
status: session14-junk-album-and-track-cleaned-171-rows
tags:
- music
- metadata
@@ -55,7 +55,79 @@ related:
> ✅ Класс `A2` **дочищен**: `find_va_misuse.py` → 0, `find_va_author.py` → остались только
> 2 защитимые папки (`Блестящие, Фриске`, `Eminem,50cent`).
## 🟢 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 13 (2026-09-27) — читать это первым
## 🟢 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 14 (2026-09-27) — читать это первым
>
> ```
> APPLY-PLAN.csv 7861 строка md5 f16163f65336afca99b8d8087c6945f5
> DIFF-new-vs-38.csv 2901 строка md5 0607c1152c8a43028de2d6ac84eb30ba
> tag-fix-plan.csv 7861 строка md5 203726ebfd2814e2328636df31337238 (НЕ ПРАВИТЬ)
> ```
>
> **Состав диффа:** `ПАПКА` · `ТРЕК` · `НЕТ-В-38` 41 · `ТОЛЬКО-В-38` 85.
> Полнота: `ВСЕГО правок (трек-уровень) 18804 · OK: потерь нет`.
>
> 🔴 **СЕССИЯ 14 — ДВА КЛАССА МУСОРА ВЫЧИЩЕНЫ (171 строка).**
>
> ### Класс 1: мусорный `new_album` — 20 строк
> Корень: план копирует `cur_album` из тега **без фильтра**. Что вычищено:
>
> | Значение в теге | Куда попало | Стало | Источник мусора |
> |---|---|---|---|
> | `Non spécifié`, `NULL` | Benassi Bros (2) | `Benassi Bros` | франц. теггер / строка «NULL» |
> | `2005 ` | Банд Эрос (1) | `Банд Эрос` | только-год в теге |
> | `no title` | Муммий Тролль (1) | `Муммий Тролль` | плейсхолдер теггера |
> | `~melody.az - КняZz - Корсар~` | КняZz (1) | `КняZz` | водяной знак сайта + склейка |
> | ` mix ` | Каста (1) | `Каста` | служебная пометка |
> | `NoTitLe` | НТЛ (1) | `НТЛ` | плейсхолдер |
> | `Album` | Пилот/misc (1) | `Пилот` | плейсхолдер |
> | `New` | Король и Шут (1) | `Король и Шут` | техпапка |
> | `2007` | Pushnoy.ru/2007 (10) | `Pushnoy.ru` | год-подпапка |
> | `Íåèçâåñòíîå íàçâàíèå` | !Детские/Из чего же (1) | `` (пусто) | CP1251→UTF8 битьё |
>
> **Правило целевого значения:** имя корня артиста = последний сегмент `folder`;
> если корень — категория (`!*`) или папка-мусорка (`misc`/`base`/`plux`/`старые`) →
> берём артиста (сегмент после категории). `Pushnoy.ru` — сайт-источник, все подпапки
> (`2007`/`старые`/`NEW`) не альбомы → `Pushnoy.ru`.
>
> Скрипт: `~/Downloads/music-tags/fix_junk_album.py` (dry-run по умолчанию).
> Верификация: `verify_junk_album.py` → **9/9 контрольных точек OK, остатков мусора 0**.
> Бэкап: `APPLY-PLAN.csv.bak-junkfix-*`.
>
> ### Класс 2: мусорный/битый `new_track` — 151 строка
>
> | Значение | строк | Диагноз | Стало |
> |---|---:|---|---|
> | `yes` | 20 | 🔴 **мой баг**: `fix_junk_album.py` писал `data[i][14]="yes"` — индекс 14 = `new_track`, а не `changed` (15) | `cur_track` / пусто |
> | `238` | 56 | `Красная Плесень`: один номер на все альбомы | номер из имени (`#3_02` → `2`) |
> | `117` | 34 | `Король и Шут`: один номер на 4 папки, номера нет нигде | пусто |
> | `236` | 11 | счётчик скачивания теггера **muzmo.ru** (`cur_album='[muzmo.ru]'`) | пусто |
> | `99`, `51`, `46` | 7 | теггер-сентинелы «номера нет» (+ уцелели из-за `continue` после ветки A) | пусто |
> | `204` | 2 | не-трек из имени файла (`204-Infected…`) | пусто |
> | `117/099/051/046` | 4 | порядковый номер сборника из имени | пусто |
> | `1/2/3/46` | 10 | одиночки НТЛ без номера | пусто |
>
> **Сентинелы-плейсхолдеры:** `99 · 51 · 46 · 117 · 238 · 236 · 204 · 0 · 999`.
> **Номер из имени файла** (в порядке приоритета): `^#\d+_(\d{1,2})[-_]` → `^(\d{1,3})[-_ ]\D`
> → `^(\d{1,3}) ` → `^0(\d{2})[_-]` → `^(\d{1,2})[_-]\D`.
>
> Скрипты: `fix_track_v3.py` (основной, 144 правки) + `fix_track_rest7.py` (добить 7
> пропущенных из-за `continue`). Верификация: `verify_track.py` → **все проверки 0/OK**.
> Бэкапы: `.bak-trackfinal-*`, `.bak-trackfinal2-*`.
>
> ### 🔴 МЕТОД-УРОК СЕССИИ 14: ВЕРИФИЦИРОВАТЬ СВОЙ ЖЕ СКРИПТ ПЕРЕЧИТЫВАНИЕМ, НЕ ЛОГИКОЙ
> Первый прогон отчитался «144 записано» и был **неполон**: `elif` в цикле пропускал
> сентинел-фильтр для строк, восстановленных из `yes`. `verify_track.py` (перечитать файл
> и сравнить с ожиданием) поймал 7 уцелевших. **Без верификации дефект ушёл бы в прод.**
>
> 🔴 **ИНДЕКСЫ КОЛОНОК `APPLY-PLAN.csv` (16 шт.):**
> `0 path · 1 folder · 2 class · 3 cur_title · 4 cur_artist · 5 cur_albumartist ·
> 6 cur_album · 7 cur_genre · 8 cur_track · 9 new_title · 10 new_artist ·
> 11 new_albumartist · 12 new_album · 13 new_genre · 14 new_track · 15 changed`.
> Всегда ставить `assert (H["new_track"], H["changed"]) == (14, 15)`.
>
> ---
> ## 🟢 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 13 (2026-09-27) — историческое
>
> ```
> APPLY-PLAN.csv 7861 строка md5 a6e440511e195668af2cee785e547fce
@@ -339,18 +411,24 @@ Alex указал на `Алиса в Стране Чудес (Диск2)/04` =
по mp3 (7861), поэтому эти форматы в него не попали by design.
- `НЕТ-В-38` (41) = есть в новом плане, не было в 38-м.
### 📌 Что делать дальше (порядок приоритета, обновлён в сессии 13)
### 📌 Что делать дальше (порядок приоритета, обновлён в сессии 14)
1. **Ответить на 8 вопросов по `album`** (см. «❓ ВОПРОСЫ К ALEX» в сессии 13) — особенно #4
(4 разных формата `album` внутри `!Radio`) и спор про `Benassi Bros`.
2. **Найти источник правила «`album` = имя корня папки»** — в бэкапах `APPLY-PLAN.csv.*` его НЕТ.
Проверить `tag-inventory3.csv`, `APPLY-PLAN-RAW.csv`, `archive/*`, `milestones/music-csv-2026-09-26/`.
3. **Дожать класс «жанр унаследован от `cur_genre`»** — `Enigma/Sleep` 13 строк `General Folk`
0. ✅ **ЗАКРЫТО в сессии 14:** мусорный `new_album` (20 строк) и мусорный `new_track` (151 строка).
`disk_v2/2 ALT,PUNK/HARD` → `RADIO 2 ALT,PUNK`. `disk/3 SHANSON/Трофим` — **не трогаем**
(Alex: «альбомы — это правильно»).
1. **Ответить на оставшиеся вопросы по `album`** — особенно #4 (4 разных формата `album`
внутри `!Radio`) и класс «`album` = название песни» (Алексин/Шалавы, Дискотека Авария).
2. **Дожать класс «жанр унаследован от `cur_genre`»** — `Enigma/Sleep` 13 строк `General Folk`
(Enigma = нью-эйдж/эмбиент, не фолк). Тот же корень дефекта, что и 26 исправленных строк.
3. **Остались неразобранными из ручного прохода `album`:** `z Другое, Enigma, Ленинград` →
`Сосни попса`; `detskiy_hor_benassi_satisfaction.mp3` → `Горячие Синглы 2004`;
`Бутусов & Ю-Питер/Девушка По Городу`; корни артистов (Жуки, Потап & Каменских, Света, Серёга)
с `album` = имя артиста.
4. **Решить судьбу 51 папки с рваной нумерацией** — но сначала: стоит ли вообще трогать
номера в подборках `!Radio`.
5. Перегенерировать `DIFF-new-vs-38.csv` после любых правок плана
(`python3 diff_new_vs_38.py > /tmp/log 2>&1`).
(`python3 diff_new_vs_38.py > /tmp/log 2>&1`) — **и всегда верифицировать свой скрипт
перечитыванием** (см. метод-урок сессии 14).
6. Применение плана к файлам — **отдельное «go»** от Alex, через `tagwriter:v2`
(см. `[[personal/plans/tagwriter-container]]`).
+49
View File
@@ -274,6 +274,55 @@ md5 out.csv && python3 gen.py > /tmp/run.log 2>&1 && md5 out.csv # MD5 обя
запятой, `$1`/`$4` уезжают в фрагмент имени папки. `scope` считается правильно (`ПАПКА`/`ТРЕК`
первое поле), а `field` — нет. Только `csv.DictReader`.
### 🔴 D10 — запись по ЧИСЛОВОМУ индексу вместо имени колонки затирает соседнее поле
`APPLY-PLAN.csv` — 16 колонок; `changed` = **индекс 15**, а `new_track` = **14**.
Скрипт сессии 14 записал `data[i][14] = "yes"`, полагая, что это `changed` → у 20 строк
`new_track` затёрся на `"yes"`, а `changed` остался прежним. Обнаружено только верификацией.
**Правило:** всегда `H = {c: i for i, c in enumerate(hdr)}` + `assert` на позиции ключевых
колонок. Карта индексов `APPLY-PLAN.csv`:
`0 path · 1 folder · 2 class · 3 cur_title · 4 cur_artist · 5 cur_albumartist · 6 cur_album ·
7 cur_genre · 8 cur_track · 9 new_title · 10 new_artist · 11 new_albumartist · 12 new_album ·
13 new_genre · 14 new_track · 15 changed`.
Обязательный `assert (H["new_track"], H["changed"]) == (14, 15)`.
### 🔴 D11 — значения-СЕНТИНЕЛЫ в тегах: `99 / 51 / 46 / 117 / 238 / 236 / 204`
Теггеры и сайты пишут в поля не «пусто», а магические числа. План копирует их как данные:
| Значение | Смысл | Где найдено |
|---|---|---|
| `99`, `51`, `46` | «номера нет» (сентинел теггера) | все папки, одиночки |
| `236` | счётчик скачанных файлов теггера **muzmo.ru** | `cur_album='[muzmo.ru]'`, 11 строк |
| `204` | не-трек из имени (`204-Infected…`) | Infected Mushroom |
| `238` | один номер на ВСЕ альбомы (Красная Плесень) | 56 строк, 5 альбомов |
| `117` | один номер на 4 разные папки (Король и Шут) | 34 строки |
**Признак сентинела:** одно и то же крупное число у МНОГИХ файлов разных альбомов/папок.
**Проверка:** `Counter(cur_track)` по папке; если одно значение >= 5 файлов и альбомы разные — мусор.
**Правило:** сентинел → пусто; но **сначала** попробовать вытащить номер из имени файла.
### 🔴 D12 — мусорные значения `album` из тега: плейсхолдеры, годы, водяные знаки
План копирует `cur_album` **без фильтра**. Найдено и вычищено 20 строк (сессия 14):
| Значение | Тип |
|---|---|
| `Non spécifié`, `Non specifie` | плейсхолдер (франц. «не указано») |
| `NULL`, `NoTitLe`, `no title`, `Album`, `New`, `mix` | плейсхолдер теггера/техпапка |
| `Неизвестное название` (`Íåèçâåñòíîå…`) | тот же плейсхолдер в CP1251-битье |
| `2005 `, `2007` | только-год |
| `~melody.az - КняZz - Корсар~` | водяной знак сайта + склейка артист-трек |
**Целевое значение = имя корня артиста** (последний сегмент `folder`); если корень —
категория (`!*`) или папка-мусорка (`misc`/`base`/`plux`/`старые`) → артист (сегмент
после категории). `Pushnoy.ru` — сайт-источник: все подпапки (`2007`/`старые`/`NEW`)
не альбомы → `Pushnoy.ru`.
**Скрипт:** `~/Downloads/music-tags/fix_junk_album.py` (dry-run по умолчанию, `--apply` пишет).
**Верификация:** `verify_junk_album.py` — перечитывает файл, сверяет контрольные точки.
## 🔴 Классы порчи `albumartist` (сессия 7, 2026-09-27)
Три класса, найденных сплошным поиском по `APPLY-PLAN.csv`. Все три — из-за того, что правило