[2026-09-26] eagle: personal/plans/music-tags-review/music-tags-review.md personal/tech/music-tags-repair-truenas.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-26 19:45:58 +06:00
1 parent 5043d4bf50
commit a56483983a
2 files changed
+42 -17

No files matched your search

@@ -11,6 +11,13 @@ updated: '2026-09-26'
**К правке:** 6773 файлов · **без изменений:** 1133
> **✅ 21-я волна (2026-09-26): CSV ГОТОВ. 7907 строк, 0 битых. Ждём «go» на применение.**
> Разобраны блоки `Pushnoy.ru`/`Александр Пушной` (13 строк cur_artist) и `Infected Mushroom`
> (7 реальных дефектов: обрезки `Deeply Disturbed (Kobi Shalti-`, `elation station (beat hackers`;
> title = имя файла `Infected Mushoom - Saeed/Red Filter`; `Eyal Shechter` → title `Raash`;
> `U R So Fucked (GANDI Remix)`). 14 файлов `._*` (AppleDouble) помечены `skip`.
> Детали — [[personal/tech/music-tags-repair-truenas|tech/music-tags-repair-truenas]], 21-я волна.
> [!warning] Ничего не изменено
> Это план. Ставь галочки, что одобряешь. После «go» — бэкап в `Music/backup/` и применение.
+35 -17
View File
@@ -51,8 +51,12 @@ related:
> 🔴 **ТРЕТИЙ УРОК: нет данных → СПРАШИВАТЬ, не оставлять молча пустым.** `NSK.mp3` (2 копии)
> — artist пустой, вопрос Alex'у не задан → Alex: «Почему ты не спросил меня что с ним делать?!».
> Открытый вопрос теперь вынесен явно (см. ниже).
> 📊 **Сводные CSV (20-я волна):** `artists-single-track.csv` **777** + `artists-multi-track.csv`
> **7129** = **7906 — все строки покрыты.**
> 📊 **Сводные CSV (ПЕРЕСОБРАНЫ в 21-й волне):** `artists-single-track.csv` **3222** +
> `artists-multi-track.csv` **4669** = **7891 строк** (скрипт `rebuild_summaries.py` строит по
> признаку `new_track` и ФИЛЬТРУЕТ `action=skip` (14 AppleDouble) + `source=dropped` (надгробие) —
> отсюда 7891, а не 7906). **Старые 777+7129 — устарели**, не использовать. Считались грубым
> `awk`/`jq` (не парсят кавычки CSV) → правильный счётчик только `csv.DictReader`: **6009 строк
> с непустым `new_track`**.
> 🖐 **190 строк без artist (было 188 — +2 из-за `Перец` не считается, см. разбор):** 186
> `!Детские/Сказки/*` (artist не существует), `Голубой щенок/01 - Хоттабыч!`,
> `НАШЕСТВИЕ` (надгробие), **`NSK.mp3` ×2**. Живой разбор `NSK.mp3` на NAS: ID3v2.3 заголовок
@@ -60,7 +64,9 @@ related:
> Итог: **0 битых, 7907 строк, ручных правок ~641.**
> ⏭ Осталось: **решение по `NSK.mp3`** (A/B/C ниже) → бэкап `Music/backup/` → применение →
> приёмка в UI → Music-библиотека Jellyfin. Плюс merge-конфликт в `1-needs-decision.md`.
> **Бэкапы:** `...bak-20260926-185339` (последний), `bak-20260926-184122`, `bak-20260926-164432` (самый ранний).
> **Бэкапы (актуально на 21-ю волну):** 27 файлов `tag-fix-plan.csv.bak-20260926-HHMMSS` +
> `bak-194111-wave21` (сделан перед пересборкой сводок). Самый ранний — `...164432`, самый
> свежий — `...193421`. Все в `~/Downloads/music-tags/`.
>
> ---
>
@@ -403,36 +409,48 @@ file size 475954 Б ≈ 29 секунд ← валидный MP3, коро
- Питфолл `sed`: `\r\n`-split в Python даёт сдвиг номеров строк после правок — брать строки
по **тексту**, не по номеру (`grep -n`, потом `sed -n` для просмотра).
### 📊 6. Сводные CSV пересобраны после правок
### 📊 6. Сводные CSV пересобраны (21-я волна, актуальное)
`python3 ~/Downloads/music-tags/build_summaries.py` (read-only исходника, пишет 2 файла):
`python3 ~/Downloads/music-tags/rebuild_summaries.py` (read-only исходника, пишет 2 файла).
Ключевое отличие от старого `build_summaries.py`: строит по признаку **наличия `new_track`**
и **фильтрует `action=skip` + `source=dropped`**.
| Файл | Строк | Колонки |
|---|---:|---|
| `artists-single-track.csv` | **777** | `artist, title, album, path` |
| `artists-multi-track.csv` | **7129** | `artist, album, track, title, path` |
| `artists-single-track.csv` | **3222** | `artist, title, album, path` |
| `artists-multi-track.csv` | **4669** | `artist, album, track, title, path` |
**777 + 7129 = 7906 — покрыты ВСЕ строки** (проверка `TOTAL COVERED` встроена в скрипт).
Пустой artist → sentinel **`(без исполнителя)`**; для сказок ключ `(без исполнителя) — <album>`.
**3222 + 4669 = 7891** = 7906 − 14 AppleDouble − 1 надгробие. Пустой artist → sentinel
**`(без исполнителя)`**. Сортировка: artist → album → track (числа первыми, потом строки).
### 📊 СОСТОЯНИЕ НА КОНЕЦ ДВАДЦАТОЙ ВОЛНЫ
> 🔴 **ПИТФОЛЛ СЧЁТЧИКОВ:** `awk -F','` / `jq -R split(",")` **НЕ парсят кавычки CSV** → дают
> 4669 вместо реальных **6009** строк с `new_track`. Для любых подсчётов по этому файлу —
> **только `csv.DictReader`** (как в `rebuild_summaries.py`).
> 🔴 Старые цифры **777 + 7129** (метод «группировка по исполнителю») больше не действительны —
> читать файлы с этим скриптом.
### 📊 СОСТОЯНИЕ НА КОНЕЦ ДВАДЦАТЬ ПЕРВОЙ ВОЛНЫ
| Показатель | Значение |
|---|---:|
| Строк в CSV | 7906 данных + заголовок = **7907** |
| **Битых строк** | **0** |
| CRLF-потерь | **0** |
| Ручных правок | **~641** |
| AppleDouble `._*` (skip) | **14** |
| Надгробие (dropped) | **1** (`НАШЕСТВИЕ 2009`) |
| Строк без artist | **190** (186 сказки + 4 прочие) |
| Сводные CSV | ✅ 777 + 7129 = 7906 |
| Сводные CSV | ✅ 3222 + 4669 = 7891 |
| Бэкапов | **27** |
| Применение на NAS | **НЕ начато (ждём «go»)** |
**Бэкапы:** `bak-20260926-185339` (последний, 20-я волна), `bak-20260926-184122`,
`bak-20260926-164432` (самый ранний).
**Бэкапы (21-я волна):** 27 файлов: `tag-fix-plan.csv.bak-20260926-HHMMSS` (самый свежий
`...193421`, самый ранний `...164432`) + `bak-194111-wave21` (перед пересборкой сводок).
**Рабочие скрипты `~/Downloads/music-tags/`:**
`diag_fields.py` (гистограмма полей), `build_summaries.py` (2 сводные CSV),
`list_noartist.py` (**новый, 20-я волна** — полный список строк без artist по папкам),
**Рабочие скрипты `~/Downloads/music-tags/` (все read-only по исходнику):**
`diag_fields.py` (гистограмма полей), **`rebuild_summaries.py`** (21-я волна — 2 сводные CSV,
строит по `new_track` + фильтрует skip/dropped; **заменяет `build_summaries.py`**),
`build_summaries.py` (старый, 20-я волна — даёт устаревшие 777+7129, не использовать),
`list_noartist.py` (список строк без artist по папкам),
`probe_nsk.py` (живой разбор ID3 — переиспользован для дампа кадров),
`repair_broken.py` / `repair_min.py` (черновики, **не применялись** — регрессия починена вручную).