[2026-09-26] eagle: personal/plans/music-tags-review/1-needs-decision.sync-conflict-20260926-150525-XJRJQB2.md personal/plans/music-tags-review/1-needs-decision.sync-conflict-20260926-165021-C6DYBCZ.md personal/tech/music-tags-repair-truenas.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-26 16:43:32 +06:00
1 parent c001e3fec7
commit 680da87d49
3 files changed
+72 -1727

No files matched your search

@@ -1,182 +0,0 @@
---
title: Music Tags — Требует решения
type: task
namespace: personal
tags: [music, jellyfin, tags, review, truenas]
status: awaiting-approval
block: cannot
---
# Требует решения
**Файлов:** 28 · **Папок:** 13
> [!info] Исполнитель неоткуда взять однозначно — разобрано вручную.
> Ставь `- [x]` напротив согласных правок и скажи «go».
[[music-tags-review|← к обзору]]
## Оглавление
- `!A Not sorted` — 1
- `!Pop, Club, Любэ` — 1
- `!Pop, Club, Любэ/!Radio/t 2009-07 c6Or_NICK/base` — 1
- `!Pop, Club, Любэ/!Radio/t 2009-07 c6Or_NICK/рап` — 1
- `!Pop, Club, Любэ/!Radio/v 2009-03 mIr.vEsNЫ` — 5
- `!Pop, Club, Любэ/!Radio/x 2008-04` — 1
- `!Pop, Club, Любэ/!Radio/y OOF` — 8
- `!Pop, Club, Любэ/!Radio/z Старое` — 2
- `!Retro` — 5
- `!Детские` — 1
- `z Другое, Enigma, Ленинград/Саундтреки` — 2
---
## А. Исполнитель вписан вручную — очевидно (8 файлов)
## z Другое, Enigma, Ленинград/Саундтреки
- [ ] **Pirates of the Caribbean.mp3**
- `artist`: ⟨мусор-релиз⟩ → **Hans Zimmer feat. Dimitri Vegas & Like Mike**
- `title`: Hans Zimmer feat. Dimitri Vegas & Like Mike - Hes A Pirate (Bonus Track) → **He's a Pirate (Bonus Track)**
- [ ] **Interstellar.mp3**
- `artist`: Interstellar - OST Интерстеллар - Саундтрек [Score] (2014) → **Hans Zimmer**
- `title`: Hans Zimmer - No Time For Caution → **No Time for Caution**
## !Retro
- [ ] **Кольщик.mp3**
- `title`: ⟨повреждено⟩ → **Кольщик**
- `artist`: ⟨повреждено⟩ → **Михаил Круг**
- [ ] **Пропаганда-Супер детка.mp3**
- `artist`: ⟨повреждено⟩ → **Пропаганда**
- `title`: ⟨повреждено⟩ → **Супер детка**
## !Pop, Club, Любэ
- [ ] **detskiy_hor_benassi_satisfaction.mp3**
- `title`: ⟨повреждено⟩ → **Satisfaction**
- `artist`: ⟨повреждено⟩ → **Детский хор + Benny Benassi**
- `album`: ⟨повреждено⟩ → **—**
## !Pop, Club, Любэ/!Radio/t 2009-07 c6Or_NICK/base
- [ ] **01 Hit The Road Jack (Kub vs Ray Charles).mp3**
- `artist`: — → **Kub vs Ray Charles**
- `title`: — → **Hit the Road Jack**
- `track`: — → **1**
## !Pop, Club, Любэ/!Radio/v 2009-03 mIr.vEsNЫ/1 novo.E
- [ ] **06 Benassi I am a Dj.mp3**
- `artist`: — → **Benassi**
- `title`: — → **I Am a DJ**
- `track`: — → **6**
## !Pop, Club, Любэ/!Radio/y OOF
- [ ] **Mymij_troll_kontrabanda.mp3**
- `artist`: — → **Мумий Тролль**
- `title`: — → **Контрабанда**
- [ ] **lil jon.mp3**
- `artist`: — → **Lil Jon**
- `title`: — → *(имя папки/файла не содержит названия — оставить пусто)*
---
## Б. Исполнителя взять неоткуда — только title (20 файлов)
Ставь `- [x]`, если согласен с title. Artist остаётся пустым (Jellyfin → Unknown Artist).
## !A Not sorted
- [ ] **НАШЕСТВИЕ 2009 - ДЕНЬ ВТОРОЙ.mp3**
- `title`: — → **НАШЕСТВИЕ 2009 — День второй**
- _примечание: это фестиваль, не артист_
## !Pop, Club, Любэ/!Radio/t 2009-07 c6Or_NICK/рап
- [ ] **Нарк.mp3**
- `title`: — → **Нарк**
## !Pop, Club, Любэ/!Radio/v 2009-03 mIr.vEsNЫ/2 y.MATno.E
- [ ] **БОДРЯЧКОМ.mp3**
- `title`: — → **Бодрячком**
- [ ] **Бык, не быкуй!.mp3**
- `title`: — → **Бык, не быкуй!**
- [ ] **волна по ебалу на.mp3**
- `title`: — → **Волна по ебалу**
## !Pop, Club, Любэ/!Radio/v 2009-03 mIr.vEsNЫ/3 clubNИчкоvo.E
- [ ] **Kazantip 2008 - Beat (zvukoff.ru).mp3**
- `artist`: Kazantip 2008 → **—**
- `title`: — → **Beat**
- _примечание: Kazantip — событие, не артист_
## !Pop, Club, Любэ/!Radio/x 2008-04
- [ ] **Sensation White (2008) - Matisse (Remix).mp3**
- `artist`: — → **Matisse**
- `title`: — → **Sensation White (Remix)**
## !Pop, Club, Любэ/!Radio/y OOF
- [ ] **029_Mast.mp3**
- `title`: — → **Mast**
- `track`: — → **29**
- [ ] **Dj Riga ceh-126 Track.mp3**
- `artist`: — → **DJ Riga**
- `title`: — → **ceh-126 Track**
- [ ] **I M P R E Z A.mp3**
- `title`: — → **Impressa**
- [ ] **dj toll.mp3**
- `title`: — → **DJ Toll**
- [ ] **i am instructor.mp3**
- `title`: — → **I Am Instructor**
- [ ] **клубняк3.mp3**
- `title`: — → **Клубняк 3**
## !Pop, Club, Любэ/!Radio/z Старое
- [ ] **Вертолет башку сорвет!(dj karas extra club).mp3**
- `artist`: — → **DJ Karas**
- `title`: — → **Вертолёт башку сорвёт (Extra Club Mix)**
- [ ] **Перец.mp3**
- `title`: — → **Перец**
## !Retro
- [ ] **Казанова.mp3**
- `title`: ⟨повреждено⟩ → **Казанова**
- `artist`: ⟨повреждено⟩ → **—**
- [ ] **Младший лейтенант.mp3**
- `title`: ⟨повреждено⟩ → **Младший лейтенант**
- `artist`: ⟨повреждено⟩ → **—**
- _вероятно Сектор Газа / Воровайки — не угадываю_
- [ ] **Остаёмся зимовать.MP3**
- `title`: ⟨повреждено⟩ → **Остаёмся зимовать**
- `artist`: ⟨повреждено⟩ → **—**
- `album`: ⟨повреждено⟩ → **—**
## !Детские
- [ ] **Из чего же.mp3**
- `title`: Èç ÷åãî æå, èç ÷åãî æå, èç ÷åãî æå → **Из чего же, из чего же, из чего же**
- `artist`: Íåèçâåñòíûé èñïîëíèòåëü → **—**
- `album`: Íåèçâåñòíîå íàçâàíèå → **—**
---
## Итог
| Категория | Файлов |
|---|---:|
| Artist вписан вручную (А) | **10** |
| Только title, artist пусто (Б) | **18** |
| **Всего** | **28** |
**Осталось 8 файлов без artist** (`Казанова`, `Младший лейтенант`, `Остаёмся зимовать`, `БОДРЯЧКОМ` и др.) — источника нет, не угадываю.
[[music-tags-review|← к обзору]]
+72 -15
View File
@@ -26,7 +26,7 @@ related:
> третья волна по замечаниям Alex → 3 бага (en-dash + подстроковый поиск стоп-слов),
> **четвёртая волна (ручной проход) → 10 багов (track-номера, disc-track, восклицательные знаки, регистр)**,
> **пятая волна (ручной разбор блока 1 глазами) → 28 файлов, 10 артистов вписано вручную**,
> **шестая волна (Alex правит мои md + ACL-фикс синка) → найдены баг `ÿþ`-BOM и конфликтные файлы**.
> **шестая волна (Alex правит мои md + ACL-фикс синка) → найден и ПОЧИНЕН баг `ÿþ`-BOM в парсере ID3**.
> Итог v5: 6773 `fix`, mojibake = 0, 121 тест PASS, блок «требует решения» 296 → 28.
## 🔴 ШЕСТАЯ ВОЛНА: ALEX ПРАВИТ МОИ НОТЫ + ACL-ФИКС СИНКА (2026-09-26)
@@ -59,26 +59,83 @@ Alex: **«Needs decision — забирай из syncthing. Medium confidence
> Alex поправил `title` на `Цех-126 Track` (кириллица). Вывод: в папках `!Radio/*`
> artist почти всегда = первые 1–3 слова имени, остальное = название. Проверять это первым.
### 🔴 БАГ: `ÿþ` (UTF-16 BOM) «починен» в мусор — 4 строки в `2-medium-confidence.md`
### ✅ БАГ `ÿþ` (UTF-16 BOM) — НАЙДЕНА ПЕРВОПРИЧИНА, ПАРСЕР ПОЧИНЕН
Alex: **«Какого хуя ты мне подсовываешь мусор со сбитой кодировкой?! Там cp1251 а не мусор!!»** —
замечание по сути верное, но диагноз оказался глубже: там **не CP1251 и не mojibake**,
а **битый ID3-тег: BOM при `enc_byte=0`**.
#### Что реально в байтах (дамп файла, `dump_id3.py`)
```
06 Steel Deluxe - Сердце открой.mp3
title: ÿþ!@54F5 B:@>9 → яю!@54F5 B:@>9 ← МУСОР вместо названия
10 Boom (Bimbo Jones Mix).mp3
title: ÿþY → яюY
artist: ÿþd → яюd
album: ÿþY → яюY
header: ID3 ver=3.0
frame TIT2 enc_byte=0 payload = 00 FF FE 21 40 35 34 46 35 20 42 3A 40 3E 39
frame TPE1 enc_byte=0 payload = 00 FF FE 53 74 65 65 6C 20 44 65 6C 75 78 65
frame TALB enc_byte=0 payload = 00 "Record Super Chart ¹ 90 (30.05.2009)"
```
**Причина:** байты `FF FE` в начале строки — это **UTF-16 BOM**, а не CP1251→Latin-1 mojibake.
`fix_encoding` конвертировал их как mojibake → `ÿþ` → `яю`. Результат **хуже исходного**.
**Суть:** заголовок кадра объявляет `enc=0` (latin-1), а **содержимое начинается с `FF FE`** —
UTF-16 BOM. Так писали древние теггеры: BOM поставили, байт кодировки оставили нулевым,
а текст после BOM — **обычные 8-битные символы**, не UTF-16.
> 🔴 **ПИТФОЛЛ: `ÿþ` (0xFF 0xFE) в начале тега — это BOM, не mojibake.**
> Не конвертировать. Настоящее значение — в имени файла (`Сердце открой`), artist — из имени.
> **Ложное срабатывание grep:** строки `Òåðÿþ ñâåò → Теряю свет` в `3-high-confidence.md`
> содержат `ÿþ` **внутри слова «Теряю»** — это корректная конвертация, НЕ баг. Различать по позиции.
Отсюда `ÿþSteel Deluxe` (= `FF FE` + ASCII «Steel Deluxe») — а не сломанная кириллица.
**Реальных багов — 4 строки (1 файл), не 2096.** Проверять адресно, а не по всему файлу.
> 🔴 **ПИТФОЛЛ: `ÿþ` (0xFF 0xFE) в начале тега — это BOM-префикс, а НЕ UTF-16-текст и НЕ mojibake.**
> Текст за ним читать как **8-битный**, сам BOM — отбросить.
> **Ловушка:** наивное `payload.decode("utf-16")` склеивает ASCII-пары →
> `Steel Deluxe` → `瑓敥\u206c敄畬數`. Проверено на живом файле: первая версия фикса дала именно это.
#### Фикс — `id3_direct.py`, функция `decode_text()`
```python
raw = data[1:]
# Broken tagger: encoding byte says latin-1 (0), payload starts with a
# UTF-16 BOM. In practice the BOM is a bogus prefix and the remaining
# bytes are 8-bit text -- decode them, don't let the BOM win.
if enc == 0 and raw[:2] in (b"\xff\xfe", b"\xfe\xff"):
raw = raw[2:]
text = raw.decode(codec, errors="replace")
return text.strip("\x00").strip().lstrip("\uffff\ufffe").strip("\ufeff")
```
**Проверено на `06 Steel Deluxe - Сердце открой.mp3`:**
```
artist: 'Steel Deluxe' ← было 'ÿþSteel Deluxe' / '瑓敥…' → ВОССТАНОВЛЕН ✅
title : '!@54F5 B:@>9' ← мусор в самом теге → брать из имени файла
```
#### Два класса дефекта (различать!)
| Класс | Пример | Как чинить |
|---|---|---|
| **BOM + валидный 8-бит текст** | TPE1 = `FF FE` + `Steel Deluxe` | отбросить BOM → **artist готов** ✅ |
| **BOM + мусор в теге** | TIT2 = `FF FE` + `21 40 35 34 46 35` | взять из **имени файла** |
#### Масштаб — 4 файла, НЕ 2096 (`scan_bom.py` по всем 7906 строкам CSV)
```
❌ 10 Boom (Bimbo Jones Mix) title='ÿþY' artist='ÿþd' → title из имени
❌ 06 Steel Deluxe - Сердце открой title='ÿþ!@54F5 B:@>9' → title из имени (artist OK)
❌ 12 Whizzkids Feat. Inusa Dawuda title="'ÿþRumours…" artist=';ÿþWhizzkids…' → оба из имени
❌ 31 Inna - Love (Play & Win Club Mix) title='7ÿþoLve…' artist='ÿþInna' → оба из имени
```
> ⚠️ **Ложное срабатывание grep — 5 строк в `3-high-confidence.md`:**
> `Òåðÿþ ñâåò → Теряю свет`, `Ïîçäðàâëÿþ → Поздравляю` — здесь `ÿþ` **внутри слова** («Теряю»),
> это корректная CP1251-конвертация. Различать по позиции: начало значения ≠ середина слова.
У всех 4 файлов artist/title выводятся из имени — правки возможны **без участия Alex**.
**Скрипты, появившиеся в этой волне:**
| Файл | Что делает |
|---|---|
| `dump_id3.py` | Дамп сырых байтов ID3-кадров (`enc_byte`, hex, repr, попытки декодирования). Незаменим при разборе кодировок |
| `scan_bom.py` | Поиск `ÿþ` по всем полям CSV-плана — отделяет реальный BOM от середины слова |
> 📌 **Правило диагностики кодировок: сначала дамп байтов, потом гипотеза.** Я дважды ошибся,
> угадывая («это CP1251» → «это UTF-16»), пока не посмотрел `payload.hex()`.
> `dump_id3.py --file <mp3>` показывает `enc_byte` и сырые байты за один прогон.
### 📂 Конфликтные файлы Syncthing — зачем и что с ними