[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:
1 parent
82f27a69da
commit
31644d1010
2 files changed
+397
-18
No files matched your search
@@ -20,6 +20,49 @@ updated: '2026-09-26'
|
||||
| [[2-medium-confidence\|Средняя уверенность]] | 5813 |
|
||||
| [[3-high-confidence\|Высокая уверенность]] | 959 |
|
||||
|
||||
## 🔴 Девятнадцатая волна (2026-09-26): ИМЕНА ДИСКОВ ВЫЧИЩЕНЫ + NSK РАЗОБРАН
|
||||
|
||||
Alex: **«Откуда строки с пустым артистом? Это косяк»** → **«Что за NSK? ... Больше нет
|
||||
треков без артиста?»**
|
||||
|
||||
### 🛠 Имена дисков/техпапок в `new_album` — ВЫЧИЩЕНЫ (200 строк)
|
||||
|
||||
**Папка `!Детские/Сборка Песни для детей/` разбита на подпапки-«диски»** (`1`,`2`,`C`,`K`,`L`,`M`,`P`,`Y`,`Les`),
|
||||
и граббер записал имя подпапки в `new_album`. **Это часть пути, не альбом** → 155 строк очищены,
|
||||
реальный альбом `Сборка Песни для детей`. Тот же класс: `misc` (~40: Пилот, Rammstein,
|
||||
Красная Плесень, Eminem), `new` (3, НТЛ), `Album` (1, Пилот) → пусто.
|
||||
|
||||
> ⚠️ Побочно: у `19. Песенка смелого моряка` при вырезании диска съехал `new_track` (был 20).
|
||||
> Проверять `new_track` рядом с вырезаемым `new_album`.
|
||||
|
||||
### 🤔 188 строк без artist — НЕ косяк (проверено по самому раннему бэкапу)
|
||||
|
||||
| Источник | Кол-во |
|
||||
|---|---:|
|
||||
| `!Детские/Сказки/*` — аудиосказки, исполнителя нет | 186 |
|
||||
| `5 POPSA` нарезки (NSK, Перец…) — ID3-кадры пустые | ~12 |
|
||||
| `НАШЕСТВИЕ 2009`, `Голубой щенок` | 2 |
|
||||
|
||||
### 🔬 `NSK.mp3` — разбор живьём на NAS
|
||||
|
||||
`ID3 v2.3` заголовок есть (size=1014), но **кадры пустые** (нули) → тегов нет.
|
||||
MPEG-заголовок `0xFFFB9240` = 128 kbps / 44100 Hz, файл 476 КБ ≈ **29 секунд** — нарезка
|
||||
чарт-сборника. `NSK` = имя файла (вероятно «Новосибирск»), **НЕ название песни**.
|
||||
Artist оставлен **пустым**, а не выдуман.
|
||||
|
||||
**Питфоллы окружения (закрепить):** `ffprobe` молча пусто на пустом ID3; `mutagen` на NAS
|
||||
НЕ установлен; `xxd` на NAS НЕТ; вложенные кавычки в `ssh 'python3 -c "..."'` ломаются →
|
||||
**скрипт локально + `scp` в `/tmp/` + `ssh … 'python3 /tmp/x.py'`**.
|
||||
|
||||
### ⏭ ЖДЁМ РЕШЕНИЯ ALEX по ~12 нарезкам `5 POPSA`
|
||||
|
||||
**A)** вписать artist/title вручную (нужен ID по звуку); **B)** оставить пустым;
|
||||
**C)** `no_change` — не трогать файлы. Сказки (186) — предлагается оставить как есть.
|
||||
|
||||
### 📊 Итог 19-й волны
|
||||
|
||||
`fix` **6931** / `no_change` **976** · 0 битых · 7907 строк · все CRLF · сводные CSV 778 + 7128 = 7906.
|
||||
|
||||
## 🔴 Восемнадцатая волна (2026-09-26): РЕГРЕССИЯ ПОЧИНЕНА + ДВЕ СВОДНЫЕ CSV СОБРАНЫ
|
||||
|
||||
Alex: **«Рэпер сява - поправь на просто "Сява"»** + **«подготовить рядом ещё пару csv»**.
|
||||
|
||||
@@ -4,7 +4,7 @@ created: '2026-09-26'
|
||||
updated: '2026-09-26'
|
||||
type: tech
|
||||
namespace: personal
|
||||
wave: 17
|
||||
wave: 20
|
||||
tags:
|
||||
- music
|
||||
- jellyfin
|
||||
@@ -20,23 +20,32 @@ related:
|
||||
|
||||
# Music Tags Repair — TrueNAS (7906 файлов)
|
||||
|
||||
> **Статус: ВОСЕМНАДЦАТАЯ ВОЛНА (2026-09-26). CSV ГОТОВ К ПРИМЕНЕНИЮ.
|
||||
> `Рэпер Сява`→`Сява`; РЕГРЕССИЯ 18 БИТЫХ СТРОК ПОЧИНЕНА (0 битых); ДВЕ СВОДНЫЕ CSV СОБРАНЫ.
|
||||
> NAS ДОСТУПЕН, применение НЕ начато — ждём «go».**
|
||||
> ✅ **НОВОЕ (18-я волна):** исправлена **собственная регрессия** — при вырезании техпапок из
|
||||
> `new_album` в `z Старое/disk*` (17-я волна) терялись запятые → 18 битых строк. Все починены.
|
||||
> **Урок: после каждого батча считать ЧИСЛО ПОЛЕЙ, не только кавычки и длину файла.**
|
||||
> Диагностика: `python3 ~/Downloads/music-tags/diag_fields.py` (гистограмма полей, строки ≠ 11).
|
||||
> 📊 **Две сводные CSV** (`build_summaries.py`, только чтение): `artists-single-track.csv`
|
||||
> (**778** строк: artist/title/album/path) + `artists-multi-track.csv` (**7128** строк:
|
||||
> artist/album/track/title/path). **778 + 7128 = 7906 — покрыты все строки.** Сортировка
|
||||
> artist→album→track. Пустой artist → sentinel `(без исполнителя)` (иначе Excel схлопнет).
|
||||
> 🖐 **188 строк без artist — НЕ косяк:** 186 из них `!Детские/Сказки/*` (аудиосказки без
|
||||
> единого исполнителя), + `НАШЕСТВИЕ 2009`, + `Голубой щенок`. Так было с самого начала.
|
||||
> Итог: **0 битых, 7907 строк, `fix` 6931 / `no_change` 976, ручных правок ~640.**
|
||||
> ⏭ Осталось ТОЛЬКО применение: бэкап `Music/backup/` → применение → приёмка в UI →
|
||||
> Music-библиотека Jellyfin. Плюс (отдельно) merge-конфликт в `1-needs-decision.md`.
|
||||
> **Бэкапы:** `...bak-20260926-184122` (последний до регрессии), `bak-20260926-164432` (самый ранний).
|
||||
> **Статус: ДВАДЦАТАЯ ВОЛНА (2026-09-26). CSV ГОТОВ, 0 БИТЫХ СТРОК, 7907 строк.
|
||||
> Ждём решения по `NSK.mp3` + «go» на применение.**
|
||||
> ✅ **НОВОЕ (20-я волна):** `Перец.mp3` (2 копии в `disk*`) → `Перцы`/`Валдай` (решение Alex
|
||||
> из `2-medium-confidence.md` — было пропущено); все сводные CSV пересобраны (777 + 7129).
|
||||
> 🔴 **ГЛАВНЫЙ УРОК ВОЛНЫ: ПЕРЕД ОТВЕТОМ ОБ ARTIST/ПРОБЛЕМНОЙ СТРОКЕ — ОТКРЫТЬ НОТЫ РЕВЬЮ.**
|
||||
> Alex: «Перец я тебе в доку выписывал! В чем трабл??» — решение **уже было в
|
||||
> `personal/plans/music-tags-review/2-medium-confidence.md`**, ассистент ответил по памяти
|
||||
> и оставил `Перец`/пусто. Проверять `personal/plans/music-tags-review/*.md` grep'ом по имени
|
||||
> файла, не полагаться на CSV `new_artist`.
|
||||
> 🔴 **ВТОРОЙ УРОК: строка-НАДГРОБИЕ ≠ строка к обработке.** `НАШЕСТВИЕ 2009` помечен
|
||||
> `no_change` + `source = dropped (file removed by user)` — файла нет. Выносить такие строки
|
||||
> в списки «требуют решения» нельзя — Alex: «Нашествие мы блядь снесли откуда он опять взялся?!».
|
||||
> Фильтровать `source` начинающийся с `dropped` при любых отчётах.
|
||||
> 🔴 **ТРЕТИЙ УРОК: нет данных → СПРАШИВАТЬ, не оставлять молча пустым.** `NSK.mp3` (2 копии)
|
||||
> — artist пустой, вопрос Alex'у не задан → Alex: «Почему ты не спросил меня что с ним делать?!».
|
||||
> Открытый вопрос теперь вынесен явно (см. ниже).
|
||||
> 📊 **Сводные CSV (20-я волна):** `artists-single-track.csv` **777** + `artists-multi-track.csv`
|
||||
> **7129** = **7906 — все строки покрыты.**
|
||||
> 🖐 **190 строк без artist (было 188 — +2 из-за `Перец` не считается, см. разбор):** 186
|
||||
> `!Детские/Сказки/*` (artist не существует), `Голубой щенок/01 - Хоттабыч!`,
|
||||
> `НАШЕСТВИЕ` (надгробие), **`NSK.mp3` ×2**. Живой разбор `NSK.mp3` на NAS: ID3v2.3 заголовок
|
||||
> 1014 Б, **0 кадров** (тело — нули), аудио валидно: 128 kbps / 44100 Hz / **~29 сек**.
|
||||
> Итог: **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` (самый ранний).
|
||||
>
|
||||
> ---
|
||||
>
|
||||
@@ -92,6 +101,333 @@ related:
|
||||
> Прогонялись **девять волн** проверок: см. таблицу волн ниже.
|
||||
> Итог v7: «требует решения» **4**, medium **5811**, high **958**, mojibake = 0, остаточный mojibake = 0.
|
||||
|
||||
## 🖐 ДЕВЯТНАДЦАТАЯ ВОЛНА: СЯВА, РЕГРЕССИЯ, ИМЕНА ДИСКОВ, СВОДНЫЕ CSV (2026-09-26)
|
||||
|
||||
> Триггер: Alex — **«Закончи правку имен песен в csv. Вручную»** → далее **«Доделывай»**,
|
||||
> затем **«Откуда строки с пустым артистом? Это косяк»** → **«Что за NSK? Ты что туда
|
||||
> вписал как артист/трек? Больше нет треков без артиста?»**
|
||||
|
||||
### ✅ 1. `Рэпер Сява` → `Сява` (2 строки)
|
||||
|
||||
Alex: **«Рэпер сява - поправь на просто "Сява"»**. Обе строки в папке
|
||||
`!Pop, Club, Любэ/!Radio/v 2009-03 mIr.vEsNЫ/2 y.MATno.E/`:
|
||||
- `Нука нака.mp3` → `new_artist = Сява` (было `Рэпер Сява`)
|
||||
- `Отдыхаем хорошо(Ida Corr cocktail).mp3` → artist `DJ Иван Silver & Сява`
|
||||
|
||||
> 🔴 **Ошибка при правке:** `patch mode=replace` дал fuzzy-match и **съел первую строку** —
|
||||
> `old_string` совпал частично. Строк стало 7906 вместо 7907. **Обнаружено** сверкой
|
||||
> `diff <(sed 's/Рэпер Сява/Сява/g' bak-184122) tag-fix-plan.csv`. Восстановлено вручную
|
||||
> (вернул строку `Ленинград - Ласточка.mp3`, потерянную при починке).
|
||||
> **Правило: `patch mode=replace` — только по УНИКАЛЬНОМУ тексту; после — сразу `wc -l`.**
|
||||
|
||||
### 🔴 2. РЕГРЕССИЯ 18 БИТЫХ СТРОК — ПОЧИНЕНА (главное этой волны)
|
||||
|
||||
Alex: **«Откуда строки с пустым артистом? Это косяк»**.
|
||||
|
||||
**Диагностика по бэкапам (гистограмма числа полей по волнам):**
|
||||
|
||||
| Бэкап | 3 поля | 10 | 11 | 12 |
|
||||
|---|---:|---:|---:|---:|
|
||||
| `bak-164432` (самый ранний, 15:15) | 2 | 2 | 7904 | 0 |
|
||||
| `bak-171423` | 2 | 2 | 7904 | 0 |
|
||||
| `bak-180619` (после 17-й волны) | 2 | **10** | 7886 | **10** |
|
||||
| `bak-184122` | 2 | 10 | 7886 | 10 |
|
||||
|
||||
**Вывод: 4 битые строки были ИЗНАЧАЛЬНО** (Пахмутова — многострочный mojibake с `"` внутри,
|
||||
разваливал парсинг). **Остальные 18 — регрессия 17-й волны:** при вырезании техпапок из
|
||||
`new_album` в `z Старое/disk*` (`disk`, `disk_v2`, `5 POPSA`, `2 ALT,PUNK`, `3 SHANSON`)
|
||||
**терялась ровно одна пустая запятая-плейсхолдер**.
|
||||
|
||||
**Три подкласса фикса:**
|
||||
|
||||
| Строк | Дефект | Фикс |
|
||||
|---:|---|---|
|
||||
| 8 | 10 полей — потерян пустой `new_album` | `NSK,,,fix` → `NSK,,,,fix` |
|
||||
| 9 | 12 полей — лишняя пустая запятая | `Nickelback,,,7,fix` → `Nickelback,,7,fix` |
|
||||
| 2 (Трофим) | 12 полей — **запятая в `Короче, дело к ночи` без кавычек** | `,"Короче, дело к ночи",Трофим,,4,fix` |
|
||||
| 2 (Пахмутова) | 3/10 полей — многострочный mojibake с `"` внутри | значение заменено на читаемое `"Пахмутова — Нежность"` / `"Нежность"` |
|
||||
|
||||
**Итог: 22 битых → 0.** Проверено: `diag_fields.py` + `wc -l` = 7907 + CRLF = 7907 + BOM на месте.
|
||||
|
||||
> 🔴 **ПРАВИЛО (закрепить навсегда): после КАЖДОГО батча — считать ЧИСЛО ПОЛЕЙ, не кавычки.**
|
||||
> Проверка кавычек (`awk -F'"' 'NF%2==0'`) и длины файла **НЕ ловит** потерю пустого поля:
|
||||
> 10-полевая строка имеет чётное число кавычек и проходит все старые чекеры.
|
||||
> ```bash
|
||||
> python3 ~/Downloads/music-tags/diag_fields.py # гистограмма: должно быть {11: 7906}
|
||||
> ```
|
||||
|
||||
### 🛠 3. БУКВЕННЫЕ/ЦИФРОВЫЕ ИМЕНА ДИСКОВ В `new_album` — ВЫЧИЩЕНЫ (200 строк)
|
||||
|
||||
**Главный новый класс дефекта.** Папка `!Детские/Сборка Песни для детей/` разбита на
|
||||
подпапки-«диски» (`1`, `2`, `C`, `K`, `L`, `M`, `P`, `Y`, `Les`), и скрипт-граббер записал
|
||||
имя подпапки в `new_album`. **Это часть пути, а не альбом.**
|
||||
|
||||
| Значение `new_album` | Строк | Реальный альбом |
|
||||
|---|---:|---|
|
||||
| `1`, `2`, `C`, `K`, `L`, `M`, `P`, `Y`, `Les` | **155** | `Сборка Песни для детей` |
|
||||
| `misc` (Пилот, Rammstein, Красная Плесень, Eminem) | ~40 | пусто (нет реального альбома) |
|
||||
| `new` (НТЛ) | 3 | пусто |
|
||||
| `Album` (Пилот `Братишка.mp3`) | 1 | пусто |
|
||||
|
||||
Диагностический детектор:
|
||||
```bash
|
||||
awk -F',' 'NR>1 {n=NF; na=(n==11)?8:((n==13)?10:((n==12)?9:0));
|
||||
if(na && length($na)<=4 && $na ~ /^[A-Za-z0-9_]+$/ && $na !~ /[а-яА-Я]/) print NR"|"$na}' tag-fix-plan.csv
|
||||
```
|
||||
|
||||
> ⚠️ **Пойман побочный дефект:** в `Сборка Песни для детей` строка `19. Песенка смелого моряка`
|
||||
> содержала `new_album = 1` и `new_track = 20` — при вырезании диска номер трека съехал.
|
||||
> Проверять `new_track` рядом с вырезаемым `new_album`.
|
||||
|
||||
### 📊 4. ДВЕ СВОДНЫЕ CSV (запрос Alex)
|
||||
|
||||
Alex: **«подготовить рядом ещё пару csv: все исполнители с одним треком + путь; все
|
||||
исполнители с более 1 трека, альбом, треки в альбоме, путь. С сортировкой
|
||||
исполнитель/альбом/номер трека. (Имеются в виду исправленные названия для записи)
|
||||
Эти две csv должны включать все строки из оригинальной csv.»**
|
||||
|
||||
Скрипт: `~/Downloads/music-tags/build_summaries.py` (**только чтение** исходника, пишет 2 файла).
|
||||
|
||||
| Файл | Строк | Колонки |
|
||||
|---|---:|---|
|
||||
| `artists-single-track.csv` | **778** | `artist, title, album, path` |
|
||||
| `artists-multi-track.csv` | **7128** | `artist, album, track, title, path` |
|
||||
|
||||
- **778 + 7128 = 7906 — покрыты ВСЕ строки** (проверка встроена в скрипт, печатает `TOTAL COVERED`).
|
||||
- Значения берутся из `new_*`, при пустом — fallback на `cur_*`.
|
||||
- Сортировка: artist → album → track (числовая, `track_key()` с regex `^(\d+)`).
|
||||
- Пустой artist → sentinel **`(без исполнителя)`**, иначе Excel схлопывает группу в невидимую.
|
||||
|
||||
> 🔴 **ПЕРВАЯ ВЕРСИЯ СКРИПТА БЫЛА БИТАЯ:** писала `e["artist"]` (пустой) вместо ключа группировки
|
||||
> `e["key"]` → **189 строк с пустым artist** в `multi`. Alex поймал сразу. Фикс: писать `key`.
|
||||
> **Урок: sentinel бесполезен, если в вывод идёт исходное поле, а не ключ.**
|
||||
|
||||
### 🖐 5. 188 СТРОК БЕЗ ARTIST — РАЗОБРАНЫ ЖИВЬЁМ (не косяк)
|
||||
|
||||
Alex: **«Больше нет треков без артиста?»**
|
||||
|
||||
| Источник | Кол-во | Вердикт |
|
||||
|---|---:|---|
|
||||
| `!Детские/Сказки/*` | 186 | аудиосказки — исполнителя **не существует** (сборник, не песня). Оставить пустым |
|
||||
| `5 POPSA` нарезки (NSK, Перец и др.) | ~12 | ID3-кадры пустые — определять не из чего |
|
||||
| `НАШЕСТВИЕ 2009 - ДЕНЬ ВТОРОЙ.mp3`, `Голубой щенок/01 - Хоттабыч!.mp3` | 2 | фестивальная нарезка / сказка |
|
||||
|
||||
**Проверка по самому раннему бэкапу `bak-164432` подтвердила: так было ИЗНАЧАЛЬНО**, не регрессия.
|
||||
|
||||
### 🔬 6. `NSK.mp3` — ЖИВОЙ РАЗБОР ФАЙЛА НА NAS
|
||||
|
||||
Alex: **«Что за NSK? Ты что туда вписал как артист/трек?»**
|
||||
|
||||
Строка: `new_title = NSK`, `new_artist` = пусто, `new_album` = пусто.
|
||||
|
||||
**Метод (питфоллы окружения):**
|
||||
- `ffprobe` в контейнере/на хосте **молча отдаёт пусто** при битом/пустом ID3 — известный питфолл.
|
||||
- `mutagen` на хосте NAS **НЕ установлен** (`ModuleNotFoundError`).
|
||||
- `xxd` на хосте NAS **НЕТ** (`command not found`).
|
||||
- **Вложенные кавычки в `ssh 'python3 -c "..."'` ломаются** (bash/zsh на NAS). **Рабочий путь:
|
||||
написать скрипт локально → `scp` в `/tmp/` → `ssh … 'python3 /tmp/script.py'`** (совпадает
|
||||
с каноном из `family/how-to/truenas-access.md`).
|
||||
|
||||
**Результат разбора (байты, `python3` на хосте NAS):**
|
||||
```
|
||||
ID3 v2.3 rev0 flags=0x0 size=1014 ← заголовок есть
|
||||
кадров: 0 (тело — нули) ← теги ПОЛНОСТЬЮ пустые
|
||||
audio starts at 1024, first sync 0xFFFB9240 → 128 kbps, 44100 Hz
|
||||
файл 475954 Б ≈ 29 секунд ← валидный MP3, короткая нарезка
|
||||
```
|
||||
|
||||
**Вывод: `NSK.mp3` — 29-секундная нарезка из чарт-сборника с пустыми тегами.** `NSK` в title —
|
||||
это **имя файла** (первые буквы, вероятно от названия сборника/«Новосибирск»), **НЕ название
|
||||
песни**. Раньше в artist лежало `disk_v2`/`5 POPSA` (мусорные папки) — вычищено, artist оставлен
|
||||
**пустым**, а не выдуман.
|
||||
|
||||
> 📌 **Канон `id3_direct.py`:** запускать на **ХОСТЕ** NAS (`truenas_admin@mallexxx.duckdns.org`,
|
||||
> python3 3.11.9 есть) — в контейнере `jellyfin` python3 НЕТ (см. `family/how-to/truenas-access.md`).
|
||||
|
||||
### ⏭ ОТКРЫТЫЙ ВОПРОС К ALEX (ждём ответа)
|
||||
|
||||
По ~12 нарезкам из `5 POPSA` (NSK, Перец, Саундтрек Простоквашено и др.) — три варианта:
|
||||
**A)** вписать artist/title вручную (нужен ID по звуку); **B)** оставить `(без исполнителя)`;
|
||||
**C)** пометить `no_change` — файлы не трогать. Сказки (186) — предлагается оставить как есть.
|
||||
|
||||
### 📊 СОСТОЯНИЕ НА КОНЕЦ ДЕВЯТНАДЦАТОЙ ВОЛНЫ
|
||||
|
||||
| Показатель | Значение |
|
||||
|---|---:|
|
||||
| Строк в CSV | 7906 (+1 заголовок = 7907 в файле) |
|
||||
| **Битых строк** | **0** |
|
||||
| CRLF-потерь | **0** |
|
||||
| Ручных правок (`source = manual (user decision)`) | **~640** |
|
||||
| `fix` / `no_change` | **6931 / 976** |
|
||||
| Сайтов-источников / иероглифов в `new_*` | **0 / 0** |
|
||||
| Техпапок и букв-дисков в `new_album` | **0** |
|
||||
| Сводные CSV | ✅ 778 + 7128 = 7906 |
|
||||
| Применение на NAS | **НЕ начато (ждём «go»)** |
|
||||
|
||||
**Бэкапы:** `bak-20260926-164432` (самый ранний), `bak-20260926-171423`, `bak-20260926-180619`,
|
||||
`bak-20260926-183432`, `bak-20260926-183541`, `bak-20260926-184029`, `bak-20260926-184122`.
|
||||
|
||||
**Рабочие скрипты в `~/Downloads/music-tags/` (все read-only, кроме `build_summaries.py`):**
|
||||
`diag_fields.py` (гистограмма полей), `build_summaries.py` (2 сводные CSV),
|
||||
`repair_broken.py` / `repair_min.py` (черновики починки регрессии — **не применялись**,
|
||||
регрессия починена вручную), `probe_nsk.py` (живой разбор ID3), `check_artist_number.py`,
|
||||
`check_file_vs_csv.py`, `verify_group_a.py`, `dump_block.py`, `find_defects.py`, `probe_real.py`.
|
||||
|
||||
### ⏭ ЧТО ДЕЛАТЬ ПЕРВЫМ ДЕЛОМ В СЛЕДУЮЩЕЙ СЕССИИ
|
||||
|
||||
> ⚠️ **УСТАРЕЛО — см. «ДВАДЦАТАЯ ВОЛНА» выше.** Из 12 нарезок `5 POPSA` решён только `Перец`
|
||||
> (`Перцы`/`Валдай`, 20-я волна). Реальный остаток — **`NSK.mp3` ×2** (A/B/C в 20-й волне).
|
||||
1. Получить от Alex решение по `NSK.mp3` (A/B/C) — см. 20-ю волну.
|
||||
2. **Бэкап `Music/backup/` → применение тегов по «go» → приёмка в UI Alex** → Music-библиотека Jellyfin.
|
||||
3. Отдельно: **чистка merge-конфликта** в `personal/plans/music-tags-review/1-needs-decision.md`.
|
||||
|
||||
## 🖐 ДВАДЦАТАЯ ВОЛНА: ПЕРЕЦ, НАДГРОБИЯ, NSK (2026-09-26)
|
||||
|
||||
> Триггер: Alex — **«Закончи правку имен песен в csv. Вручную»** → **«Доделывай»** →
|
||||
> **«Откуда строки с пустым артистом? Это косяк»** → **«Что за NSK? Ты что туда вписал как
|
||||
> артист/трек? Больше нет треков без артиста?»** → **«Рэпер сява - поправь на просто "Сява"»** →
|
||||
> **«Почему ты не спросил меня что с ним делать?! Это единственный такой трек непонятный?
|
||||
> Все остальное не вызывает никаких сомнений? Перец я тебе в доку выписывал! В чем трабл??
|
||||
> Нашествие мы блядь снесли откуда он опять взялся у тебя в списке?!»**
|
||||
|
||||
### ✅ 1. `Рэпер Сява` → `Сява` (2 строки)
|
||||
|
||||
Обе в `!Pop, Club, Любэ/!Radio/v 2009-03 mIr.vEsNЫ/2 y.MATno.E/`:
|
||||
- `Нука нака.mp3` → `new_artist = Сява`
|
||||
- `Отдыхаем хорошо(Ida Corr cocktail).mp3` → artist `DJ Иван Silver & Сява`
|
||||
|
||||
> 🔴 **Ошибка при правке:** `patch mode=replace` дал **fuzzy-match** и съел первую строку —
|
||||
> стало 7906 вместо 7907. Обнаружено сверкой `diff <(sed 's/Рэпер Сява/Сява/g' bak-184122) tag-fix-plan.csv`.
|
||||
> Затем при починке случайно удалилась строка `Ленинград - Ласточка.mp3` — тоже восстановлена.
|
||||
> **Правило: после `patch` ВСЕГДА `wc -l`, и сверять с бэкапом через `sed`-подстановку.**
|
||||
|
||||
**Второй дефект той же правки:** удаляя `cur_album`/`new_album`, легко потерять **пустое поле** —
|
||||
`,"Сява",,,fix` (11 полей) vs `,"Сява",,fix` (10). Считать поля, не запятые.
|
||||
|
||||
### 🔴 2. `Перец.mp3` — решение Alex БЫЛО В ДОКЕ, ассистент его пропустил
|
||||
|
||||
Alex: **«Перец я тебе в доку выписывал! В чем трабл??»**
|
||||
|
||||
**Реальное решение (в `personal/plans/music-tags-review/2-medium-confidence.md`):**
|
||||
```
|
||||
- **Перец.mp3** → Валдай — Перцы
|
||||
```
|
||||
⇒ `new_artist = Валдай`, `new_title = Перцы`.
|
||||
|
||||
**Почему пропущено:** `Перец.mp3` существует в **трёх** папках:
|
||||
| Путь | Было | Стало |
|
||||
|---|---|---|
|
||||
| `z Старое/Перец.mp3` | ✅ `Перцы`/`Валдай` | (не трогалось, уже верно) |
|
||||
| `z Старое/disk_v2/5 POPSA/Перец.mp3` | ❌ `Перец`/пусто | ✅ `Перцы`/`Валдай` |
|
||||
| `z Старое/disk/5 POPSA/Перец.mp3` | ❌ `Перец`/пусто | ✅ `Перцы`/`Валдай` |
|
||||
|
||||
Ассистент чистил `disk*` и **не сверил с нотами ревью** — искал только по CSV.
|
||||
|
||||
> 🔴 **ПРАВИЛО (закрепить):** перед ответом по ЛЮБОМУ artist/title — **грепнуть
|
||||
> `personal/plans/music-tags-review/*.md` по имени файла**, а не полагаться на текущее
|
||||
> состояние CSV. Нота ревью — первичный источник решения Alex.
|
||||
|
||||
### 🔴 3. `НАШЕСТВИЕ 2009` — строка-НАДГРОБИЕ, а не задача
|
||||
|
||||
Alex: **«Нашествие мы блядь снесли откуда он опять взялся у тебя в списке?!»**
|
||||
|
||||
Строка 883: `no_change` + `source = dropped (file removed by user)`. **Файла нет** — Alex снёс.
|
||||
Метка стоит с 16:57 (`bak-165750`), присутствует во всех бэкапах (строка не удалена из CSV
|
||||
намеренно — чтобы не потерять `path`).
|
||||
|
||||
**Промах:** ассистент вынес её в список «строки без artist» как будто она к обработке.
|
||||
Это сбило с толку.
|
||||
|
||||
> 🔴 **ПРАВИЛО:** при любых отчётах/списках **фильтровать `source`, начинающийся с `dropped`**.
|
||||
> Такие строки — история, не работа. Отдельный вопрос Alex'у: убирать ли надгробия из CSV вообще.
|
||||
|
||||
### 🖐 4. ПОЛНЫЙ РАЗБОР строк без artist — 190 (не 188)
|
||||
|
||||
Скрипт: `~/Downloads/music-tags/list_noartist.py` (read-only).
|
||||
|
||||
| Источник | Кол-во | Вердикт |
|
||||
|---|---:|---|
|
||||
| `!Детские/Сказки/*` | **186** | у аудиосказок artist **не существует** (сборник, не песня). Решение Alex: оставить как есть, дубли разберёт сам |
|
||||
| `Голубой щенок/01 - Хоттабыч!.mp3` | 1 | часть сказки «Голубой щенок» — artist не нужен |
|
||||
| `!A Not sorted/НАШЕСТВИЕ 2009…` | 1 | **надгробие**, файла нет |
|
||||
| `…/disk_v2/5 POPSA/NSK.mp3` | 1 | ❓ нарезка, теги пустые |
|
||||
| `…/disk/5 POPSA/NSK.mp3` | 1 | ❓ та же нарезка, копия |
|
||||
|
||||
**Проверено по самому раннему бэкапу `bak-164432`:** так было ИЗНАЧАЛЬНО, это **не регрессия**.
|
||||
|
||||
### 🔬 5. `NSK.mp3` — живой разбор на NAS (артефакт для будущих сессий)
|
||||
|
||||
Alex: **«Что за NSK? Ты что туда вписал как артист/трек?»**
|
||||
|
||||
Строка: `new_title = NSK`, `new_artist = пусто`, `new_album = пусто`.
|
||||
|
||||
**Результат байтового разбора (`python3` на ХОСТЕ NAS):**
|
||||
```
|
||||
ID3 v2.3 rev0 flags=0x0 size=1014 ← заголовок есть, syncsafe = 0x000776
|
||||
кадров: 0 (тело — полностью нули) ← теги ПУСТЫЕ
|
||||
audio starts at 1024, first sync 0xFFFB9240 → 128 kbps, 44100 Hz
|
||||
file size 475954 Б ≈ 29 секунд ← валидный MP3, короткая нарезка
|
||||
```
|
||||
|
||||
**Вывод:** 29-секундная нарезка из чарт-сборника с пустыми тегами. `NSK` в title — **имя файла**
|
||||
(вероятно «Новосибирск» или имя сборника-источника), **НЕ название песни**. Раньше в artist
|
||||
лежал мусор `disk_v2`/`5 POPSA` — вычищен, artist оставлен **пустым** (не выдуман).
|
||||
|
||||
**Открытый вопрос Alex'у (A/B/C):**
|
||||
- **A)** вписать artist/title вручную по звуку (нужен ID)
|
||||
- **B)** оставить `(без исполнителя)`, title = `NSK`
|
||||
- **C)** пометить `no_change` — файл не трогать
|
||||
|
||||
**Питфоллы окружения (проверено в этой волне):**
|
||||
- `ffprobe` на хосте/в контейнере **молча отдаёт пусто** при пустом ID3 — не доказательство.
|
||||
- `mutagen` на хосте NAS **НЕ установлен** (`ModuleNotFoundError`).
|
||||
- `xxd` на хосте NAS **НЕТ** (`command not found`).
|
||||
- 🔴 **Вложенные кавычки в `ssh 'python3 -c "..."'` ломаются** (zsh/bash на NAS съедает их,
|
||||
скрипт получает пустоту). **Рабочий путь: написать скрипт локально → `scp` в `/tmp/` →
|
||||
`ssh … 'python3 /tmp/script.py'`.** Совпадает с каноном `family/how-to/truenas-access.md`.
|
||||
- Питфолл `sed`: `\r\n`-split в Python даёт сдвиг номеров строк после правок — брать строки
|
||||
по **тексту**, не по номеру (`grep -n`, потом `sed -n` для просмотра).
|
||||
|
||||
### 📊 6. Сводные CSV пересобраны после правок
|
||||
|
||||
`python3 ~/Downloads/music-tags/build_summaries.py` (read-only исходника, пишет 2 файла):
|
||||
|
||||
| Файл | Строк | Колонки |
|
||||
|---|---:|---|
|
||||
| `artists-single-track.csv` | **777** | `artist, title, album, path` |
|
||||
| `artists-multi-track.csv` | **7129** | `artist, album, track, title, path` |
|
||||
|
||||
**777 + 7129 = 7906 — покрыты ВСЕ строки** (проверка `TOTAL COVERED` встроена в скрипт).
|
||||
Пустой artist → sentinel **`(без исполнителя)`**; для сказок ключ `(без исполнителя) — <album>`.
|
||||
|
||||
### 📊 СОСТОЯНИЕ НА КОНЕЦ ДВАДЦАТОЙ ВОЛНЫ
|
||||
|
||||
| Показатель | Значение |
|
||||
|---|---:|
|
||||
| Строк в CSV | 7906 данных + заголовок = **7907** |
|
||||
| **Битых строк** | **0** |
|
||||
| CRLF-потерь | **0** |
|
||||
| Ручных правок | **~641** |
|
||||
| Строк без artist | **190** (186 сказки + 4 прочие) |
|
||||
| Сводные CSV | ✅ 777 + 7129 = 7906 |
|
||||
| Применение на NAS | **НЕ начато (ждём «go»)** |
|
||||
|
||||
**Бэкапы:** `bak-20260926-185339` (последний, 20-я волна), `bak-20260926-184122`,
|
||||
`bak-20260926-164432` (самый ранний).
|
||||
|
||||
**Рабочие скрипты `~/Downloads/music-tags/`:**
|
||||
`diag_fields.py` (гистограмма полей), `build_summaries.py` (2 сводные CSV),
|
||||
`list_noartist.py` (**новый, 20-я волна** — полный список строк без artist по папкам),
|
||||
`probe_nsk.py` (живой разбор ID3 — переиспользован для дампа кадров),
|
||||
`repair_broken.py` / `repair_min.py` (черновики, **не применялись** — регрессия починена вручную).
|
||||
|
||||
### ⏭ ЧТО ДЕЛАТЬ ПЕРВЫМ ДЕЛОМ В СЛЕДУЮЩЕЙ СЕССИИ
|
||||
|
||||
1. **Получить от Alex решение по `NSK.mp3`** (A/B/C выше) — 2 строки.
|
||||
2. Спросить, убирать ли **строку-надгробие** `НАШЕСТВИЕ 2009` из CSV.
|
||||
3. **Бэкап `Music/backup/` → применение тегов по «go» → приёмка в UI Alex** → Music-библиотека Jellyfin.
|
||||
4. Отдельно: **чистка merge-конфликта** в `personal/plans/music-tags-review/1-needs-decision.md`.
|
||||
|
||||
## 🖐 СЕМНАДЦАТАЯ ВОЛНА: ЧИСТКА `no_change` — САЙТЫ, ИЕРОГЛИФЫ, ВОДА (2026-09-26)
|
||||
|
||||
> Триггер: Alex — **«Продолжай до конца»**, затем **«Можешь точечно использовать батч правки
|
||||
|
||||
Reference in new issue
Block a user