From c4e44ac277bce3ecf73af9573795d959b4c9ed2a Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 27 Sep 2026 14:24:18 +0600 Subject: [PATCH] [2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/tech/id3-tag-repair.md personal/tech/scripts/find_va_author.py --- .../plans/music-artist-albumartist-repair.md | 191 +++++++++++++++++- personal/tech/id3-tag-repair.md | 57 +++++- personal/tech/scripts/find_va_author.py | 62 ++++++ 3 files changed, 302 insertions(+), 8 deletions(-) create mode 100644 personal/tech/scripts/find_va_author.py diff --git a/personal/plans/music-artist-albumartist-repair.md b/personal/plans/music-artist-albumartist-repair.md index f0d92b0e..f1de3f43 100755 --- a/personal/plans/music-artist-albumartist-repair.md +++ b/personal/plans/music-artist-albumartist-repair.md @@ -4,7 +4,7 @@ created: '2026-09-27' updated: '2026-09-27' type: plan namespace: personal -status: session9-done-va-class-cleared-category-root-rolled-back +status: session10-done-va-author-class-cleared-spelling-normalized tags: - music - metadata @@ -23,6 +23,38 @@ related: # Music `artist` + `albumartist` Repair — правила Alex и ход работ +> ## 🟢 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 10 (2026-09-27) — читать это первым +> +> ``` +> APPLY-PLAN.csv 7861 строка md5 7679ee01a2aa8f28623b6fb8559d7381 +> DIFF-new-vs-38.csv 5000 строк md5 53716eea5accbffe50dbc0ee3a8ef8f7 +> tag-fix-plan.csv не тронут (база 38-го, источник истины для диффа) +> ``` +> +> **Пустых полей в плане — 0.** Дифф: `ПОТЕРЯНО 0 · ЛИШНИХ 0 · ПОТЕРЬ НЕТ, дифф ПОЛНЫЙ`. +> Все прочие md5/цифры по тексту ниже — **исторические**. Полный разбор — раздел +> **«🔷 СЕССИЯ 10»** в конце документа. +> +> ### 🔴 ГЛАВНОЕ ПРАВИЛО (Alex повторил дважды с матом — не забывать!) +> +> | Поле | Значение | +> |---|---| +> | `albumartist` | **ВЛАДЕЛЕЦ АЛЬБОМА**. Сборник песен одного автора (даже с гостевыми фитами) → **ИМЯ АВТОРА**, не `Various Artists` | +> | `artist` | исполнитель **конкретного трека** (фиты, реальные имена) | +> | `Various Artists` | **только** настоящие сборники **разных** авторов | +> +> Alex: «`albumartist` птаха блядь! artist — реальные исполнители! **ты поебанулся и забыл +> что че значит??**» → правило продублировано в `[[personal/tech/id3-tag-repair]]`. +> +> ### Итог сессий 7-10: ~440 строк, пять классов +> +> `A1` чужое `albumartist` из корня папки (40) · `A2` `Various Artists` поверх одного артиста (~290) · +> `A3` имя папки/склейка в `album` (~30) · `A4` корень категории как альбом (3, откат) · +> `A5` разнобой написания серии `Нечетный`/`Нечётный` (42). +> +> ✅ Класс `A2` **дочищен**: `find_va_misuse.py` → 0, `find_va_author.py` → остались только +> 2 защитимые папки (`Блестящие, Фриске`, `Eminem,50cent`). +> > ## 🔴 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 9 (2026-09-27) > > ``` @@ -3047,11 +3079,162 @@ APPLY-PLAN.csv.bak-before-nested-fix-20260927-141715 | **A3** имя папки/склейка в `album` | `Rammstein - misc` → `misc`, `Infected Mushroom - Other Track's` → `Other Tracks` | `find_folder_as_album.py` | 5 | | **A4** корень папки-категории как альбом | `z Другое…` | — | 3 (откат) | +## 🔷 СЕССИЯ 10 (2026-09-27, поздняя) — ПОСЛЕДНИЙ КЛАСС: `Various Artists` НА АЛЬБОМЕ ОДНОГО АВТОРА + +### 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (конец сессии 10) + +``` +APPLY-PLAN.csv 7861 строка md5 7679ee01a2aa8f28623b6fb8559d7381 +DIFF-new-vs-38.csv 5000 строк md5 53716eea5accbffe50dbc0ee3a8ef8f7 +tag-fix-plan.csv не тронут (база 38-го, источник истины для диффа) +verify_diff_completeness.py — независимый контроль полноты +``` + +**Пустых полей в плане — 0** (все пять `new_*`). +Дифф: `ПОТЕРЯНО 0 · ЛИШНИХ 0 · ПОТЕРЬ НЕТ, дифф ПОЛНЫЙ`. +`ВСЕГО правок (трек-уровень): 18558` — не менялось (правки заменяют значения, не число расхождений). + +### 🔴 ГЛАВНОЕ ПРАВИЛО, КОТОРОЕ ALEX ПРОДИКТОВАЛ (повторно, с матом) + +> «`albumartist` птаха блядь! artist — реальные исполнители! **ты поебанулся и забыл что че значит??**» +> +> «**Трофим блядь albumartist!**» (про сборник `Следующая остановка`, где 8 разных гостей) +> +> «**ты опять забыл че значит albumartist?**» + +**Формулировка (зафиксировать намертво):** + +| Поле | Значение | +|---|---| +| `albumartist` | **ВЛАДЕЛЕЦ АЛЬБОМА** — тот, чей это альбом/проект. Если это **сборник песен одного автора** (даже с гостевыми фитами) → **ИМЯ АВТОРА**, НЕ `Various Artists` | +| `artist` | исполнитель **конкретного трека** — включая фиты, реальные имена | +| `Various Artists` | **ТОЛЬКО** для настоящих сборников **разных** авторов (радио, retro, саундтреки, лейбл-сборники) | + +**Как я это нарушал:** ставил `Various Artists` там, где папка названа по артисту, а гости — фиты. +Alex: «разные исполители → various» — НЕТ, это не критерий; критерий — **кто владелец альбома**. + +### Правки сессии 10 (по комментариям Alex, по одной) + +| # | Папка / объект | Файлов | Было | Стало | Комментарий Alex | +|---|---|---:|---|---|---| +| 1 | `Benassi Bros/Re Sfaction` | 15 | `Various Artists` | `Benassi Bros` | «ну ставь benassi bros» | +| 2 | `Benassi Bros/2003 Hypnotica Bonus` | 5 | `Various Artists` | `Benassi Bros` | то же | +| 3 | `Dj Tiesto` | 14 | `Various Artists` | `Tiesto` | «тоже» (после вопроса про PoW) | +| 4 | `…/Life System (Astrix & Yahel & IM)…` | 2 | `Various Artists` | `Infected Mushroom` | «то же» | +| 5 | `…/S Is Here (Yahel Mix)` | 3 | `Various Artists` | `Infected Mushroom` | «то же» | +| 6 | `Агата Кристи` (корень) | 59 | `Various Artists` | `Агата Кристи` (52) + своё имя (7) | «почему Various?» | +| 7 | `Агата Кристи/9999 - Разное/Кавер-версии и пародии` | 24 | `Various Artists` | `Агата Кристи` | «albumartist тоже Агата Кристи поставь» | +| 8 | `Агата Кристи/9999 - Разное/Проекты` | 12 | `Various Artists` | `Агата Кристи` | «и …/Проекты» | +| 9 | `!Retro/Иванушки` | 8 | `Various Artists` | `Иванушки` | «почему various?» | +| 10 | `!Retro/Муслим Магомаев` | 7 | `Various Artists` | `Муслим Магомаев` | то же | +| 11 | `!Рэп/Птаха - Красивые, богатые (2009)` | 8 | `Various Artists` | `Птаха` | «albumartist птаха!» | +| 12 | `!Рэп/Трофим/11 Следующая остановка` | 14 | `Various Artists` | `Трофим` | «Трофим albumartist!» | +| 13 | `z Другое…/Ленинград/C.Шнуров - Бумер (2003)` | 19 | `Various Artists` | `Сергей Шнуров` | «автор альбома → Сергей Шнуров. ДА» | + +### Правки формата `album` (сессия 10) + +| # | Объект | Файлов | Было | Стало | Основание | +|---|---|---:|---|---|---| +| 1 | `!Rock&Folk/Rammstein` + `/misc` | 5 | `Rammstein - misc` | `misc` | Alex: «**это альбом — misc**»; «оно должно попадать в album! не в albumartist!» | +| 2 | `Нечетный Воин/CD1` | 11 | `Нечетный Воин (CD1)` | `Нечётный Воин` | «CD1/CD2 — убрать» | +| 3 | `Нечетный Воин/CD2` | 11 | `Нечетный Воин (CD2)` | `Нечётный Воин` | то же | +| 4 | серия целиком | 42 | 4 варианта | `Нечётный Воин` (24) / `Нечётный Воин 2` (20) | «`Нечетный`/`Нечётный` — очевидно блядь, не??» | +| 5 | `Infected Mushroom - Other Track's` | 2 | имя папки | `Other Tracks` | часть «Radio/Other Tracks»-пачки | + +**Маппинг написания серии (норма — с ё):** + +``` +'Нечетный Воин' -> 'Нечётный Воин' +'Нечетный Воин (CD1)'-> 'Нечётный Воин' +'Нечетный Воин (CD2)'-> 'Нечётный Воин' +'Нечетный воин 2' -> 'Нечётный Воин 2' +'Нечётный воин 2' -> 'Нечётный Воин 2' +``` + +### ✅ ОСТАТОК КЛАССА — 2 папки, `Various Artists` ЗАЩИТИМ (не трогать) + +``` +!Pop, Club, Любэ/Блестящие, Фриске 5 файлов (папка-склейка двух составов) +!Рэп/Eminem,50cent 6 файлов (папка двух рэпперов) +``` + +>`find_va_author.py` даёт по ним «кандидат», но вердикт — `Various Artists` корректен. + +### ✅ ЛОЖНЫЕ СРАБАТЫВАНИЯ детекторов (проверено, НЕ правились) + +| Папка | Детектор | Вердикт | +|---|---|---| +| `!Рэп/Трофим/11 Следующая остановка` | `find_va_misuse` → `Трофим` | Alex переопределил → `Трофим` (правил) | +| `!Rock&Folk/ДДТ/2008 L'Echoppe` | `find_aa_hijack` → `Юрий Шевчук & Казански` | ❌ ложное: `ДДТ` верно, дуэт — исполнители альбома | +| `!Pop, Club, Любэ/Бенасси/Re Sfaction` | `find_aa_hijack` | ❌ ложное: решение Alex | +| `…/S Is Here` | `find_aa_hijack` | ❌ ложное: решение Alex | +| `!Детские/Сборка Песни для детей/L` | `find_aa_hijack` | ❌ ложное: сборник, `Детские песни` верно | +| 47 папок с `Various Artists` | `find_va_author` | ✅ ВЕРНО — настоящие сборники (`Sbornik_Novij_Rok` 200, `!Retro` 158, `!Radio/*`, `Final Fantasy VI`, трибьюты, `Gazgolder`) | + +### 🧰 ИНСТРУМЕНТЫ СЕССИИ 10 + +| Файл | Назначение | +|---|---| +| `/tmp/check_benassi.py` | смотр `albumartist` по папкам Benassi | +| `/tmp/fix_benassi_aa.py` | Benassi `Various Artists` → `Benassi Bros` | +| `/tmp/fix_aa_tiesto_im.py` | Tiesto + Infected Mushroom | +| `/tmp/fix_agatha.py` | Агата Кристи корень + Кавер-версии | +| `/tmp/fix_proekty.py` | Проекты + Иванушки + Магомаев | +| `/tmp/fix_misc.py` | `Rammstein - misc` → `misc` | +| `/tmp/fix_va_rest.py` | остаток `Various Artists` (НТЛ, Ария, Тест Сабвуфера) | +| `/tmp/rollback_z_drugoe.py` | откат корня категории | +| `/tmp/fix_ptaha.py` | Птаха | +| `/tmp/fix_trofim.py` | Трофим | +| `/tmp/fix_bumer.py` | C.Шнуров — Бумер | +| `/tmp/fix_cd_suffix.py` | `(CD1)`/`(CD2)` из album | +| `/tmp/fix_nechetny_spelling.py` | нормализация `Нечётный Воин`/`Нечётный Воин 2` | +| `/tmp/find_va_author.py` | **НОВЫЙ детектор**: `Various Artists` на альбоме одного автора | +| `/tmp/list_va_remaining.py` | инвентарь всех папок с `Various Artists` | + +### Бэкапы сессии 10 + +``` +APPLY-PLAN.csv.bak-before-benassi-20260927-140435 +APPLY-PLAN.csv.bak-before-aa-tiesto-im-20260927-140556 +APPLY-PLAN.csv.bak-before-aa-hijack-20260927-140659 +APPLY-PLAN.csv.bak-before-misc-album-20260927-140831 +APPLY-PLAN.csv.bak-before-agatha-20260927-141128 +APPLY-PLAN.csv.bak-before-proekty-20260927-141200 +APPLY-PLAN.csv.bak-before-va-rest-20260927-141317 +APPLY-PLAN.csv.bak-before-z-drugoe-va-20260927-141339 +APPLY-PLAN.csv.bak-before-z-drugoe-rollback-20260927-141422 +APPLY-PLAN.csv.bak-before-nechetny-20260927-141459 +APPLY-PLAN.csv.bak-before-nechetny-artist-20260927-141705 +APPLY-PLAN.csv.bak-before-nested-fix-20260927-141715 +APPLY-PLAN.csv.bak-before-ptaha-20260927-141911 +APPLY-PLAN.csv.bak-before-trofim-20260927-142044 +APPLY-PLAN.csv.bak-before-nechetny-spelling-20260927-142113 +APPLY-PLAN.csv.bak-before-bumer-20260927-142130 +``` + +### ⏭ СЛЕДУЮЩИЙ ШАГ (сессия 11) + +1. Глазами пройти `field=album` в диффе (ПАПКА-записи) — содержательные решения. +2. Затем `field=albumartist`. +3. Боевой прогон `--apply --verify` — **не запущен**, ждёт отдельного «go». +4. Контейнер `snapcur` на NAS (только чтение, `:ro`) — **не убран**, Alex не подтвердил. +5. Открытые вопросы, ответа НЕ было (не трогать): `Рэп/НТЛ` помечен Alex как `НТЛ` — учтено. + +## 📊 ИТОГ СЕССИЙ 7-10: ~440 строк по четырём классам + +| Класс | Проявление | Детектор | Объём | +|---|---|---|---| +| **A1** чужое значение `albumartist` из корня папки | `DJ Feel`, `VIP77`, `Бумер`, `КняZz`, `Мика Ньютон`, `Виктор Жуков`, `ДА и Меньшиков` | `find_aa_hijack.py` | 40 | +| **A2** `Various Artists` поверх одного артиста | Агата Кристи 95, НТЛ 80, Бенасси 20, Tiesto 14, Иванушки 8, Магомаев 7, ИМ 5, Ария 12, Тест Сабвуфера 4, Птаха 8, Трофим 14, Шнуров/Бумер 19 | `find_va_misuse.py` + `find_va_author.py` | ~290 | +| **A3** имя папки/склейка в `album` | `Rammstein - misc` → `misc`, `Infamous Mushroom - Other Track's` → `Other Tracks`, `(CD1)`/`(CD2)` | `find_folder_as_album.py` | ~30 | +| **A4** корень папки-категории как альбом | `z Другое…` | — | 3 (откат) | +| **A5** разнобой написания серии | `Нечетный`/`Нечётный`, 4 варианта | `fix_nechetny_spelling.py` | 42 | + ## ⏭ СЛЕДУЮЩИЙ ШАГ -1. `album` для `Би-2/Нечётный Воин/*` — оставить или унифицировать (ждёт Alex). -2. Глазами пройти `field=album` в диффе (305 строк, из них ПАПКА — 72) — содержательные решения. -3. Затем `field=albumartist` (571 строка папок). +1. `album` для `Би-2/Нечётный Воин/*` — унифицирован (`Нечётный Воин` / `Нечётный Воин 2`), **ЗАКРЫТО**. +2. Глазами пройти `field=album` в диффе — содержательные решения. +3. Затем `field=albumartist`. 4. Боевой прогон `--apply --verify` — **не запущен**, ждёт отдельного «go». 5. Контейнер `snapcur` на NAS (только чтение, `:ro`) — **не убран**, Alex не подтвердил. diff --git a/personal/tech/id3-tag-repair.md b/personal/tech/id3-tag-repair.md index e78faf81..5d8471eb 100755 --- a/personal/tech/id3-tag-repair.md +++ b/personal/tech/id3-tag-repair.md @@ -302,13 +302,34 @@ Alex), `ДДТ/2008 L'Echoppe` (сборник ДДТ, 10 файлов = дуэ !Retro/Муслим Магомаев 7 → Муслим Магомаев Infected Mushroom (2 папки) 5 → Infected Mushroom Тест Сабвуфера 4 → Тест Сабвуфера +!Рэп/Птаха - Красивые, богатые (2009) 8 → Птаха (альбом с фитами) +!Рэп/Трофим/11 Следующая остановка 14 → Трофим (8 гостей на альбоме Трофима) +z Другое…/C.Шнуров - Бумер (2003) 19 → Сергей Шнуров (саундтрек, автор музыки) ``` -**Правило:** `Various Artists` ставить ТОЛЬКО когда исполнители **действительно разные**. -Один артист (в т.ч. с вариациями написания) → ставить **его**. +**Правило:** `Various Artists` ставить ТОЛЬКО когда исполнители **действительно разные** +и **нет владельца альбома**. Один артист (в т.ч. с вариациями написания) → ставить **его**. +Сборник песен одного автора с гостевыми фитами → **имя автора**. -Детектор: `personal/tech/scripts/find_va_misuse.py` — папки с `aa='Various Artists'`, где ->50% файлов имеют одного `artist`. Итог: `ПАПОК-КАНДИДАТОВ: 0` (класс вычищен). +🔴 **Alex дважды ловил меня на этом в сессии 10:** +> «**`albumartist` птаха блядь! artist — реальные исполнители! ты поебанулся и забыл что че значит??**» +> «**Трофим блядь albumartist!**» — про `Следующая остановка`, где 8 разных гостей (Маршал, Овсиенко, Азиза…) + +**Формулировка, которую нельзя забывать:** + +| Поле | Значение | +|---|---| +| `albumartist` | **владелец альбома/проекта** — чей это релиз | +| `artist` | исполнитель конкретного трека (фиты — реальные имена) | +| `Various Artists` | только сборники **разных** авторов без единого владельца | + +Детекторы: `personal/tech/scripts/find_va_misuse.py` (папки с `aa='Various Artists'`, где +>50% файлов — один `artist`; итог `ПАПОК-КАНДИДАТОВ: 0`) и +`personal/tech/scripts/find_va_author.py` (папка названа по автору, `aa='Various Artists'`; +остались только 2 защитимые: `Блестящие, Фриске`, `Eminem,50cent`). + +**Защитимые ложные:** 47 папок с настоящими сборниками (`Sbornik_Novij_Rok` 200, `!Retro` 158, +`!Radio/*`, `Final Fantasy VI`, трибьюты, `Gazgolder`) — `Various Artists` ВЕРЕН. ### 🔴 A3 — имя подпапки уезжает в `album`/`albumartist` склейкой @@ -338,6 +359,34 @@ Infected Mushroom (2 папки) 5 → Infected Mushroom Реакция Alex (со «стоп»): «**красную плесень в красную плесень - виа меа в виа меа - не объединять корень Другого в альбом**». +### 🔴 A6 — разнобой написания серии + технические суффиксы в `album` + +Один релиз жил в четырёх написаниях, плюс `(CD1)`/`(CD2)` в значении: + +``` +'Нечетный Воин' (22 файла, без ё) +'Нечетный Воин (CD1)' (11) ← технический суффикс диска +'Нечетный Воин (CD2)' (11) +'Нечетный воин 2' (4) +'Нечётный воин 2' (16) ← регистр «воин» строчными +``` + +**Норма (Alex: «`Нечетный`/`Нечётный` — очевидно блядь, не??»):** литературное написание +**с ё**, суффикс диска убрать. + +``` +'Нечетный Воин' -> 'Нечётный Воин' +'Нечетный Воин (CD1)' -> 'Нечётный Воин' +'Нечетный Воин (CD2)' -> 'Нечётный Воин' +'Нечетный воин 2' -> 'Нечётный Воин 2' +'Нечётный воин 2' -> 'Нечётный Воин 2' +``` + +Итог: `Нечётный Воин` (24) + `Нечётный Воин 2` (20). Скрипт: `/tmp/fix_nechetny_spelling.py`. + +**Общий принцип:** технические суффиксы (`(CD1)`, `(Disc 2)`) — не часть названия альбома; +перед записью значения сверять написание серии с нормой (ё, регистр). + ### 🔴 A5 — имя ПРОЕКТА вместо артиста + вложенные скобки в имени файла (сессия 9) Класс: `artist` (и `albumartist`) = **название музыкального проекта**, а реальные исполнители diff --git a/personal/tech/scripts/find_va_author.py b/personal/tech/scripts/find_va_author.py new file mode 100644 index 00000000..c222cbeb --- /dev/null +++ b/personal/tech/scripts/find_va_author.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Класс A2 (второй детектор): albumartist='Various Artists', но это АЛЬБОМ ОДНОГО АВТОРА. + +Признак: папка названа по автору (или автор доминирует в artist), а стоит 'Various Artists'. +Дополняет find_va_misuse.py (тот ловит «>50% один artist» без учёта имени папки). + +Питфолл: 47 папок-сборников дают «кандидат» ложно (Sbornik_Novij_Rok, !Retro, !Radio/*, +Final Fantasy VI, трибьюты, Gazgolder) — они в SKIP. Остаток после чистки: +`Блестящие, Фриске` и `Eminem,50cent` — папки-склейки, Various Artists там ВЕРЕН. + +Использование: python3 find_va_author.py +Итог сессии 10: кандидатов 2 (оба защитимые). +""" +import csv +import collections +import os + +P = '/Users/admin/Downloads/music-tags/APPLY-PLAN.csv' +rows = list(csv.DictReader(open(P, encoding='utf-8-sig', newline=''))) + + +def s(v): + return (v or '').strip() + + +# музыкальные папки-КОНТЕЙНЕРЫ, где Various Artists законен сам по себе +SKIP_PARTS = ('!Radio', 'Sbornik', 'Трибьют', 'VA ', 'Сборник', 'Сборка') +SKIP_EXACT = { + '!Retro', '!Rock&Folk/!rock_o_pop', '!Классика', '!Rock&Folk/Неголубой огонёк НГ 2004', + '!A Not sorted/Sbornik_Novij_Rok', +} + +by = collections.defaultdict(list) +for r in rows: + if s(r['new_albumartist']) == 'Various Artists': + by[r['folder']].append(r) + +print("КАНДИДАТЫ: папка-АВТОР + Various Artists\n") +hits = 0 +for folder, rs in sorted(by.items()): + if any(p in folder for p in SKIP_PARTS): + continue + if folder in SKIP_EXACT or any(folder.startswith(x) for x in SKIP_EXACT): + continue + fam = os.path.basename(folder) # имя самой папки + parent = os.path.basename(os.path.dirname(folder)) # имя родителя + arts = collections.Counter(s(r['new_artist']) for r in rs if s(r['new_artist'])) + top, cnt = arts.most_common(1)[0] if arts else ('', 0) + n = len(rs) + # автор = доминирующий artist, и он же имя родительской папки + if top and cnt >= 2 and (top == parent or top in parent or parent in top): + print(f" {n:4d} файлов top={top!r} ({cnt}/{n}) автор-папка={parent!r}") + print(f" {folder}") + hits += 1 + # либо альбом назван так же, как папка, и 1 исполнитель + elif n <= 20 and cnt >= max(2, n * 0.4): + print(f" {n:4d} файлов top={top!r} ({cnt}/{n}) папка={fam!r}") + print(f" {folder}") + hits += 1 + +print(f"\nвсего кандидатов: {hits}")