diff --git a/personal/tech/music-tags-final-review.md b/personal/tech/music-tags-final-review.md index 15dfef9c..1a0b19bf 100755 --- a/personal/tech/music-tags-final-review.md +++ b/personal/tech/music-tags-final-review.md @@ -4,6 +4,7 @@ created: '2026-09-26' updated: '2026-09-26' type: tech namespace: personal +wave: 36 tags: - music - jellyfin @@ -18,7 +19,7 @@ related: _Обновлено: 2026-09-26. Источник: `~/Downloads/music-tags/tag-fix-plan.csv`._ -> ## ✅ 35-я волна — СКАЗКИ ВОССТАНОВЛЕНЫ, СЛИТЫЕ АЛЬБОМЫ РАЗЪЕДИНЕНЫ. АППРУВ РАЗБЛОКИРОВАН +> ## ✅ 36-я волна — КОРРЕКЦИЯ: СКВОЗНАЯ НУМЕРАЦИЯ («(часть N)» ОТМЕНЕНО) + ПРОЦЕССНЫЙ УРОК > > **Построчное чтение завершено: 1–7906 (100%).** Правки продолжаются по спискам Alex. > 28-я волна: **сквозная нумерация треков по дискам** (9 многодисковых альбомов) — ✅ ГОТОВО. @@ -31,6 +32,13 @@ _Обновлено: 2026-09-26. Источник: `~/Downloads/music-tags/tag-f > 34-я волна: ✅ **СКАЗКИ ВОЗВРАЩЕНЫ** — `batchAB`, `artist` из имени папки-сказки (241 правка), > из `rebuild_summaries.py` убран фильтр `if not art: continue`. > 35-я волна: ✅ **разъединены слитые альбомы сказок** — `batchAC`+`batchAD`, 14 правок. +> 36-я волна: ⛔ **отменено «(часть 1)/(часть 2)»** — сквозная нумерация `Али-Баба` **1–14** +> (`batchAF2`); версии `Буратино`/`Хоттабыч`/`Летучий корабль` разведены и пронумерованы (`batchAE`). +> +> 🔴 **ПРОЦЕССНЫЙ УРОК 36-й ВОЛНЫ — правка CSV ≠ обновление сводок.** +> После ЛЮБОЙ правки `tag-fix-plan.csv` ОБЯЗАТЕЛЬНО `python3 rebuild_summaries.py`. +> Ассистент поправил CSV, не пересобрал сводки → Alex видел старое `(часть 1)` и решал, что не сделано. +> Приёмка: `grep -c "часть" artists-*.csv` → `0`. > > 🔴🔴 **ИСПРАВЛЕНО (было: из сводок выброшены 562 строки `!Детские/Сказки`).** > Причина — фильтр в `rebuild_summaries.py`: `if not art: continue` («пустой artist не артист»). @@ -39,16 +47,22 @@ _Обновлено: 2026-09-26. Источник: `~/Downloads/music-tags/tag-f > > ✅ **Итог правок:** `single` 646 + `multi` 6897 = **7543** (было 7302 — недосчитывало 562 сказки). > **0 групп «один артист — разные написания»**, `colliding normalized names` = **0**, -> нечисловых треков **0**, пустых title **0**. -> 👉 Детали — `personal/tech/music-tags-repair-truenas.md` (волны 34–35). +> нечисловых треков **0**, пустых title **0**, `(часть` в сводках = **0**. +> 👉 Детали — `personal/tech/music-tags-repair-truenas.md` (волны 34–36). > -> ### ⚠️ ОТКРЫТО: 1 строка CSV без файла на диске +> ### ⚠️ ОТКРЫТО (1): 7 альбомов сказок без номеров треков +> Номера отсутствуют в именах файлов физически. `Bremenskie muzykanty` (4, = 2 сказки), +> `Голубой щенок` (4, 2 версии), `Винни-Пух` (9), `Русские народные сказки` (11), +> `Сказочный сборник` (16), `Арабская сказка` (2), `Л.Н. Толстой` (1). +> Первые три чинятся из `(N)`; у остальных порядок произвольный — ждёт решения Alex. +> +> ### ⚠️ ОТКРЫТО (2): 1 строка CSV без файла на диске > > `/storage/Music/!A Not sorted/НАШЕСТВИЕ 2009 - ДЕНЬ ВТОРОЙ.mp3` — есть в CSV, на диске нет. > Полное сравнение `os.walk` (7905 файлов) ↔ CSV (7906 строк, NFC) дало: > **на диске без CSV = 0**, **в CSV без диска = 1**. Ждёт решения: удалить строку или файл переименован. > -> ### ⚠️ Открыто: 104 дубля `(album, track)` — копии релизов в разных папках (дедупликация). +> ### ⚠️ ОТКРЫТО (3): 104 дубля `(album, track)` — копии релизов в разных папках (дедупликация). ## Состав файлов diff --git a/personal/tech/music-tags-repair-truenas.md b/personal/tech/music-tags-repair-truenas.md index 1649cf53..57c6f875 100755 --- a/personal/tech/music-tags-repair-truenas.md +++ b/personal/tech/music-tags-repair-truenas.md @@ -4,7 +4,7 @@ created: '2026-09-26' updated: '2026-09-26' type: tech namespace: personal -wave: 35 +wave: 36 tags: - music - jellyfin @@ -20,6 +20,83 @@ related: # Music Tags Repair — TrueNAS (7906 файлов) +> ## ✅ ТРИДЦАТЬ ШЕСТАЯ ВОЛНА (2026-09-26) — СКВОЗНАЯ НУМЕРАЦИЯ ЧАСТЕЙ + 🔴 ГЛАВНЫЙ ПРОЦЕССНЫЙ ПРОВАЛ: ЗАБЫТЫЙ `rebuild_summaries.py` +> +> Триггер: Alex — «приключения буратино - номера!! старик хоттабыч, Летучий корабль - тоже - +> и две версии в 1 альбоме» → «блядь! какого хуя `Али-Баба и сорок разбойников (часть 1)` и +> `(часть 2)`?! **сквозная блядь!!!**» → «там до сих пор `(часть 1)` и `(часть 2)`». +> +> ### 🔴 ГЛАВНЫЙ ПРОЦЕССНЫЙ УРОК: ПРАВКА CSV ≠ ОБНОВЛЕНИЕ СВОДОК +> **После ЛЮБОЙ правки `tag-fix-plan.csv` ОБЯЗАТЕЛЬНО `python3 rebuild_summaries.py`.** +> Ассистент поправил CSV (batch AF2), не пересобрал сводки — Alex видел старые значения +> в `artists-multi-track.csv` и **справедливо решил, что правка не сделана**. +> Это два разных шага: скрипт правки меняет CSV, `rebuild_summaries.py` переносит изменения +> в `artists-single-track.csv` / `artists-multi-track.csv`. Забыть второй = соврать Alex. +> **Проверка приёмки:** `grep -c "<старое_значение>" artists-*.csv` → должно быть `0`. +> +> ### ✅ СКВОЗНАЯ НУМЕРАЦИЯ ЧАСТЕЙ (отмена решения 35-й волны) +> 35-я волна развела Али-Бабу на `(часть 1)` / `(часть 2)` — **Alex отверг: это ОДИН альбом, +> нумерация сквозная.** Скрипт `fix_manual_batchAF2.py` (14 правок, идемпотентен, `bak-batchAF`): +> +> | Папка | Было (35-я волна) | Стало (36-я волна) | Треки | +> |---|---|---|---:| +> | `Али-Баба и сорок разбойников` (файлы `01`–`07`) | album `(часть 1)`, треки 1–7 | album **`Али-Баба и сорок разбойников`**, треки **1–7** | 14 | +> | `Али-Баба и сорок разбойников_2` (файлы `01`–`07`) | album `(часть 2)`, треки 1–7 | тот же album, треки **8–14** (база +7) | ↑ | +> +> **Правило:** `_N` в имени папки = **продолжение того же релиза**, а не отдельный альбом. +> Номера частей 2+ считаются **от исходного номера в имени файла + сдвиг**, не от текущего +> значения поля (иначе повторный прогон накапливает дельту — классический кейс неидемпотентности). +> «(часть N)» в теге `album` — **выдумка ассистента, стоп-слово**. Alex такое не принимает. +> +> ### ✅ РАЗВЕДЕНЫ ВЕРСИИ + ЗАПОЛНЕНЫ НОМЕРА (batch AE, 8 правок, `bak-batchAE`) +> Проверка диска через `os.listdir` (python на хосте NAS — имена не в UTF-8!): +> +> | Папка | Было | Стало | Треков | +> |---|---|---|---:| +> | `Buratino` (файлы `(1)`,`(2)`) | номера **пустые** | album `Приключения Буратино`, треки **1–2** | 2 | +> | `Xottabych` (файлы `(1)`–`(4)`) | номера **пустые** | album `Старик Хоттабыч`, треки **1–4** | 4 | +> | `Летучий корабль` (кириллица, `01`,`02`) | номера 1,2 + **пустые у второй версии** | album `Летучий корабль`, треки 1–2 | 2 | +> | `Letuchij korabl` (файлы `(1)`,`(2)`) | слить в один album с кириллицей | album **`Летучий корабль (другая версия)`**, треки **1–2** | 2 | +> +> **Урок:** две папки одной сказки (транслит vs кириллица) = **разные записи**, своя нумерация с 1. +> Подтверждено составом файлов: `01 - Летучий корабль`, `02 - По щучьему велению` (одна версия) +> vs `Летучий корабль (1)`, `(2)` (другая). +> **Детектор номеров:** `\((\d{1,2})\)` (скобки) и `^(\d{1,2})\s*[-._)]` (ведущий номер) — +> обе формы покрывают все папки сказок. +> +> ### 📊 ИТОГ 36-й ВОЛНЫ +> +> | Показатель | Волна 35 | **Волна 36** | +> |---|---:|---:| +> | `tag-fix-plan.csv` | 7906 (0 битых) | **7906 (0 битых)** | +> | `artists-single-track.csv` | 646 | **646** | +> | `artists-multi-track.csv` | 6897 | **6897** | +> | Сумма сводок | 7543 | **7543** | +> | Артистов в multi | 322 | **322** | +> | `colliding normalized names` | 0 | **0** | +> | Нечисловых треков | 0 | **0** | +> | `(часть` в сводках | ⚠️ было | **0** ✅ | +> +> Скрипты волны: `fix_manual_batchAE.py`, `fix_manual_batchAF2.py` (оба идемпотентны, повтор = 0). +> +> ### ⚠️ ОТКРЫТО: 7 АЛЬБОМОВ СКАЗОК БЕЗ НОМЕРОВ +> Номера **отсутствуют физически в именах файлов** — нужен порядок треков (не алгоритмизуемо): +> +> | Альбом | Файлов | Решение | +> |---|---:|---| +> | `Bremenskie muzykanty` | 4 | **две сказки**: «Бременские музыканты» `(1)`,`(2)` + «По следам бременских» `(1)`,`(2)` → развести на 2 альбома | +> | `Голубой щенок` | 4 | `(1)`,`(2)` × 2 версии (транслит+кириллица) | +> | `Винни-Пух` | 9 | часть имён без номеров; `01`–`06` только в `Vinni Pooh` | +> | `Русские народные сказки` | 11 | имена = названия, порядок неявный | +> | `Сказочный сборник` | 16 | имена = названия, порядок неявный | +> | `Арабская сказка` | 2 | — | +> | `Л.Н. Толстой` | 1 | — | +> +> Первые три чинятся однозначно из `(N)`; остальные четыре — порядок произвольный. +> +> Также **открыт** вопрос 35-й волны: `/storage/Music/!A Not sorted/НАШЕСТВИЕ 2009 - ДЕНЬ ВТОРОЙ.mp3` +> есть в CSV, нет на диске (1 строка из 7906). + > ## ✅ ТРИДЦАТЬ ПЯТАЯ ВОЛНА (2026-09-26) — РАЗЪЕДИНЕНЫ СЛИТЫЕ АЛЬБОМЫ СКАЗОК + ПОЙМАНА ПОТЕРЯ ЧАСТИ 2 > > Триггер: Alex — «че произошло с трек номером в `/storage/Music/!Детские/Сказки/Alisa v strane chudes`» @@ -34,8 +111,8 @@ related: > |---|---|---|---:| > | `Alisa v strane chudes` (файлы `(1)`–`(8)`) | album `Алиса в Стране Чудес`, треки **27–34** | album **`Алиса в стране чудес`**, треки **1–8** | 8 | > | `Алиса в Стране Чудес (Диск1)` + `(Диск2)` | album `Алиса в Стране Чудес` | без изменений, треки **1–26** | 26 | -> | `Али-Баба и сорок разбойников` | album без маркера части | **`Али-Баба и сорок разбойников (часть 1)`**, треки 1–7 | 7 | -> | `Али-Баба и сорок разбойников_2` | album **`…разбойников_2`** (маркер диска в теге!) | **`… (часть 2)`**, треки 1–7 | 7 | +> | `Али-Баба и сорок разбойников` | album без маркера части | ~~**`Али-Баба и сорок разбойников (часть 1)`**, треки 1–7~~ ⛔ **ОТМЕНЕНО в 36-й волне** → album `Али-Баба и сорок разбойников`, сквозные треки 1–14 | 7 | +> | `Али-Баба и сорок разбойников_2` | album **`…разбойников_2`** (маркер диска в теге!) | ~~**`… (часть 2)`**, треки 1–7~~ ⛔ **ОТМЕНЕНО в 36-й волне** → тот же album, треки 8–14 | 7 | > | `Ali baba i 40 razboinikov` (файлы `(1)`–`(6)`) | album `Али-Баба и 40 разбойников` | без изменений — **это ДРУГАЯ запись**, треки 1–6 | 6 | > > **Урок 1.** Транслит-папка = **отдельная запись**, а не продолжение русской. Своя нумерация с 1.