From d7a3e90631f15f042d1fd6703a6176accb0bb4c7 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sat, 26 Sep 2026 20:16:28 +0600 Subject: [PATCH] [2026-09-26] eagle: personal/tech/music-tags-final-review.md personal/tech/music-tags-repair-truenas.md --- personal/tech/music-tags-final-review.md | 35 ++++++++- personal/tech/music-tags-repair-truenas.md | 89 +++++++++++++++++++++- 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/personal/tech/music-tags-final-review.md b/personal/tech/music-tags-final-review.md index b2c188cb..92ccc97d 100755 --- a/personal/tech/music-tags-final-review.md +++ b/personal/tech/music-tags-final-review.md @@ -18,9 +18,11 @@ related: _Обновлено: 2026-09-26. Источник: `~/Downloads/music-tags/tag-fix-plan.csv`._ -> ## ✅ ГОТОВО К АППРУВУ +> ## ✅ ГОТОВО К АППРУВУ (28-я волна) > **Построчное чтение завершено: 1–7906 (100%).** 27-я волна закрыла блок 6402–7906. +> 28-я волна добавила **сквозную нумерацию треков по дискам** (9 многодисковых альбомов). > Все проверки пройдены. Жду слово Alex («go») для бэкапа и применения тегов. +> ⚠️ Открытый вопрос: 104 дубля `(album, track)` — копии релизов в разных папках (дедупликация). > Полный контекст волн — `personal/tech/music-tags-repair-truenas.md`. ## Состав файлов @@ -28,10 +30,12 @@ _Обновлено: 2026-09-26. Источник: `~/Downloads/music-tags/tag-f | Файл | Строк | Что это | |---|---|---| | `tag-fix-plan.csv` | 7906 | Главный план правок, 11 колонок | -| `artists-single-track.csv` | 3223 | Разбивка: треки БЕЗ номера (artist/title/album/path) | -| `artists-multi-track.csv` | 4667 | Разбивка: треки С номером (artist/album/track/title/path) | +| `artists-single-track.csv` | 3196 | Разбивка: треки БЕЗ номера (artist/title/album/path) | +| `artists-multi-track.csv` | 4694 | Разбивка: треки С номером (artist/album/track/title/path) | | | **7890** | = сумма сводок (16 строк отфильтрованы: 15 skip + 1 намеренно пустая) | +_Сводки пересобраны в 28-й волне после сквозной нумерации (`rebuild_summaries.py`)._ + ## Действия | action | строк | смысл | @@ -81,3 +85,28 @@ _Обновлено: 2026-09-26. Источник: `~/Downloads/music-tags/tag-f - `ty_49` / `пакет.mp3` (`!Radio/y OOF/`) — оставлен. - 46 уникальных альбомов после снятия года — с официальными треклистами не сверялись (кроме Pushnoy, где регрессия найдена и исправлена). + +## Сквозная нумерация по дискам (28-я волна) + +9 многодисковых альбомов перенумерованы непрерывно (Диск N = offset от суммы треков +предыдущих дисков). Все — без дыр и дублей: + +| Album | Итог | Треков | +|---|---|---:| +| `Final Fantasy VI: Balance and Ruin` | 1–74 | 74 | +| `изBESTняк` | 1–40 | 40 | +| `Алиса в Стране Чудес` (2 диска + транслит-папка) | 1–34 | 34 | +| `Трое из Простоквашино` | 1–20 | 20 | +| `Лунапарк` | 1–19 | 19 | +| `Live Aus Berlin [Limited Edition]` | 1–18 | 18 | +| `Принц и нищий` | 1–14 | 14 | +| `Малыш и Карлсон` | 1–6 | 6 | +| `Остров сокровищ` | 1–6 | 6 | + +## ⚠️ Открытый вопрос: 104 дубля `(album, track)` + +Это **не диски**, а одни и те же релизы, лежащие в двух папках на диске +(`Город дорог` 15, `Мат без электричества` 13, `Живая коллекция` 13, +`Второй Магаданский` 11, `Lies For The Liars` 11, `Ч\Б` 8, +`Аристократия помойки 1–4`, `Война и мир`, `Ветер в голове`, `SMS`, `MCMXC A.D.` и др.). +Решаются **дедупликацией файлов**, не нумерацией. Нужно решение Alex. diff --git a/personal/tech/music-tags-repair-truenas.md b/personal/tech/music-tags-repair-truenas.md index 55b991f7..be7cb8c5 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: 27 +wave: 28 tags: - music - jellyfin @@ -20,6 +20,93 @@ related: # Music Tags Repair — TrueNAS (7906 файлов) +> ## ✅ ДВАДЦАТЬ ВОСЬМАЯ ВОЛНА (2026-09-26) — СКВОЗНАЯ НУМЕРАЦИЯ ТРЕКОВ ПО ДИСКАМ +> +> Триггер: Alex — «там где ты убрал номера дисков из альбомов (сказки) теперь треки дублированы, +> нужно для вторых дисков сквозную нумерацию». +> +> ### Суть проблемы +> В волнах 23–26 из `new_album` снимались год-префиксы и диск-суффиксы +> (`Трое из Простоквашино (Диск 2)` → `Трое из Простоквашино`). Для многодисковых релизов это +> **склеило разные диски в один album**: у Диска 1 и Диска 2 остались одинаковые `new_track` +> (1, 2, 3 …). В Jellyfin это выглядит как дубликаты треков. +> +> ### Решение: сквозная нумерация +> Диск N получает offset = сумма числа треков всех дисков с меньшим номером. +> Порядок внутри диска — по номеру из имени файла (не по текущему `new_track`). +> +> ### Итог — 9 альбомов (119+ треков), все непрерывны без дыр и дублей +> +> | Album | Диски (исходные папки) | Кол-во треков | Итог | +> |---|---|---:|---| +> | `Final Fantasy VI: Balance and Ruin` | Disc 1–5 (`Mc 5 - Bonus`) | 17/17/16/10/14 | **1–74** | +> | `Алиса в Стране Чудес` | `(Диск1)`,`(Диск2)`,`Alisa v strane chudes` | 13/13/8 | **1–34** | +> | `изBESTняк` | `CD 1`,`CD 2` | 20/20 | **1–40** | +> | `Лунапарк` | `CD1`,`CD2` | 12/7 | **1–19** | +> | `Live Aus Berlin [Limited Edition]` | `…CD1`,`…CD2` | 12/6 | **1–18** | +> | `Принц и нищий` | `(Диск 1)`,`(Диск 2)` | 7/7 | **1–14** | +> | `Трое из Простоквашино` | `(Диск 1)`,`(Диск 2)` | 9/11 | **1–20** | +> | `Малыш и Карлсон` | `(Диск 1)`,`(Диск 2)` | 3/3 | **1–6** | +> | `Остров сокровищ` | `(Диск 1)`,`(Диск 2)` | 4/2 | **1–6** | +> +> ### 🔴 ГЛАВНЫЙ УРОК ВОЛНЫ: НЕИДЕМПОТЕНТНЫЙ СКРИПТ +> Первая версия (`fix_disc_auto.py`) читала **текущий** `new_track` и прибавляла offset. +> Повторный прогон прибавил offset **второй раз** (Disc 4: 10 → 60 → 110). +> Alex получил бы молча испорченный файл, если бы скрипт по ошибке запустили дважды. +> **Правило:** любой скрипт, меняющий номер, обязан считать цель **от исходного значения +> (номер из имени файла), а не от текущего**. Второй прогон должен давать «nothing». +> Финальный `fix_disc_final.py` — идемпотентен, проверено вторым прогоном (0 изменений). +> Откат делался из `bak-*-disc` (состояние ДО всех disc-правок). +> +> ### 🔴 ВТОРОЙ УРОК: Unicode-нормализация имён папок +> Папка `Принц и нищий (Диск 2)` существовала в **двух разных формах**: NFC и NFD +> (combining breve `U+0306` в слове «нищий»). `csv`/`os` их не различают визуально, +> поэтому album разъехался на `Принц и нищий` и `Принц и нищий`, а номера — на 1-7 / 9-14 / 8. +> Лечение: `unicodedata.normalize("NFC", …)` перед любыми сравнениями имён папок/альбомов. +> **При склейке альбомов всегда нормализовать Unicode.** +> +> ### 🔴 ТРЕТИЙ УРОК: транслит-папка = ещё один диск +> `Alisa v strane chudes` (латиница, 8 треков) — это **третий диск** того же релиза, не отдельный +> альбом. Распознаётся по совпадению набора треков с кириллическими папками. Не группировать +> по признаку «кириллица/латиница в имени папки» — группировать по совпадению содержимого. +> +> ### ⚠️ ОСТАЛОСЬ (НЕ диски — отдельная задача) +> 104 пары `(album, track)` дублируются, но это **одни и те же релизы в двух папках на диске**, +> а не диски: `Город дорог` (15), `Мат без электричества` (13), `Живая коллекция` (13), +> `Второй Магаданский` (11), `Lies For The Liars` (11), `Ч\Б` (8), `Аристократия помойки 1–4`, +> `Война и мир`, `Ветер в голове`, `SMS`, `MCMXC A.D.`, `Oblivion`-синглы и др. +> Решаются **дедупликацией файлов**, не нумерацией. Ждут решения Alex. +> +> ### 📊 ФИНАЛЬНОЕ СОСТОЯНИЕ (28-я волна) +> +> | Показатель | Значение | +> |---|---:| +> | `tag-fix-plan.csv` | **7906 строк, 0 битых** | +> | `fix` / `no_change` / `skip` | **6934 / 957 / 15** | +> | `artists-single-track.csv` | **3196** | +> | `artists-multi-track.csv` | **4694** | +> | Сумма сводок | **7890** | +> | Многодисковых альбомов со сквозной нумерацией | **9** | +> | Остаточных дублей `(album, track)` | **104** (копии релизов в разных папках) | +> +> ### 🛠 СКРИПТЫ ВОЛНЫ (все по схеме tmp + валидация + `os.replace`) +> - `fix_disc_auto.py` — ❌ **отозван**, неидемпотентен (накапливает offset). +> - `fix_disc_tracks.py` / `_2` / `_3` — промежуточные, тоже отозваны. +> - `fix_disc_final.py` — ✅ **рабочий**: сквозная нумерация 8 альбомов, идемпотентен. +> - `fix_disc_fixup.py` — выравнивание album `Принц и нищий` (+ Лунапарк из имён файлов). +> - `fix_alisa3.py` — транслит-папка как 3-й диск (`+26`). +> +> ⏭ **СЛЕДУЮЩИЙ ШАГ (ждёт слова Alex):** +> 1. Решение по 104 дублям релизов: разбирать (дедупликация) или принять как есть. +> 2. Alex глазами проверяет `artists-single-track.csv` / `artists-multi-track.csv` → **аппрув**. +> 3. После аппрува: бэкап в `Music/backup/` → применение → приёмка в UI Jellyfin → +> `rm -rf Music/backup/` → создание Music-библиотеки. +> +> **Бэкапы 28-й волны:** `bak-*-disc`, `bak-*-disc2`, `bak-*-disc3`, `bak-*-discauto`, +> `bak-*-broken-double`, `bak-*-discfinal`, `bak-*-fixup`, `bak-*-alisa3`, `bak-*-disclast`. +> +> --- +> > ## ✅ ДВАДЦАТЬ СЕДЬМАЯ ВОЛНА (2026-09-26) — ПОСТРОЧНОЕ ЧТЕНИЕ ЗАВЕРШЕНО: 1–7906 (100%) > > **Весь файл прочитан глазами построчно. Готов к аппруву Alex.** Триггер: Alex —