From b718a09e959b290bdcd0ac18ab8c60e5acf6d8a4 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Mon, 28 Sep 2026 00:11:55 +0600 Subject: [PATCH] [2026-09-28] eagle: personal/plans/music-artist-albumartist-repair.md personal/tech/music-tags-repair-truenas.md --- .../plans/music-artist-albumartist-repair.md | 98 +++++++++++++++++-- personal/tech/music-tags-repair-truenas.md | 69 ++++++++++++- 2 files changed, 157 insertions(+), 10 deletions(-) diff --git a/personal/plans/music-artist-albumartist-repair.md b/personal/plans/music-artist-albumartist-repair.md index 4e04d019..29fc7951 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: ДИФФ-ОТ-БД-СВЕРЕН / СБОРЩИК-v2-НЕ-НАПИСАН (сборники вне дифа) / ПРОГОН-НЕ-ЗАПУСКАТЬ-БЕЗ-ПОДТВЕРЖДЕНИЯ +status: ДИФФ-v6-СОБРАН-ПОЛНЫЙ-ПРОХОД-ПО-СБОРНИКАМ / СБОРЩИК-НАПИСАН / DRY-RUN-НЕ-ЗАПУЩЕН / ПРОГОН-НЕ-ЗАПУСКАТЬ-БЕЗ-ПОДТВЕРЖДЕНИЯ tags: - music - metadata @@ -35,11 +35,95 @@ related: **Что делаем:** привести ID3-теги библиотеки `/mnt/RED_2TB/storage/Music` (7861 файл) в порядок, чтобы Navidrome показывал правильные альбомы/исполнителей/жанры. -**Главный артефакт на сейчас (27 сен, сессия ~36):** +**Главный артефакт на сейчас (27 сен, сессия 38):** ``` -⚠️ ДИФФ ОТ БАЗЫ ГОТОВ, СВЕРЕН С ПЛАНОМ. ПРОГОН НЕ ЗАПУСКАТЬ БЕЗ ПОДТВЕРЖДЕНИЯ ALEX. +⚠️ ДИФФ v6 СОБРАН — ПОЛНЫЙ ПРОХОД ПО СБОРНИКАМ. ПРОГОН НЕ ЗАПУСКАТЬ БЕЗ ПОДТВЕРЖДЕНИЯ ALEX. +ДИФФ: ~/Downloads/music-tags/DIFF-v6.csv + 102 строки · 553 правки · 282 файла + md5 b2b68bf9f3a0ca7645cb0ef90ec95f30 + по полям: album 183 · artist 155 · albumartist 157 · track 58 + сортировка: по АЛФАВИТУ field (album → albumartist → artist → track) + источник цели: БД Navidrome (то, что РЕАЛЬНО в тегах), НЕ канон +План: ~/Downloads/music-tags/apply-plan-v6.csv (7861 строка, md5 4480cc0d1ba81db6380b935a459e7eac) +Сборщик: ~/Downloads/music-tags/build_diff_v6.py ← 8 правил, заменил build_diff_from_db.py +Канон: ~/Downloads/music-tags/APPLY-PLAN.csv (2 882 935 B — эталон ручных правок, НЕ ПЕРЕЗАПИСЫВАТЬ) +Бэкапы: DIFF-v6.csv.bak-20260927-* · DIFF-db-to-fix.csv.bak-20260927-234901 + +ЧЕМ v6 ОТЛИЧАЕТСЯ ОТ v5 (DIFF-db-to-fix.csv): + album 60 → 183 файлов (+123: сборники, которых v5 не видел) + artist 154 → 155 (+1: Т9) + albumartist 157 → 157 (=) + track 58 → 58 (=) +``` + +🔴 **ГЛАВНЫЙ УРОК СЕССИИ 38: СБОРЩИК ПРАВИЛ ПО СОВПАДЕНИЮ, А НЕ ПО ПАПКЕ.** +`build_diff_from_db.py` содержал **три хардкод-префикса** (`!Рэп/Трофим/`, `!Рэп/Птаха…`, +`Тема дороги.mp3`) и **не знал правила сборников вообще**. Поэтому в дифф v5 не попали: +`!Retro` (46), `!Rock&Folk/!rock_o_pop` (24), `!Pop, Club, Любэ/!ZabuGor` (15), +`!Классика` (5), `9999 - Разное/*` (30), 3 корневых файла = **123 файла**. +Alex: «ты сказочный долбоёб. у меня даже слов нет на этом моменте». +🔑 **ПРАВИЛО: прежде чем отдавать дифф — сверить его не с самим собой, а с постановкой задачи.** +Я сверил `verify_v5_vs_diff.py` (дифф↔план, сходится 1:1) и объявил «готово» — но обе стороны +сравнения были построены на одном и том же кривом сборщике. **Сверка сама с собой ничего не доказывает.** + +🔴 **ФАКТ: ПРОХОД v3 БЫЛ ТОЧЕЧНЫЙ, НЕ ПОЛНЫЙ — 18 папок из 23 правились по 1-3 файла.** +Правило в v3-скрипте срабатывало только при `album == title` или `album == имя файла`. +Файлы, у которых `album` был **чужим альбомом** (не равен ни title, ни файлу), проскакивали. +``` +!Pop, Club, Любэ/!ZabuGor правилось 1 из 15 !Retro/Забугр 3 из 32 +!Pop, Club, Любэ/Green Apelsin правилось 1 из 38 !Rock&Folk/!rock_o_pop 2 из 57 +!Pop, Club, Любэ/Алексин правилось 1 из 14 !Rock&Folk/Ария, Кипелов 3 из 12 + !Рэп/Птаха - Красивые… 1 из 8 +ПОЛНЫХ проходов всего 6: Little Big (1/1) · Руки вверх (2/2) · Хабиб (1/1) + · Юрий Антонов (1/1) · Юрий Никулин (3/3) · Серьга (1/1) +``` +🔑 **ДИАГНОСТИКА «проход был полным?»: `collections.Counter(cur_album)` по папке.** +Много уникальных значений = прохода не было. `!Retro`: **62 уникальных album на 236 файлов**. +Скрипты: `full_check_sborniki.py`, `why_resurface.py`. + +✅ **ПРАВИЛА СБОРЩИКА v6 (`build_diff_v6.py`) — 8 штук, В КОДЕ:** +``` +1. Папки '!*' → album = basename БЕЗ ведущих '!' + albumartist НЕ ТРОГАЕМ (Various Artists как есть) + artist НЕ ТРОГАЕМ +2. Папки 'Разное' → album = имя папки-владельца (НЕ имя файла) + 9999 - Разное/X albumartist = владелец категории ('Агата Кристи', уже так) +3. Трофим album: срез префикса 'NN ' (только 01-04 Аристократия помойки) + albumartist 'Трофим' → 'Сергей Трофимов' + artist 'Трофим' → 'Сергей Трофимов' + фиты 'С.Трофимов,группа X' → 'Сергей Трофимов и группа «X»' + track: пусто → номер из имени файла (#N_MM_) +4. Птаха album 'Птаха - Красивые, богатые (2009)' → 'Красивые, богатые' +5. Ленинград/Тема дороги album 'саунд треки к фильму' → 'Ленинград'; artist 'Бумер' → 'Ленинград' +6. Адресно Radio !Pop, Club, Любэ/detskiy_hor_benassi… → album='Radio' + !Pop, Club, Любэ/!Radio/Stylemasters… → album='Radio' +7. artist НЕ ТРОГАЕМ нигде, кроме п.3 и п.5 +8. Т9 - Вдох-Выдох album='Вдох-выдох', artist='Т9' (внешний источник, Discogs 2008) +``` + +🔑 **ЦЕЛЕВАЯ МОДЕЛЬ СБОРНИКОВ (окончательно, Alex 2026-09-27):** +``` +album = имя папки-владельца БЕЗ '!' ← ЕДИНСТВЕННОЕ, ЧТО МЕНЯЕМ в сборниках +albumartist = 'Various Artists' (сборники) / 'Агата Кристи' (9999 - Разное) +artist = реальный исполнитель трека ← НЕ ТРОГАЕМ НИКОГДА +``` +Alex дословно: «**АЛЬБОМ БЛЯДЬ rock_o_pop** не albumartist блядь! для сборников типа +rock_o_pop **artist = 'Various Artists'**!!!». `!` — служебный префикс сортировки, **в тег НЕ пишется +никогда**. Антидефект: в `!ZabuGor` у Marlyn Manson `album='!ZabuGor'` — `!` **попал в тег**. + +✅ **ДИФФ v6 СВЕРЕН ПО ПАПКАМ — 16 album-строк, все ожидаемые на месте** (см. таблицу +в [[personal/tech/music-tags-repair-truenas]] § сессия 38). + +✅ **ДУБЛИ ТРОФИМА — ПОДТВЕРЖДЕНО УДАЛЕНИЕ (проверка `find` на NAS).** +`!Рэп/Трофим/` **157 файлов** (эталон, живое дерево). Копии `!Radio/z Старое/disk*/3 SHANSON/Трофим` +— **0 живых**, остались только в `backup/` (220) и `backup_album_root_…-229/` (49). +🔑 Команда проверки: `find … -ipath "*Трофим*" -name "*.mp3" -printf "%h\n" | sort | uniq -c`. + +**Главный артефакт ПРЕДЫДУЩЕЙ сессии (сессия 37) — АРХИВ:** + +``` ДИФФ: ~/Downloads/music-tags/DIFF-db-to-fix.csv 16 857 B · 92 строки с заголовком = 91 ЗАПИСЬ (ПАПКА 26 · ТРЕК 65) md5 a5f2b910826dcc46474b6e26513f414f @@ -47,13 +131,9 @@ related: ⚠️ СЧЁТ: 91 запись ≠ 92 строки файла (заголовок) и ≠ 87 (2 файла с ДВОЙНОЙ правкой: Тема дороги album+artist, Птаха album в одну сторону) - сортировка: по АЛФАВИТУ field (album → albumartist → artist → track) - источник цели: БД Navidrome (то, что РЕАЛЬНО в тегах), НЕ канон + 🔴 УСТАРЕЛ: не содержит сборников (123 файла). Использовать DIFF-v6.csv. План: ~/Downloads/music-tags/apply-plan-v5.csv (7861 строка, md5 d4392b11f143844c590a0a9c4a752208) - меняется 159 файлов · без изменений 7702 - по полям: albumartist 157 · artist 154 · album 60 · track 58 · title 0 · genre 0 -Сборщик: ~/Downloads/music-tags/build_diff_from_db.py -Канон: ~/Downloads/music-tags/APPLY-PLAN.csv (2 882 935 B — эталон ручных правок, НЕ ПЕРЕЗАПИСЫВАТЬ) +Сборщик: ~/Downloads/music-tags/build_diff_from_db.py ← 🔴 ЗАМЕНЁН на build_diff_v6.py ``` ✅ **СВЕРКА ДИФФ ↔ ПЛАН (27 сен, сессия ~36) — СХОДИТСЯ.** Скрипт diff --git a/personal/tech/music-tags-repair-truenas.md b/personal/tech/music-tags-repair-truenas.md index eca68f19..33807a9a 100755 --- a/personal/tech/music-tags-repair-truenas.md +++ b/personal/tech/music-tags-repair-truenas.md @@ -100,7 +100,74 @@ related: > Файлы в сборниках (`disk/`, `disk_v2/`) **удалять нельзя** — указание Alex: > «они корректно живут в сборниках». Удаляем ТОЛЬКО дубли альбомов. -> ## 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (2026-09-27, сессия ~36) — ЧИТАЙ ЭТО ПЕРВЫМ +> ## 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (2026-09-27, сессия 38) — ЧИТАЙ ЭТО ПЕРВЫМ +> +> 🔴🔴 **`apply` НЕ ЗАПУСКАТЬ БЕЗ ПРЯМОГО ПОДТВЕРЖДЕНИЯ ALEX.** Дословно: «**без подтверждения +> никакого apply блядь**». Дифф и dry-run — можно, запись — только «go». +> +> ✅ **ДИФФ v6 СОБРАН — ПОЛНЫЙ ПРОХОД ПО СБОРНИКАМ (главный результат сессии).** +> ``` +> ~/Downloads/music-tags/DIFF-v6.csv +> 102 строки · 553 правки · 282 файла · md5 b2b68bf9f3a0ca7645cb0ef90ec95f30 +> план: apply-plan-v6.csv — 7861 стр, md5 4480cc0d1ba81db6380b935a459e7eac +> ``` +> | Поле | Файлов | Было в v5 | +> |---|---|---| +> | `album` | **183** | 60 | +> | `artist` | 155 | 154 | +> | `albumartist` | 157 | 157 | +> | `track` | 58 | 58 | +> +> Прирост `album` = **+123 файла** — ровно те сборники, что v5 не видел. +> +> ✅ **СБОРЩИК НАПИСАН: `~/Downloads/music-tags/build_diff_v6.py`** (заменил `build_diff_from_db.py`). +> Реализует 8 правил, читает локальную копию БД `~/Downloads/navidrome-db/navidrome-after-v3.db`. +> 🔑 **Правила сборников теперь В КОДЕ, а не в хардкод-списке из 3 префиксов.** +> +> ✅ **СВЕРКА `DIFF-v6.csv` ПО ПАПКАМ — 16 album-строк:** +> ``` +> !Retro 32 разных → 'Retro' +> !Rock&Folk/!rock_o_pop 16 разных → 'rock_o_pop' +> !Pop, Club, Любэ/!ZabuGor 8 разных → 'ZabuGor' +> !Классика 5 разных → 'Классика' +> 9999 - Разное/{Кавер-версии,Неизданное,Проекты} → имя вложенной папки (30 файлов) +> !Pop, Club, Любэ/detskiy_hor_benassi… → 'Radio' (адресно) +> !Pop, Club, Любэ/!Radio/Stylemasters… → 'Radio' (адресно) +> !Рэп/03. Т9 - Вдох-Выдох… → 'Вдох-выдох' + artist 'Т9' +> !Рэп/Птаха - Красивые… → 'Красивые, богатые' +> !Рэп/Трофим/01-04 Аристократия помойки → срез префикса NN_ +> z Другое…/Тема дороги.mp3 → 'Ленинград' + artist 'Ленинград' +> ``` +> +> 🔴 **Т9 - «Вдох-Выдох» — АЛЬБОМ УСТАНОВЛЕН ПО ВНЕШНЕМУ ИСТОЧНИКУ (Discogs).** +> Файл `!Рэп/03. Т9 - Вдох-Выдох (Ода Нашей Любви).mp3` лежал в корне `!Рэп` с мусорным +> `album='Record Super Chart #1'` и `artist='Вдох-Выдох'` (часть названия песни!). +> Релиз `Т9 — Вдох-Выдох`, CD Album, **2008** (Discogs r3300495). +> **Решение Alex: `album='Вдох-выдох'`, `artist='Т9'`** ✅ подтверждено. +> 🔑 **МЕТОД: реальный альбом одиночного файла ставится по внешнему источнику (Discogs/MusicBrainz), +> НЕ по имени папки.** Иначе в тег уедет `Record Super Chart #1`. +> +> 🔴 **ПРАВИЛО КОРНЕВЫХ ФАЙЛОВ (закрыто):** файл прямо в категории (`!Рэп/x.mp3`, +> `!Pop, Club, Любэ/x.mp3`) → `album` = имя категории БЕЗ `!`. Для `!Radio` внутри — +> `album='Radio'`. Вложенные `!Radio/v 2009-03 mIr.vEsNЫ/…` **НЕ ТРОГАЕМ** (Alex: их +> значение `2009-03 mIr.vEsNЫ` верное — это дата-папка релиза, не дефект). +> ⚠️ **Питфолл: я спрашивал про `Record Super Chart #1` как про «папку» — такой ПАПКИ НЕТ.** +> Это значение поля `album`. **Прежде чем спрашивать — читать `os.path.dirname`, а не гадать.** +> +> ✅ **ДУБЛИ ТРОФИМА ПОДТВЕРЖДЕНЫ УДАЛЁННЫМИ (проверено `find` на NAS):** +> ``` +> !Рэп/Трофим/ 157 файлов ← ЭТАЛОН (живое дерево) +> backup/!Рэп/Трофим/ 220 файлов ← бэкап +> backup_album_root_…-229/…/3 SHANSON/Трофим 49 файлов ← бэкап +> ``` +> Живых копий `!Radio/z Старое/disk*/3 SHANSON/Трофим` — **0**. Удаление 50 файлов выполнено ✅. +> 🔑 **Проверка: `find … -ipath "*Трофим*" -name "*.mp3" -printf "%h\n" | sort | uniq -c`.** +> Префикс `backup` в пути = бэкап; живое дерево всегда без него. +> +> ⚠️ **ОСТАЛОСЬ (перед apply):** **dry-run v6 не запущен.** Плюс висят решения Alex по +> `10 Ностальгия`/`Боже, какой пустяк` и `Sbornik_Novij_Rok` genre. + +> ## 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (2026-09-27, сессия 37) — АРХИВ > > 🔴🔴 **`apply` НЕ ЗАПУСКАТЬ БЕЗ ПРЯМОГО ПОДТВЕРЖДЕНИЯ ALEX.** Дословно 27 сен: > «**без подтверждения никакого apply блядь**». Дифф и dry-run — можно, запись — только «go».