[2026-09-27] eagle: family/plans/music-jellyfin-lidarr-taiga.md personal/plans/music-artist-albumartist-repair.md personal/plans/tagwriter-container.md personal/tech/music-tags-repair-truenas.md
This commit is contained in:
1 parent
28b6fbd5e2
commit
412fca65ae
4 files changed
+231
-9
No files matched your search
@@ -1,4 +1,85 @@
|
||||
# Music → Jellyfin + Lidarr на Тайге — план (v9, 2026-09-27)
|
||||
# Music → Jellyfin + Lidarr на Тайге — план (v10, 2026-09-27)
|
||||
|
||||
> ## 🆕 v10: СКРИПТ-ПИСАТЕЛЬ ГОТОВ, БЭКАП ПРОВЕРЕН, ЖДЁТ «GO»
|
||||
>
|
||||
> ✅ **Вся подготовка закрыта. Файлы музыки НЕ тронуты массово — ждёт «go» от Alex.**
|
||||
>
|
||||
> | Этап | Артефакт | Итог |
|
||||
> |---|---|---|
|
||||
> | Сбор тегов | `raw_tags_full.tsv` | 7861 строка, md5 `0c3647fadb6556b4100c555ed59bfb44` |
|
||||
> | Инвентарь | `tag-inventory3.csv` | 7861 строка, 13 колонок (+`albumartist`) |
|
||||
> | План artist/albumartist/album | `fix-plan-FINAL.csv` | 7861 строка, **0 пустых** |
|
||||
> | План жанров | `genre-plan-FINAL.csv` | 7861 строка, **65 уникальных, 0 пустых** |
|
||||
> | Мусор в тегах | — | 10 классов вычищено (спам-URL 51, мойибаке 21, заглушки 325…) |
|
||||
> | ⭐ **ЕДИНЫЙ ПЛАН** | **`APPLY-PLAN-FINAL.csv`** | **7861 строка, 7628 изменений (97%), все 5 полей заполнены** |
|
||||
> | **Бэкап** | `Music/backup/` | ✅ **7861 MP3, сверка по относительным путям 1:1** |
|
||||
> | **Скрипт-писатель** | `apply_tags_v2.py` | ✅ **написан, 4 дефекта v1 закрыты, тест 5 файлов пройден** |
|
||||
>
|
||||
> ### ✅ `album` ДОЗАПОЛНЕН ПО ПАПКЕ — 452 → 0 пустых
|
||||
>
|
||||
> Alex спросил «Как у тебя спам оказался в albumartist?» → вопрос вскрыл **двух вещей**:
|
||||
> 1. **Спам был в `cur_albumartist`, НЕ в `new_albumartist`** — правило «сборник → Various Artists»
|
||||
> перезаписывает target целиком, старый спам уходит сам. Проверка: `новых со спамом: 0`.
|
||||
> 2. **Реальная недоделка — 452 файла с пустым `album`** (206 АЛЬБОМ, 165 ДЕТСКИЕ-СБОРНИК,
|
||||
> 74 АЛЬБОМ-мульти, 5 СКАЗКИ). Решение `fill_album.py`: **`album` = имя папки**
|
||||
> (для `misc`/`disk` — родитель; для буквенных папок детских сборников — буква).
|
||||
>
|
||||
> ### ✅ БЭКАП ПРОВЕРЕН ФАКТОМ (Alex: «Бэкап же уже снят?»)
|
||||
>
|
||||
> ```
|
||||
> backup: 7861 mp3 из 8478 файлов 50 ГБ ← 1:1 С ОСНОВНОЙ БИБЛИОТЕКОЙ
|
||||
> backup_conv40: 40 mp3 251 МБ
|
||||
> backup_fix: 165 mp3 1.4 ГБ
|
||||
> backup_raw: 0 mp3 (71 файл wma/ogg) 411 МБ
|
||||
> Сверка по относительным путям: 0 лишних в обе стороны
|
||||
> ```
|
||||
>
|
||||
> ⚠️ **Питфолл:** `/storage/Music` **не существует на хосте NAS** — только внутри контейнера
|
||||
> (`/mnt/RED_2TB/storage` → `/storage`, ro). Первая проверка дала ложный вывод «бэкапа нет».
|
||||
> **Правильно: `M=/mnt/RED_2TB/storage/Music`.**
|
||||
>
|
||||
> 🔴 **Вопрос бэкапа ЗАКРЫТ — копировать НЕ нужно.**
|
||||
>
|
||||
> ### ✅ `cur_*` НЕ СЛОМАНЫ (Alex: «То есть ты сломал cur поля?»)
|
||||
>
|
||||
> ```
|
||||
> paths не найдено в inventory: 0
|
||||
> расхождений cur_* vs inventory: 1 ← пробел в genre у одного файла
|
||||
> спам-значений в cur_*: 40 ← ВСЕ на месте (СОХРАНЁН)
|
||||
> ```
|
||||
>
|
||||
> **Причина подозрения:** в отчёте было «спам вычищен из album», без различения `cur_*`/`new_*`.
|
||||
> **Правило: в отчётах явно писать, какое поле.**
|
||||
>
|
||||
> ### ✅ СКРИПТ `apply_tags_v2.py` — ВСЕ 4 ДЕФЕКТА v1 ЗАКРЫТЫ
|
||||
>
|
||||
> Alex: «Бери скрипт которым ты уже прогонял apply и фикси его чтобы писал все нужные поля и
|
||||
> сносил старые **но не терял данных которые не надо терять**… исправляй проблему пропуска файлов,
|
||||
> а так же **вывод прогресса и финальную сводку**. **Не апплаить без команды!**»
|
||||
>
|
||||
> | # | Дефект v1 | Фикс v2 |
|
||||
> |---|---|---|
|
||||
> | D1 | `delall` ВНУТРИ `if value:` → пустое значение не удаляло тег | `delall` **всегда**, `add` — по значению |
|
||||
> | D2 | `_frames()` без `TPE2`/`TCON` | пишем `TIT2`,`TPE1`,`TPE2`,`TALB`,`TCON`,`TRCK` |
|
||||
> | D3 | индекс без фильтра `.mp3` → порча не-MP3 | `is_mp3_file()`, пропущено не-mp3 **560** |
|
||||
> | D4 | нет прогресса/сводки | шаг **250**, итог по полям, `--verify` + `apply-report.csv` |
|
||||
>
|
||||
> **«Не терять данные»:** сохраняются `APIC` (обложка), `TDRC` (год), `TLEN`, `TPUB`, `USLT` —
|
||||
> удаляются только 6 управляемых ID; `save()` — **в тот же путь** (иначе теряется MPEG-поток).
|
||||
>
|
||||
> **Тест 5 файлов:** `APPLY ok=5 err=0` · `TPE2 записан 5` · `VERIFY 5/5 MISMATCH=0` ·
|
||||
> `APIC сохранён` · `первые байты b'ID3'` · `18 718 742 байт`.
|
||||
>
|
||||
> **Образ `tagwriter:v2`** собран, CSV на NAS: `/mnt/RED_2TB/docker/tagwriter/data/apply-plan.csv`.
|
||||
> Полный разбор → [[personal/plans/tagwriter-container]] §v9.
|
||||
>
|
||||
> ### ⏭ ОСТАЛОСЬ
|
||||
>
|
||||
> 1. 🔴 **ЖДЁТ «go» ОТ ALEX** — массовый `--apply --verify` по 7861
|
||||
> 2. ⏳ Приёмка: **видно в UI** (Navidrome/Jellyfin), не read-back ассистента
|
||||
> 3. ⏳ Деплой Navidrome (план — [[family/how-to/navidrome-truenas-android]])
|
||||
> 4. ⏳ Lidarr (исходная задача, отложена)
|
||||
> 5. ⏳ После приёмки: удаление бэкапов + 29 битых/DRM
|
||||
|
||||
> ## 🆕 v9: ЕДИНЫЙ ПЛАН НА ПРИМЕНЕНИЕ ГОТОВ — `APPLY-PLAN-FINAL.csv` (7861 строка)
|
||||
>
|
||||
|
||||
@@ -4,6 +4,7 @@ created: '2026-09-27'
|
||||
updated: '2026-09-27'
|
||||
type: plan
|
||||
namespace: personal
|
||||
status: script-reviewed-tested-awaiting-go
|
||||
tags:
|
||||
- music
|
||||
- metadata
|
||||
@@ -16,7 +17,7 @@ tags:
|
||||
related:
|
||||
- '[[family/plans/music-jellyfin-lidarr-taiga]]'
|
||||
- '[[personal/tech/music-tags-repair-truenas]]'
|
||||
- '[[personal/tech/jellyfin-tags-cp1251-unreadable]]'
|
||||
- '[[personal/plans/tagwriter-container]]'
|
||||
- '[[family/how-to/navidrome-truenas-android]]'
|
||||
---
|
||||
|
||||
@@ -700,11 +701,39 @@ paths не найдено в inventory: 0
|
||||
8. ✅ **Скрипт-писатель `apply_tags_v2.py` НАПИСАН** — все 4 дефекта v1 закрыты, образ
|
||||
`tagwriter:v2` собран, **тест на 5 файлах пройден** (`ok=5 err=0`, `VERIFY 5/5 MISMATCH=0`)
|
||||
→ [[personal/plans/tagwriter-container]]
|
||||
9. 🔴 **ЖДЁТ «go» ОТ ALEX** — массовый прогон `--apply --verify` по `APPLY-PLAN-FINAL.csv` (7861)
|
||||
10. ⏳ Приёмка Alex: **видно в UI** (Navidrome/Jellyfin), не «read back» ассистента
|
||||
11. ⏳ После приёмки: откат 40 из `backup_conv40/` (если нужен), удаление 29 битых/DRM,
|
||||
9. ✅ **СКРИПТ ПОЛНОСТЬЮ ПЕРЕПРОВЕРЕН** (Alex: «Ещё раз проверь весь текст скрипта на
|
||||
адекватность») — найдено **6 дефектов, один критический**:
|
||||
- 🔴 **P1: `TRCK` СТИРАЛСЯ БЕЗВОЗВРАТНО** — `_managed_frame_ids()` содержал `TRCK`
|
||||
(на удаление), но `_frames()` его не создавал, а **колонки `track`/`new_track` в CSV
|
||||
НЕТ ВООБЩЕ** → номер трека исчез бы у всех 7861 файла, восстановить нечем.
|
||||
**Фикс:** `_managed_frame_ids()` = ровно `FIELD_MAP`.
|
||||
- P2 docstring врал (обещал `TDRC`) · P3 `TDRC` сохранялся случайно · P4 `changed=no`
|
||||
перезаписывались (233 файла) → `--force` · P5 нет защиты пути → `ValueError` при выходе
|
||||
за `MUSIC` · P6 `save()` не атомарный (известный риск, бэкап есть).
|
||||
10. ✅ **ТЕСТ «ДО/ПОСЛЕ» НА ЖИВОМ ФАЙЛЕ** — `snapshot.py` → apply → `snapshot.py` → `cmp_snap.py`
|
||||
на файле с **9 фреймами** (`Высоцкий/Рецидивист/09 Рецидивист.mp3`, `TRCK='9'`):
|
||||
**`TRCK` СОХРАНЁН · `TCOM`/`TSSE` сохранены · потеряно 0 фреймов · размер 4148743 → 4148743**
|
||||
11. 🔴 **ЖДЁТ «go» ОТ ALEX** — массовый прогон `--apply --verify` по `APPLY-PLAN-FINAL.csv` (7861).
|
||||
⚠️ **Перед боевым прогоном вернуть 8 тестовых файлов из бэкапа** (`!Классика` ×5,
|
||||
`Высоцкий` ×2, `Камбурова` ×1 — они уже с новыми тегами после тестов).
|
||||
12. ⏳ Приёмка Alex: **видно в UI** (Navidrome/Jellyfin), не «read back» ассистента
|
||||
13. ⏳ После приёмки: откат 40 из `backup_conv40/` (если нужен), удаление 29 битых/DRM,
|
||||
удаление бэкапов `backup/` + `backup_raw/` + `backup_fix/` + `backup_conv40/`
|
||||
12. ⏳ Lidarr + Navidrome (первоначальная задача Alex, ещё не начата)
|
||||
14. ⏳ Lidarr + Navidrome (первоначальная задача Alex, ещё не начата)
|
||||
|
||||
## 🔴 ПРАВИЛО (открыто в этой сессии): «управляемый» набор фреймов = набор записываемых
|
||||
|
||||
`TRCK` стоял в списке **на удаление**, но отсутствовал в списке **на запись** и в CSV.
|
||||
**Фрейм, которым скрипт «управляет», но значение которого нигде не задано, — это потеря данных
|
||||
по определению.** Валидировать инвариант ДО прогона:
|
||||
|
||||
```python
|
||||
assert sorted(_managed_frame_ids()) == sorted(fid for _, fid, _ in FIELD_MAP)
|
||||
```
|
||||
|
||||
Тот же класс уже стоил библиотеке 40 MP3 (`fix40.py`) и 16 не-MP3 (`apply_tags.py` без `.mp3`-фильтра) —
|
||||
**ловушка в списках «что трогаем» находится только построчным перечитыванием, а не тестами на живых файлах**
|
||||
(тест прошёл бы успешно: `delall(TRCK)` + отсутствие `add` не вызывают ошибки, просто тихо стирают тег).
|
||||
|
||||
### ✅ Бэкап: вопрос ЗАКРЫТ (Alex: «Бэкап же уже снят?»)
|
||||
|
||||
@@ -758,7 +787,8 @@ APIC сохранён · первые байты b'ID3' · 18 718 742 байт
|
||||
|
||||
```
|
||||
/Users/admin/milestones/music-csv-2026-09-26/
|
||||
├── APPLY-PLAN-FINAL.csv ⭐⭐ 7861 стр — ЕДИНЫЙ ПЛАН НА ПРИМЕНЕНИЕ (14 колонок)
|
||||
├── APPLY-PLAN-FINAL.csv ⭐⭐⭐ 7861 стр — ЕДИНЫЙ ПЛАН НА ПРИМЕНЕНИЕ (14 колонок)
|
||||
│ все 5 полей заполнены, валидация по нулям
|
||||
├── fix-plan-FINAL.csv ⭐ 7861 стр, план artist/albumartist/album
|
||||
├── genre-plan-FINAL.csv ⭐ 7861 стр, план жанров (65 уник., 0 пусто)
|
||||
├── APPLY-PLAN.csv промежуточный единый (до чистки мусора)
|
||||
|
||||
@@ -17,9 +17,103 @@ updated: '2026-09-26'
|
||||
---
|
||||
# tagwriter — контейнер применения тегов MP3 (TrueNAS)
|
||||
|
||||
_Создан: 2026-09-26. **Статус (обновлён 2026-09-27): ✅ `apply_tags_v2.py` НАПИСАН, ВСЕ 4 ДЕФЕКТА v1 ЗАКРЫТЫ (D1 `delall` вне `if` · D2 +`TPE2`/`TCON` · D3 фильтр `.mp3` · D4 прогресс+сводка+`--verify`), ОБРАЗ `tagwriter:v2` СОБРАН, ТЕСТ НА 5 ФАЙЛАХ ПРОЙДЕН (`ok=5 err=0`, `VERIFY совпало=5 MISMATCH=0`, APIC сохранён, MPEG-поток цел). 🔴 **ФАЙЛЫ МУЗЫКИ НЕ ТРОНУТЫ МАССОВО — ЖДЁТ «go» ОТ ALEX.** ⏳ НЕ выполнено: массовый apply по `APPLY-PLAN-FINAL.csv` (7861), откат 40 из `backup_conv40/`, удаление 29 битых/DRM, приёмка Jellyfin. Бэкапы готовы и проверены по путям: `backup/` 7861 MP3 (1:1 с основной библиотекой), `backup_conv40/` 40, `backup_fix/` 165, `backup_raw/` 71. Решение Alex по TRCK = **B** (номера не удалять).**_
|
||||
_Создан: 2026-09-26. **Статус (обновлён 2026-09-27): ✅ `apply_tags_v2.py` НАПИСАН + ПОЛНОСТЬЮ ПЕРЕПРОВЕРЕН (v10). ЗАКРЫТЫ 4 ДЕФЕКТА v1 (D1 `delall` вне `if` · D2 +`TPE2`/`TCON` · D3 фильтр `.mp3` · D4 прогресс+сводка+`--verify`) + 6 ДЕФЕКТОВ, найденных при перечитывании (P1 🔴 `TRCK` стирался безвозвратно · P2 docstring врал · P3 `TDRC` сохранялся случайно · P4 `changed=no` перезаписывались · P5 нет защиты пути · P6 `save()` не атомарный). ОБРАЗ `tagwriter:v2` СОБРАН. ТЕСТЫ: 5 файлов (`ok=5 err=0`, `MISMATCH=0`) + 3 файла (`ok=3 err=0`, `MISMATCH=0`) + ТЕСТ «ДО/ПОСЛЕ» на файле с 9 фреймами (`TRCK` СОХРАНЁН, `TCOM`/`TSSE` сохранены, размер 4148743 → 4148743 байт, потеряно 0 фреймов). 🔴 **ФАЙЛЫ МУЗЫКИ НЕ ТРОНУТЫ МАССОВО — ЖДЁТ «go» ОТ ALEX.** ⏳ НЕ выполнено: массовый apply по `APPLY-PLAN-FINAL.csv` (7861), возврат 8 тестовых файлов из бэкапа, откат 40 из `backup_conv40/`, удаление 29 битых/DRM, приёмка Jellyfin. Бэкапы готовы и проверены по путям: `backup/` 7861 MP3 (1:1 с основной библиотекой), `backup_conv40/` 40, `backup_fix/` 165, `backup_raw/` 71. Решение Alex по TRCK = **B** (номера не удалять).**_
|
||||
_Основание: [[personal/plans/music-tags-wave38-fixes]]._
|
||||
|
||||
## ✅ v10 (2026-09-27): ПОЛНОЕ ПЕРЕЧИТЫВАНИЕ СКРИПТА — 🔴 НАЙДЕН ДЕФЕКТ УНИЧТОЖЕНИЯ `TRCK`
|
||||
|
||||
**Задача Alex:** «**Ещё раз проверь весь текст скрипта на адекватность.**»
|
||||
|
||||
Перечитан весь `apply_tags_v2.py` (333 строки) построчно → найдено **6 проблем, одна критическая**.
|
||||
Все исправлены **до** боевого прогона.
|
||||
|
||||
### 🔴🔴 P1 (КРИТИЧНО): `TRCK` СТИРАЛСЯ БЕЗВОЗВРАТНО
|
||||
|
||||
**Механика ловушки:**
|
||||
|
||||
```python
|
||||
_managed_frame_ids() → ["TIT2","TPE1","TPE2","TALB","TCON","TRCK"] # TRCK стоит на удаление
|
||||
_frames(r) → TIT2, TPE1, TPE2, TALB, TCON — TRCK НЕ создаётся
|
||||
CSV APPLY-PLAN-FINAL → колонки track / new_track ОТСУТСТВУЮТ ВООБЩЕ
|
||||
```
|
||||
|
||||
**`delall("TRCK")` выполнялся бы, `add(TRCK)` — никогда.** Номер трека исчез бы у **всех 7861 файла**,
|
||||
и восстановить его было бы **нечем** — данных о треке нет ни в CSV, ни где-либо ещё.
|
||||
|
||||
**Фикс:**
|
||||
|
||||
```python
|
||||
def _managed_frame_ids():
|
||||
"""🔴 НЕ добавлять сюда фрейм, которого нет в _frames()/CSV —
|
||||
он будет стёрт без возможности восстановления (так было с TRCK)."""
|
||||
return [fid for _, fid, _ in FIELD_MAP] # TIT2 TPE1 TPE2 TALB TCON
|
||||
```
|
||||
|
||||
**🔴 ПРАВИЛО: набор «управляемых» фреймов = РОВНО набор записываемых. Управляемый, но не
|
||||
записываемый фрейм = гарантированная потеря данных.** Проверка инварианта:
|
||||
`sorted(_managed_frame_ids()) == sorted(fid for _,fid,_ in FIELD_MAP)` → `True`.
|
||||
|
||||
### Остальные 5 исправлений
|
||||
|
||||
| # | Проблема | Было | Стало |
|
||||
|---|---|---|---|
|
||||
| **P2** | docstring врал | «пишем TDRC», реально TDRC не писался | честный список: `ЧТО ПИШЕТ` / `ЧТО НЕ ТРОГАЕТ` |
|
||||
| **P3** | `TDRC` (год) сохранялся **случайно** | не был в списке удаления — везение, не замысел | задокументировано как «не трогаем» + в `ЧТО НЕ ТРОГАЕТ` |
|
||||
| **P4** | `changed=no` обрабатывались | 233 файла зря перезаписывались (`delall`+`add` на неизменном) | `build_jobs(force=...)` пропускает их, флаг `--force` для перезаписи |
|
||||
| **P5** | нет защиты пути | `/storage/Music/../../etc` прошёл бы | `map_path()` → `os.path.normpath` + `ValueError` при выходе за `MUSIC` |
|
||||
| **P6** | `save()` не атомарный | обрыв (kill/диск полный) → битый файл | оставлено (бэкап есть), но зафиксировано как известный риск |
|
||||
|
||||
### ✅ ТЕСТ «ДО/ПОСЛЕ» НА ЖИВОМ ФАЙЛЕ — `TRCK` ВЫЖИЛ
|
||||
|
||||
**Метод:** `snapshot.py` (снимок фреймов + значений в JSON) → `--apply` → `snapshot.py` снова →
|
||||
`cmp_snap.py` (побайтовое сравнение списка фреймов и значений).
|
||||
|
||||
**Тестовый файл с 9 фреймами** (выбран `find_trck.py` — искал `.mp3` с непустым `TRCK`):
|
||||
|
||||
```
|
||||
!Барды/Владимир Высоцкий/Рецидивист/09 Рецидивист.mp3
|
||||
фреймы: TALB, TCOM, TCON, TIT2, TPE1, TPE2, TRCK, TSSE, TXXX ← 9 штук
|
||||
TRCK = '9'
|
||||
```
|
||||
|
||||
**Результат сравнения:**
|
||||
|
||||
```
|
||||
поле ДО ПОСЛЕ ВЕРДИКТ
|
||||
TCON Поп Pop ИЗМЕНЕН (план) ✓
|
||||
TRCK 9 9 СОХРАНЁН ✓
|
||||
TCOM Владимир Высоцкий Владимир Высоцкий СОХРАНЁН ✓
|
||||
TSSE Lavf60.16.100 Lavf60.16.100 СОХРАНЁН ✓
|
||||
|
||||
фреймы: потеряно ничего, появилось ничего
|
||||
размер: 4148743 → 4148743 (разница 0)
|
||||
ИТОГ: ✓ ВСЁ СОХРАНЕНО
|
||||
```
|
||||
|
||||
### Тест из 3 файлов (разные случаи)
|
||||
|
||||
```
|
||||
APPLY: 3 файла — ok=3 err=0
|
||||
TPE2 (albumartist): 1 · TALB (album): 1 · TCON (genre): 3
|
||||
VERIFY: совпало 3/3, MISMATCH 0
|
||||
```
|
||||
|
||||
### 📄 Инструменты верификации (в `/mnt/RED_2TB/docker/tagwriter/data/`)
|
||||
|
||||
| Скрипт | Назначение |
|
||||
|---|---|
|
||||
| `snapshot.py` | снимок фреймов файла в JSON (список ID + значения 9 ключевых) |
|
||||
| `cmp_snap.py` | сравнение двух снимков: что сохранено, что изменено, что потеряно |
|
||||
| `find_trck.py` | поиск mp3 с непустым `TRCK` (для выбора тестового файла) |
|
||||
| `make_test_csv.py` | мини-CSV из указанных путей — для точечного теста |
|
||||
| `check_one.py` | быстрый отчёт по одному файлу (фреймы, значения, байты) |
|
||||
|
||||
### 🔴 ПИТФОЛЛ: `--entrypoint python3` требует, чтобы скрипт БЫЛ в смонтированном каталоге
|
||||
|
||||
Первый запуск `snapshot.py` → `can't open file '/app/data/snapshot.py': No such file or directory`,
|
||||
хотя `scp` вроде прошёл. **Проверять `ls -la` монтируемого файла ПОСЛЕ `scp`, до `docker run`.**
|
||||
`/app` — образ, `/app/data` — монтирование; `scp` в `data/` нужен **и** `-v .../data:/app/data`.
|
||||
|
||||
## ✅ v9 (2026-09-27): `apply_tags_v2.py` — НОВЫЙ СКРИПТ-ПИСАТЕЛЬ, ВСЕ 4 ДЕФЕКТА ЗАКРЫТЫ
|
||||
|
||||
**Задача Alex:** «Бери скрипт которым ты уже прогонял apply и фикси его чтобы писал все нужные
|
||||
|
||||
@@ -39,8 +39,25 @@ related:
|
||||
> - **сборник ≠ «>1 артиста»** — это ловит альбомы с фитами; Alex дал прямые примеры
|
||||
> - процессный запрет Alex: **сначала ручные списки, скриптом — только обновление CSV**
|
||||
> - ✅ `fix-plan-FINAL.csv` — 7861 стр, **0 пустых `artist`**, 7233 изменения
|
||||
> - ✅ `genre-plan-FINAL.csv` — 7861 стр, **82 уникальных жанра** (было 154), 51 пустой,
|
||||
> - ✅ `genre-plan-FINAL.csv` — 7861 стр, **65 уникальных жанра** (было 154), **0 пустых**,
|
||||
> мойибаке `Psy Årance` → `Psy-Trance` (29 файлов, `Å`/`Е` — латиница vs кириллица)
|
||||
>
|
||||
> ### ✅ ОБНОВЛЕНИЕ 2026-09-27 (вечер) — ПЛАН ЗАКРЫТ, СКРИПТ ГОТОВ, ЖДЁТ «GO»
|
||||
>
|
||||
> | Шаг | Факт |
|
||||
> |---|---|
|
||||
> | `APPLY-PLAN-FINAL.csv` | ✅ 7861 стр, 7628 изменений, **все 5 полей заполнены** (title/artist/albumartist/album/genre) |
|
||||
> | `album` дозаполнен по папке | ✅ 452 → **0 пустых** |
|
||||
> | Валидация | ✅ дубли 0 · спам 0 · мойибаке 0 · пустых 0 · class↔albumartist 0 |
|
||||
> | Бэкап | ✅ `backup/` **7861 MP3**, сверка по относительным путям **1:1** (0 расхождений) |
|
||||
> | `cur_*` | ✅ **не сломаны** — 1 расхождение = пробел в `genre` |
|
||||
> | Скрипт `apply_tags_v2.py` | ✅ написан, 4 дефекта v1 закрыты; **⚠️ ПОСЛЕ ПОЛНОЙ ПЕРЕПРОВЕРКИ исправлено ещё 6 дефектов** (🔴 `TRCK` стирался безвозвратно · `changed=no` перезаписывались · нет защиты пути · docstring врал); тесты 5+3 файла `MISMATCH=0` + «ДО/ПОСЛЕ» на 9-фреймовом файле (`TRCK` сохранён, потеряно 0 фреймов) |
|
||||
> | 🔴 Дальше | **ЖДЁТ «go» ОТ ALEX** — массовый `--apply --verify` по 7861. ⚠️ Перед прогоном вернуть 8 тестовых файлов из бэкапа |
|
||||
>
|
||||
> Питфоллы сессии: `cur_*` ≠ `new_*` в отчётах · `/storage/Music` не существует на хосте (только
|
||||
> `/mnt/RED_2TB/storage/Music`, в контейнере `/storage` ro) · инлайн-python через ssh ломается на
|
||||
> кавычках · tirith блокирует кириллицу вплотную к ASCII.
|
||||
> Детали → [[personal/plans/music-artist-albumartist-repair]] и [[personal/plans/tagwriter-container]].
|
||||
|
||||
> ## ✅ ТРИДЦАТЬ ВОСЬМАЯ ВОЛНА (2026-09-26) — ФИНАЛЬНЫЙ АУДИТ + 4 ПРАВКИ + ПРИМЕНЕНИЕ НА NAS
|
||||
>
|
||||
|
||||
Reference in new issue
Block a user