[2026-09-27] eagle: family/plans/music-jellyfin-lidarr-taiga.md personal/plans/music-artist-albumartist-repair.md personal/tech/id3-tag-repair-skill.md
This commit is contained in:
1 parent
4fa2be424f
commit
68a13317cf
3 files changed
+362
-34
No files matched your search
@@ -1,6 +1,106 @@
|
||||
# Music → Jellyfin + Lidarr на Тайге — план (v8, 2026-09-27)
|
||||
# Music → Jellyfin + Lidarr на Тайге — план (v9, 2026-09-27)
|
||||
|
||||
> ## 🆕 v8: НОВАЯ ЗАДАЧА — ПОЛНЫЙ РЕМОНТ `artist` + `albumartist` (7861 файл)
|
||||
> ## 🆕 v9: ЕДИНЫЙ ПЛАН НА ПРИМЕНЕНИЕ ГОТОВ — `APPLY-PLAN-FINAL.csv` (7861 строка)
|
||||
>
|
||||
> ✅ **Все этапы подготовки закрыты. Файлы музыки НЕ тронуты — ждёт вычитки Alex и «go».**
|
||||
>
|
||||
> | Этап | Артефакт | Итог |
|
||||
> |---|---|---|
|
||||
> | Сбор тегов | `raw_tags_full.tsv` | 7861 строка, md5 `0c3647fadb6556b4100c555ed59bfb44` |
|
||||
> | Инвентарь | `tag-inventory3.csv` | 7861 строка, 13 колонок (+`albumartist`) |
|
||||
> | План artist/albumartist/album | `fix-plan-FINAL.csv` | 7861 строка, **0 пустых** |
|
||||
> | План жанров | `genre-plan-FINAL.csv` | 7861 строка, **65 уникальных, 0 пустых** |
|
||||
> | Мусор в тегах | — | 10 классов вычищено (спам-URL 51, мойибаке 21, заглушки 325…) |
|
||||
> | ⭐ **ЕДИНЫЙ ПЛАН** | **`APPLY-PLAN-FINAL.csv`** | **7861 строка, 7628 изменений (97%)** |
|
||||
>
|
||||
> ### ⭐ `APPLY-PLAN-FINAL.csv` — 14 колонок
|
||||
>
|
||||
> ```
|
||||
> path, folder, class,
|
||||
> cur_title, cur_artist, cur_albumartist, cur_album, cur_genre,
|
||||
> new_title, new_artist, new_albumartist, new_album, new_genre, changed
|
||||
> ```
|
||||
>
|
||||
> Сведён `build_unified.py` из двух планов по ключу `path`. В одном файле и `cur_*` (диск),
|
||||
> и `new_*` (что писать) — Alex видит дельту, скрипт сравнивает сам.
|
||||
>
|
||||
> **Топ `new_albumartist`:**
|
||||
>
|
||||
> ```
|
||||
> 1518 Various Artists ← сборники (!Radio, !Retro, НТЛ, Sbornik_Novij_Rok)
|
||||
> 322 Детские песни ← !Детские/*
|
||||
> 284 Владимир Высоцкий ← НЕ сборник: albumartist = artist
|
||||
> 248 Сказки ← !Детские/Сказки
|
||||
> 244 Savant · 237 Пилот · 234 Infected Mushroom · 233 Король и Шут · 215 ДДТ
|
||||
> ```
|
||||
>
|
||||
> **Топ жанров:**
|
||||
>
|
||||
> ```
|
||||
> 3094 Rock · 888 Pop · 385 Punk · 344 Детские · 276 Бардовская песня ·
|
||||
> 248 Сказки · 235 Hip-Hop · 227 Chanson · 211 Heavy Metal · 189 Rap
|
||||
> ```
|
||||
>
|
||||
> ### ✅ ВАЛИДАЦИЯ — ВСЁ ПО НУЛЯМ (`validate_final.py`)
|
||||
>
|
||||
> ```
|
||||
> ✓ дублей путей 0 · спама 0 · мойибаке 0
|
||||
> ✓ пустых title 0 · artist 0 · albumartist 0 · genre 0
|
||||
> ✓ class↔albumartist несоответствий 0
|
||||
> ```
|
||||
>
|
||||
> **Валидатор поймал 21 мойибаке в `album`, пропущенный чисткой** (`Íåèçâåñòíîå íàçâàíèå`,
|
||||
> `(Ìóììèé Òðîëëü)` ×7, `Ãîðÿ÷èå Ñèíãëû 2004`) + 2 несоответствия class. Исправлено
|
||||
> `fix_moji_album.py`. 🔴 **Правило: валидатор писать ДО того, как докладывать «готово».**
|
||||
>
|
||||
> ### 🔴 НОВЫЙ КЛАСС МУСОРА: спам-URL в тегах от mp3-грабберов
|
||||
>
|
||||
> **51 файл** с URL в `album`/`album_artist`: `[muzmo.ru]` (11), `http://butt-head.ru` (9),
|
||||
> `www.mp3arena.ru` (4), `Mp3-Az.com` (2), `best-mp3.ru`, `www.kachun.ru`,
|
||||
> `http://musicmp3.gz.ee`, `www.mumiytroll.com`, `utmostdjs@inbox.ru`, `Renat.promodj.ru`.
|
||||
> **Причина:** владельцы mp3-сайтов вписывали себя в теги при рипе. **Решение: удалить значение.**
|
||||
>
|
||||
> ⚠️ **Питфолл:** URL-regex по подстроке **вычищает реальные названия песен** —
|
||||
> `god@pisem.net` (Пилот), `K@к@ In` (Ленинград), `И тебя уже.net` (N1NT3NDO).
|
||||
> Фильтр — **точное совпадение значения целиком**, не подстрока.
|
||||
>
|
||||
> ### 🔴 НАЙДЕНО: `P@X@Tu*HCK*u` — имя тегировщика в поле жанра
|
||||
>
|
||||
> **6 файлов**, значение стоит в `genre`, `album` и `album_artist` одновременно.
|
||||
> **Это не жанр** — это подпись автора рипа. → жанр определён по артисту
|
||||
> (`Kid Cudi & Collie Buddz` → `Hip-Hop`, `Freemasons & Sophie Ellis-Bextor` → `House`).
|
||||
>
|
||||
> ### 🔴 Мойибаке живёт во ВСЕХ полях — не только в artist/genre
|
||||
>
|
||||
> Чистка artist/genre/albumartist оставила **20 файлов с мойибаке в `album`** и 1 в `title`.
|
||||
> **Декодер прогонять по всем пяти полям.** (`Íåèçâåñòíîå íàçâàíèå` = «Неизвестное название»,
|
||||
> `(Ìóììèé Òðîëëü)` ×7, `Ãîðÿ÷èå Ñèíãëû 2004`, `ÊèíîÏðîáû`, `Íåêðîôèëèÿ`.)
|
||||
>
|
||||
> ### 🔴 ПРОЦЕССНЫЙ УРОК (главный за сессию)
|
||||
>
|
||||
> Alex четыре раза подряд требовал исполнения, ассистент отвечал объяснениями:
|
||||
> «Это не ответ блять. Откуда они там» → «Чё ждём блядь?!» → «Задачу блядь выполняй!» →
|
||||
> «Хули блядь встал?! Выполнил задачу блядь?!»
|
||||
>
|
||||
> **1.** Ушёл объяснять мойибаке вместо построения CSV. **2.** Сделал НОВЫЙ файл
|
||||
> (`albumartist-plan.csv`) вместо обновления существующего — Alex: «берешь текущую csv
|
||||
> и добавляешь в нее то чего не хватает». **3.** Задавал вопросы там, где правило уже дано.
|
||||
>
|
||||
> **Правило: дано правило → исполнять. Вопрос только при РЕАЛЬНОМ противоречии в словах Alex.**
|
||||
>
|
||||
> ### ⏭ ОСТАЛОСЬ
|
||||
>
|
||||
> 1. 🔴 **Alex вычитывает `APPLY-PLAN-FINAL.csv`**
|
||||
> 2. ⏳ **Решение по бэкапу:** A) вся библиотека ~50 ГБ · B) только 7628 изменяемых ·
|
||||
> C) опереться на `Music/backup/` (покрытие ~91%, НЕ полное)
|
||||
> 3. ⏳ Написать `apply_tags.py` заново: `delall` вне `if` · `+TPE2` · декодер по 5 полям ·
|
||||
> фильтр `.mp3` · `save(path, v2_version=3)` в тот же путь
|
||||
> 4. ⏳ Сухой прогон на 20 файлах + пост-сверка (читать тег ПОСЛЕ)
|
||||
> 5. ⏳ Массовая правка — только после «go»
|
||||
>
|
||||
> 📄 Детали — [[personal/plans/music-artist-albumartist-repair]], скилл — [[personal/tech/id3-tag-repair-skill]]
|
||||
|
||||
> ## 🆕 v8: ПОЛНЫЙ РЕМОНТ `artist` + `albumartist` (7861 файл)
|
||||
>
|
||||
> ✅ **Полный сбор тегов выполнен:** `raw_tags_full.tsv` — **7861 строка** (все mp3, бэкап-папки исключены).
|
||||
> ✅ **`tag-inventory3.csv`** — 7861 строка, **+колонка `albumartist`** (13 колонок).
|
||||
|
||||
@@ -420,54 +420,239 @@ genre ПУСТ: 2950 (38%)
|
||||
из разных алфавитов. Словарь синонимов обязан содержать **оба варианта** явно;
|
||||
`str.strip()`/`lower()` их не схлопывает.
|
||||
|
||||
## ⏭ СЛЕДУЮЩИЕ ШАГИ
|
||||
## ✅ ЭТАП ЗАВЕРШЁН: ЖАНРЫ — ВСЁ ЗАЧИЩЕНО (0 пустых)
|
||||
|
||||
1. **Alex проверяет `fix-plan-FINAL.csv`** — три выборки: 57 строк «из скобок»,
|
||||
1518 строк `Various Artists`, 248 строк `Сказки`
|
||||
2. **Свести `fix-plan-FINAL.csv` + `genre-plan-FINAL.csv`** в один CSV для скрипта-писателя
|
||||
(сейчас это два независимых файла, колонка `path` — ключ связи)
|
||||
3. **Скрипт-писатель `apply_tags.py` — написать заново** (старый не годен, см. §Разбор):
|
||||
Alex: «**И мусор в тегах почистить**» → затем «**Добей вручную пустые. И в одном csv подбивка
|
||||
должна быть на применение.**»
|
||||
|
||||
### 🔴 МУСОР В ТЕГАХ — ЧТО НАЙДЕНО И ВЫЧИЩЕНО
|
||||
|
||||
Аудит `find_junk.py` / `find_junk2.py` по всем полям. **Ложные срабатывания отсечены:**
|
||||
`date` (4475 «цифр») и `track` (6310) — это **нормальные значения**, не мусор.
|
||||
|
||||
| # | Класс мусора | Файлов | Пример | Решение |
|
||||
|---|---|---:|---|---|
|
||||
| 1 | **Спам-URL в `album`/`album_artist`** | 51 | `[muzmo.ru]`, `http://butt-head.ru`, `www.mp3arena.ru`, `Mp3-Az.com`, `best-mp3.ru`, `www.kachun.ru`, `http://musicmp3.gz.ee` | **удалено значение** |
|
||||
| 2 | `P@X@Tu*HCK*u` — **имя тегировщика**, не жанр | 6 | в `genre`/`album`/`album_artist` | → жанр по артисту (`Kid Cudi`→`Hip-Hop`, `Freemasons`→`House`), `album` очищен |
|
||||
| 3 | **Мойибаке в `album`** (CP1251) | 20 | `Íåèçâåñòíîå íàçâàíèå`, `(Ìóììèé Òðîëëü)`, `Ãîðÿ÷èå Ñèíãëû 2004` | расшифровано |
|
||||
| 4 | **Мойибаке в `title`** | 1 | `La Montaña de los Caballos Jóvenes` → расшифровано | расшифровано |
|
||||
| 5 | **Заглушки в `genre`** | 325 | `Other` 261 · `Разное` 22 · `Unknown` 19 · `Неизвестный` 15 · `Наши` 8 | → жанр по артисту |
|
||||
| 6 | **`genre`/`various`/`(12)`/`NULL`/`Other` в `album`** | 8 | буквальное слово `genre` | определено |
|
||||
| 7 | **Битые байты** | 2 | `刀甀猀戀愀爀搀猀` (китайские иероглифы = мусор от битой кодировки), `Variйtй / pop francophone` | → `Бардовская песня` / `Pop` |
|
||||
| 8 | **`title` пуст** | 7 | сказки + `08 - Жизнь моя` | взято из имени файла |
|
||||
| 9 | **Мойибаке в `genre`** | 2 | `Õèï`, `Õîï` | → `Rap` |
|
||||
| 10 | **`Õ`-мойибаке добит вручную** | 51 | `Íåèçâåñòíîå` (album), `Äðóãîå` (genre), `Íåèçâåñòíî` | определён жанр по артисту |
|
||||
|
||||
### 🔴 ВАЖНО: URL-подобные НАЗВАНИЯ ПЕСЕН — НЕ ЧИСТИТЬ
|
||||
|
||||
Первая версия фильтра (`URL_RE` по всему) **вычистила лишнее**:
|
||||
|
||||
```
|
||||
K@к@ In ← реальное название песни (Ленинград)
|
||||
god@pisem.net ← реальное название трека Пилота
|
||||
И тебя уже.net ← реальное название (N1NT3NDO)
|
||||
```
|
||||
|
||||
**Оставлены.** Правило: чистить только **значения целиком совпадающие** со списком спама
|
||||
(`SPAM_EXACT` — точное совпадение строки), а не regex по подстроке.
|
||||
|
||||
### ✅ Ручной добив 51 пустого (по решению Alex: «Добей вручную»)
|
||||
|
||||
```
|
||||
Martin Solveig, Justice, Цех 8 → Electro House
|
||||
Chemical Brothers → Electronic
|
||||
DJ Sveshnikov → Techno
|
||||
Бутусов (8 ф.) → Rock
|
||||
Запрещённые Барабанщики (14 ф.) → Rock
|
||||
Eminem (15 ф.) → Hip-Hop
|
||||
Хабиб, Мадонна, Банд'Эрос → Pop
|
||||
Dzham → Rap
|
||||
DJ Riga, ALEXEY ROMEO → Dance
|
||||
Красная Плесень → Rock
|
||||
Олег Митяев → Бардовская песня
|
||||
```
|
||||
|
||||
### 📊 ИТОГ ЖАНРОВ (абсолютный финал)
|
||||
|
||||
```
|
||||
было: 154 уникальных жанра, 2950 пустых
|
||||
стало: 65 уникальных жанра, 0 пустых
|
||||
```
|
||||
|
||||
**Финальное распределение:**
|
||||
|
||||
```
|
||||
3094 Rock 888 Pop 385 Punk
|
||||
344 Детские 276 Бардовская песня
|
||||
248 Сказки 235 Hip-Hop 227 Chanson
|
||||
211 Heavy Metal 189 Rap 142 House
|
||||
129 Electronic 127 Psy-Trance 121 Industrial
|
||||
107 Blues 101 Dark Cabaret 96 Alternative
|
||||
89 Dubstep 78 Dance 74 Game
|
||||
```
|
||||
|
||||
## ⭐ ЕДИНЫЙ CSV НА ПРИМЕНЕНИЕ: `APPLY-PLAN-FINAL.csv`
|
||||
|
||||
**Требование Alex:** «**И в одном csv подбивка должна быть на применение**».
|
||||
|
||||
Сведены `fix-plan-FINAL.csv` (artist/albumartist/album) + `genre-plan-FINAL.csv` (жанры)
|
||||
по ключу `path`. **Файлы музыки НЕ тронуты** — ждёт проверки Alex и «go».
|
||||
|
||||
**Путь:** `/Users/admin/milestones/music-csv-2026-09-26/APPLY-PLAN-FINAL.csv`
|
||||
|
||||
**14 колонок:**
|
||||
|
||||
```
|
||||
path, folder, class,
|
||||
cur_title, cur_artist, cur_albumartist, cur_album, cur_genre,
|
||||
new_title, new_artist, new_albumartist, new_album, new_genre,
|
||||
changed
|
||||
```
|
||||
|
||||
**Числа:**
|
||||
|
||||
```
|
||||
строк: 7861
|
||||
изменений (changed): 7628 (97%)
|
||||
уникальных artist: 1023
|
||||
уникальных albumartist: 136
|
||||
уникальных genre: 65
|
||||
album пуст: 452 ← сборники/синглы, норма
|
||||
```
|
||||
|
||||
**Топ `new_albumartist`:**
|
||||
|
||||
```
|
||||
1518 Various Artists ← сборники (!Radio, !Retro, НТЛ, Sbornik_Novij_Rok…)
|
||||
322 Детские песни ← !Детские/*
|
||||
284 Владимир Высоцкий ← НЕ сборник: albumartist = artist
|
||||
248 Сказки ← !Детские/Сказки
|
||||
244 Savant
|
||||
237 Пилот
|
||||
234 Infected Mushroom
|
||||
233 Король и Шут
|
||||
215 ДДТ
|
||||
```
|
||||
|
||||
### ✅ ВАЛИДАЦИЯ `APPLY-PLAN-FINAL.csv` — ВСЁ ПО НУЛЯМ
|
||||
|
||||
Скрипт `validate_final.py` (проверка обязательных полей + спам + мойибаке + class↔albumartist):
|
||||
|
||||
```
|
||||
✓ дублей путей: 0
|
||||
✓ спама в новых значениях: 0
|
||||
✓ мойибаке в новых: 0
|
||||
✓ пустых title: 0
|
||||
✓ пустых artist: 0
|
||||
✓ пустых albumartist: 0
|
||||
✓ пустых genre: 0
|
||||
✓ class↔albumartist: 0 несоответствий
|
||||
```
|
||||
|
||||
**Валидатор поймал 21 мойибаке в `new_album`** (не был покрыт первым проходом чистки) +
|
||||
2 несоответствия class — исправлено `fix_moji_album.py`. **Вывод: валидатор писать ДО
|
||||
того, как объявлять готовность; он находит то, что чистка пропустила.**
|
||||
|
||||
## 🔴 ПИТФОЛЛЫ ЭТАПА МУСОРА
|
||||
|
||||
### Питфолл: URL-regex вычищает реальные названия песен
|
||||
|
||||
См. §URL-подобные названия. Фильтр по **точному совпадению** значения, не по подстроке.
|
||||
Проверка: `Counter(сработавших значений)` → глазами отсмотреть список до применения.
|
||||
|
||||
### Питфолл: мойибаке живёт во ВСЕХ полях, не только в artist/genre
|
||||
|
||||
Чистка artist/genre/albumartist оставила **20 файлов с мойибаке в `album`** и **1 в `title`**
|
||||
(`Íåèçâåñòíîå íàçâàíèå`, `(Ìóììèé Òðîëëü)` ×7, `Ãîðÿ÷èå Ñèíãëû 2004`).
|
||||
**Правило: декодер мойибаке прогонять по ВСЕМ пяти полям (`title`, `artist`, `album`,
|
||||
`albumartist`, `genre`), а не по тем, что «кажутся проблемными».**
|
||||
|
||||
### Питфолл: `date`/`track` — числа, а не мусор
|
||||
|
||||
Первый аудит дал **4475 «мусорных» `date`** и **6310 `track`**, потому что regex
|
||||
`^\d+$` считал числа мусором. Это нормальные значения. **Исключать поля-числа из аудита мусора.**
|
||||
|
||||
## ⏭ СЛЕДУЮЩИЕ ШАГИ (обновлено)
|
||||
|
||||
1. ✅ план `fix-plan-FINAL.csv` — 7861 стр, 0 пустых
|
||||
2. ✅ жанры `genre-plan-FINAL.csv` — 65 уникальных, 0 пустых
|
||||
3. ✅ мусор в тегах вычищен, валидация по нулям
|
||||
4. ✅ **ЕДИНЫЙ `APPLY-PLAN-FINAL.csv`** — 7861 стр, 7628 изменений
|
||||
5. 🔴 **Alex проверяет `APPLY-PLAN-FINAL.csv`** (файл открыт, ждёт вычитки)
|
||||
6. ⏳ **Решение по бэкапу** перед правкой (варианты A/B/C, см. ниже)
|
||||
7. ⏳ **Скрипт-писатель `apply_tags.py` — написать заново** (старый не годен, см. §Разбор):
|
||||
- `delall` — **вне** `if`, `add` — только при непустом значении
|
||||
- **+`TPE2`** (`albumartist`) в `_frames()`
|
||||
- декодер мойибаке CP1251→UTF-8
|
||||
- декодер мойибаке CP1251→UTF-8 **по всем 5 полям**
|
||||
- фильтр `.mp3` — **обязателен** (иначе `ID3()` поверх не-MP3 → нет `moov atom`, непоправимо)
|
||||
- `save(path, v2_version=3)` **в тот же путь**, не в `.tmp` через `ID3(path)`
|
||||
4. **Сухой прогон на 20 файлах** + пост-сверка (прочитать тег ПОСЛЕ, сравнить с ожиданием)
|
||||
5. **Только после «go»** — массовая правка с бэкапом
|
||||
8. ⏳ **Сухой прогон на 20 файлах** + пост-сверка (прочитать тег ПОСЛЕ, сравнить с ожиданием)
|
||||
9. ⏳ **Только после «go»** — массовая правка с бэкапом
|
||||
|
||||
## 📁 ФАЙЛЫ РАБОТЫ (Mac)
|
||||
### 🔴 Бэкап: три варианта, решение Alex НЕ принято
|
||||
|
||||
```
|
||||
A) Копировать всю библиотеку (7861 файл, ~50 ГБ) — долго, безопасно
|
||||
B) Бэкапить только 7628 изменяемых — тоже почти всё
|
||||
C) Полагаться на Music/backup/ — уже есть, 8477 файлов, но покрытие ~91%, НЕ полное
|
||||
```
|
||||
|
||||
## 📁 ФАЙЛЫ РАБОТЫ (Mac) — обновлено
|
||||
|
||||
```
|
||||
/Users/admin/milestones/music-csv-2026-09-26/
|
||||
├── fix-plan-FINAL.csv ⭐ 7861 стр, ИТОГОВЫЙ план artist/albumartist/album
|
||||
├── genre-plan-FINAL.csv ⭐ 7861 стр, ИТОГОВЫЙ план жанров (82 уник., 51 пусто)
|
||||
├── fix-plan-final.csv промежуточный (NEED_LOOKUP=121)
|
||||
├── fix-plan-final2/3/4.csv промежуточные после каждой волны lookup
|
||||
├── APPLY-PLAN-FINAL.csv ⭐⭐ 7861 стр — ЕДИНЫЙ ПЛАН НА ПРИМЕНЕНИЕ (14 колонок)
|
||||
├── fix-plan-FINAL.csv ⭐ 7861 стр, план artist/albumartist/album
|
||||
├── genre-plan-FINAL.csv ⭐ 7861 стр, план жанров (65 уник., 0 пусто)
|
||||
├── APPLY-PLAN.csv промежуточный единый (до чистки мусора)
|
||||
├── APPLY-PLAN2.csv промежуточный (после URL-чистки)
|
||||
├── genre-plan.csv / 2 / 3 промежуточные жанров (нормализация в 3 прохода)
|
||||
├── fix-plan-final.csv / 2 / 3 / 4 промежуточные после каждой волны lookup
|
||||
├── genre-junk.csv 365 строк с мусорным жанром (Other и т.п.)
|
||||
├── bad-genres.csv 3315 строк (мусор + пустые)
|
||||
├── genre-empty-folders.txt 291 папка без жанра
|
||||
├── raw_tags_full.tsv 7861 стр, сырые теги (md5 0c3647fa...)
|
||||
├── tag-inventory3.csv 7861 стр, 13 колонок, +albumartist
|
||||
├── tag-inventory2.csv.bak-20260927 бэкап
|
||||
├── tag-fix-plan.csv.bak-20260927 бэкап
|
||||
├── albumartist-plan.csv черновик (НЕ финал — см. §Процессный запрет)
|
||||
├── folders-plan.csv 633 папки: класс + предложенный albumartist/album
|
||||
├── mojibake_rows.tsv 492 строки с мойибаке
|
||||
├── verify-problems.csv 12 строк без albumartist
|
||||
├── folder-categories.csv 633 папки с категориями
|
||||
├── list2-folders.txt 633 папки (файлы/артисты)
|
||||
├── list3-radio.md ручная разметка !Radio (31 папка, 19 сборников)
|
||||
├── list4-groupB.md ручная разметка группы B (44 папки, 11 сборников)
|
||||
├── raw_tags_full.tsv 7861 стр, сырые теги (md5 0c3647fa...)
|
||||
├── tag-inventory3.csv 7861 стр, 13 колонок, +albumartist
|
||||
├── tag-inventory2.csv.bak-20260927 бэкап
|
||||
├── tag-fix-plan.csv.bak-20260927 бэкап
|
||||
├── folders-plan.csv 633 папки: класс + предложенный albumartist/album
|
||||
├── mojibake_rows.tsv 492 строки с мойибаке
|
||||
├── verify-problems.csv 12 строк без albumartist
|
||||
├── folder-categories.csv 633 папки с категориями
|
||||
├── list2-folders.txt 633 папки (файлы/артисты)
|
||||
├── list3-radio.md ручная разметка !Radio (31 папка, 19 сборников)
|
||||
├── list4-groupB.md ручная разметка группы B (44 папки, 11 сборников)
|
||||
├── need-lookup.txt / lookup-still.txt списки на поиск в интернете
|
||||
└── *.py analyze / build_inventory3 / build_folders_plan /
|
||||
build_fix_plan / resolve_composers / apply_lookup1-3 /
|
||||
build_final / verify_manual / audit_categories /
|
||||
check_genres / dump_bad_genres / split_genres /
|
||||
normalize_genres / fill_genres / clean_genres /
|
||||
final_genres
|
||||
final_genres / find_junk / find_junk2 /
|
||||
clean_junk_tags / final_clean / final_clean2 /
|
||||
fix_paxatu / final_touch / fix_moji_album /
|
||||
build_unified / validate_final
|
||||
```
|
||||
|
||||
## 🔴 ПРОЦЕССНЫЙ УРОК ЭТАПА (главный)
|
||||
|
||||
Alex трижды требовал одно и то же, а ассистент **уходил в объяснения вместо исполнения**:
|
||||
|
||||
> «**Это не ответ блять. Откуда они там**» → «**Ты блядь csv дописал... Чё ждём блядь?!**» →
|
||||
> «**Хватит блядь! Задачу которую я поставил блядь выполняй!**» → «**Хули блядь встал еб твою
|
||||
> мать?! Выполнил задачу блядь?!**»
|
||||
|
||||
**Что было не так:**
|
||||
1. **Ушёл объяснять мойибаке** вместо того, чтобы строить CSV — задача стояла, ассistant
|
||||
отвечал на вопрос из предыдущего сообщения.
|
||||
2. **Сделал новый файл** (`albumartist-plan.csv`) вместо **обновления существующего** —
|
||||
Alex просил «берешь текущую csv и добавляешь в нее то чего не хватает».
|
||||
3. **Останавливался и задавал вопросы** там, где правило уже было дано («сборник = папка
|
||||
не одного артиста»).
|
||||
|
||||
**Правило: если Алекс дал правило — исполнять, а не уточнять. Вопрос допустим только при
|
||||
РЕАЛЬНОМ противоречии в его же словах. Объяснение ≠ выполнение.**
|
||||
|
||||
### Питфолл: субагент пишет в корень vault
|
||||
|
||||
Субагент по поиску композиторов создал `Советские детские песни — композиторы.md`
|
||||
|
||||
@@ -37,10 +37,35 @@ related:
|
||||
| Summary CSVs | инвариант суммы: `single + multi + skip == total` (теряли 562, потом 335 строк) |
|
||||
| Sentinel | группировать по КОРНЮ сборника, не по ближайшей папке (165 файлов в 9 фальшивых «артистов») |
|
||||
| 🆕 **Genre normalization** | 🔴 **G1–G5**, см. ниже |
|
||||
| 🆕 **Junk tag cleanup** | 🔴 **J1–J4**, см. ниже |
|
||||
|
||||
## 🆕 Junk tag cleanup (J1–J4) — вычистка мусора из тегов
|
||||
|
||||
**Контекст:** перед применением плана — аудит всех полей на мусор. Найдено и вычищено 10 классов
|
||||
(спам-URL 51, `P@X@Tu*HCK*u` 6, мойибаке в `album` 20 + `title` 1, заглушки genre 325,
|
||||
битые байты 2, `title` пуст 7).
|
||||
|
||||
| # | Правило |
|
||||
|---|---|
|
||||
| **J1** | **URL-подобные НАЗВАНИЯ песен не чистить.** `god@pisem.net`, `K@к@ In`, `И тебя уже.net` — реальные треки Пилота/Ленинграда/N1NT3NDO. Regex по подстроке вычищает их ошибочно. Фильтр — **точное совпадение значения целиком** со списком спама (`SPAM_EXACT`), не подстрока. |
|
||||
| **J2** | **Мойибаке — во ВСЕХ пяти полях.** Декодер прогонять по `title`/`artist`/`album`/`albumartist`/`genre`, не только по «проблемным». Пропуск дал 20 мойибаке в `album` (`Íåèçâåñòíîå íàçâàíèå`, `(Ìóììèé Òðîëëü)` ×7). |
|
||||
| **J3** | **`date`/`track` — числа, НЕ мусор.** Regex `^\d+$` дал 4475 ложных по `date` и 6310 по `track`. Исключать поля-числа из аудита мусора. |
|
||||
| **J4** | **Валидатор писать ДО объявления готовности.** `validate_final.py` (обязательные поля + спам + мойибаке + class↔albumartist) поймал 21 пропущенное значение. Проверка: все счётчики = 0. |
|
||||
|
||||
### Симптомы мусора в тегах (что искать)
|
||||
|
||||
```
|
||||
спам-URL в album/album_artist [muzmo.ru], http://butt-head.ru, www.mp3arena.ru, Mp3-Az.com
|
||||
имя тегировщика в genre/album P@X@Tu*HCK*u (не жанр! → по артисту)
|
||||
битые байты 刀甀猀戀愀爀搀猀 (иероглифы), Variйtй (смешанная кодировка)
|
||||
заглушки Other, Unknown, Неизвестный, Разное, Наши, genre, various, (N)
|
||||
мойибаке в album Íåèçâåñòíîå íàçâàíèå, (Ìóììèé Òðîëëü)
|
||||
```
|
||||
|
||||
|
||||
## 🆕 Genre normalization (G1–G5) — квинтэссенция
|
||||
|
||||
**Контекст:** 7861 файл, было **154 уникальных жанра**, 2950 пустых. Стало **82 / 51**.
|
||||
**Контекст:** 7861 файл, было **154 уникальных жанра**, 2950 пустых. Стало **65 / 0**.
|
||||
|
||||
| # | Правило |
|
||||
|---|---|
|
||||
@@ -48,7 +73,7 @@ related:
|
||||
| **G2** | **Гомоглифы — оба варианта в словарь явно.** `Å` (U+00C5, латиница) vs `Е` (U+0415, кириллица) выглядят одинаково; `lower()` их не схлопывает, а `.encode('latin-1')` падает на кириллической → декодер мойибаке **молча пропускает половину строк**. |
|
||||
| **G3** | **Мусорный жанр может быть мисридом поля.** `(17)` = все 32 файла **ДДТ** (номер плейлиста в кадре жанра); `General Rock` = все 31 **Ленинград**. Признак: `Counter(genre) → set(artist)` даёт **1:1** = это не жанр. Alex: «каждую смотри конкретно, не батчем по папке». |
|
||||
| **G4** | **Заполнять по артисту, порядок specific → general.** Таблица `подстрока → жанр` по `folder + artist`, первое совпадение выигрывает. Правила артистов **перед** папкой-ловушкой, иначе `!rock&folk` съест всех внутри. |
|
||||
| **G5** | **Незаполнимое — оставить ПУСТЫМ.** `unknown`/`неизвестно`/`разное`/`наши`/`(12)` не несут информации; подстановка по папке = **выдумывание метаданных**. 51 пустой — осознанное решение. |
|
||||
| **G5** | **Незаполнимое — оставить ПУСТЫМ** … но Alex потребовал **«Добей вручную пустые»** → 51 значение разобрано по артисту вручную (`Martin Solveig`→`Electro House`, `Chemical Brothers`→`Electronic`, `Eminem`→`Hip-Hop`, `Madonna`→`Pop`). **Итог: 0 пустых.** Правило G5 верно как дефолт, но Alex вправе потребовать ручной добив. |
|
||||
|
||||
### Порядок работ по жанрам (7 шагов)
|
||||
|
||||
@@ -66,13 +91,31 @@ related:
|
||||
|
||||
```
|
||||
/Users/admin/milestones/music-csv-2026-09-26/
|
||||
├── genre-plan-FINAL.csv ⭐ 7861 стр, 82 жанра, 51 пусто
|
||||
├── APPLY-PLAN-FINAL.csv ⭐⭐ 7861 стр — ЕДИНЫЙ ПЛАН НА ПРИМЕНЕНИЕ (14 колонок, 7628 изменений)
|
||||
├── fix-plan-FINAL.csv ⭐ 7861 стр, план artist/albumartist/album
|
||||
├── genre-plan-FINAL.csv ⭐ 7861 стр, 65 жанров, 0 пусто
|
||||
├── genre-junk.csv 365 строк мусора
|
||||
├── bad-genres.csv 3315 (мусор + пустые)
|
||||
└── check_genres.py → split_genres.py → normalize_genres.py →
|
||||
fill_genres.py → clean_genres.py → final_genres.py
|
||||
└── check_genres.py → split_genres.py → normalize_genres.py → fill_genres.py →
|
||||
clean_genres.py → final_genres.py → find_junk.py → find_junk2.py →
|
||||
clean_junk_tags.py → final_clean.py → final_clean2.py → fix_paxatu.py →
|
||||
final_touch.py → fix_moji_album.py → build_unified.py → validate_final.py
|
||||
```
|
||||
|
||||
**Единый план собирается сведением** `fix-plan-FINAL.csv` + `genre-plan-FINAL.csv` по ключу
|
||||
`path` (`build_unified.py`). Колонки результата:
|
||||
|
||||
```
|
||||
path, folder, class,
|
||||
cur_title, cur_artist, cur_albumartist, cur_album, cur_genre,
|
||||
new_title, new_artist, new_albumartist, new_album, new_genre, changed
|
||||
```
|
||||
|
||||
**Правило:** в одном файле держать и `cur_*` (что на диске), и `new_*` (что записать) —
|
||||
скрипт-писатель сравнивает их сам, а человек видит дельту глазами.
|
||||
|
||||
**Питфолл пайплайна:** `clean_genres.py` чистит **по списку**, а не до сходимости — после
|
||||
прогона на выходе тут же обнаружились новые остатки. Понадобился третий проход
|
||||
(`final_genres.py`: + детектор мойибаке + ещё 453 синонима). **Правило G1 выведено отсюда.**
|
||||
То же повторилось на мусоре: чистка пропустила 21 мойибаке в `album` — поймал только
|
||||
`validate_final.py`. **Правило J4 выведено отсюда.**
|
||||
Reference in new issue
Block a user