[2026-09-28] eagle: personal/plans/tagwriter-container.md personal/tech/music-tags-repair-truenas.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-28 00:47:21 +06:00
1 parent 85d2856bc0
commit 20d6726a75
2 files changed
+199 -5

No files matched your search

+82 -1
View File
@@ -4,7 +4,7 @@ created: '2026-09-26'
updated: '2026-09-27'
type: plan
namespace: personal
status: session22-apply-306-done-navidrome-db-rebuilt-0-orphans
status: session23-apply-v6-282-done-db-rebuilt-7808
tags:
- music
- truenas
@@ -21,6 +21,87 @@ related:
---
# tagwriter — применение тегов к MP3 (TrueNAS)
## 🔴🔴 КАНОН ЗАПУСКА (сессия 23) — ЧИТАТЬ ДО ЛЮБОГО ПРОГОНА
> ### ✅ РАБОЧАЯ КОМАНДА (дока была неверна в пути к скрипту — исправлено)
>
> ```bash
> docker create --name twX --entrypoint python3 \
> -v /tmp/tw306:/app/data:ro \
> -v /mnt/RED_2TB/storage/Music:/music:ro \
> tagwriter:latest /app/apply_tags_v2.py --dry-run # ← /app/, НЕ /app/data/
> docker start -a twX
> ```
>
> 🔴 **`/app/data/apply_tags_v2.py` — НЕВЕРНО** (так было в этой доке). Скрипт лежит
> **в образе**: `/app/apply_tags_v2.py` (25971 B). `/app/data` — монтируемая папка с планом.
> Симптом ошибки: `can't open file '/app/data/apply_tags_v2.py': No such file or directory`.
> 🔴 **`--plan` НЕ СУЩЕСТВУЕТ.** `CSV_IN = "/app/data/apply-plan.csv"` — константа в коде.
> Аргументы: `--dry-run --apply --readback --verify --force --limit N`.
> 🔴 **`cd /mnt/RED_2TB/docker/navidrome && docker compose stop` для сноса БД.**
>
> ### 🔴 ПУТЬ В ПЛАНЕ ОБЯЗАН НАЧИНАТЬСЯ С `/storage/Music/`
>
> Любой новый сборщик плана пишет **абсолютный** путь. `map_path()` в образе снимает префикс
> `/storage/Music/`; без него путь считается «вне /music» → **MISSING + `к обработке: 0`**.
> ```python
> plan_rows.append({"path": "/storage/Music/" + rel, ...}) # ← обязательный префикс
> ```
> Симптом: dry-run даёт `ИТОГО к правке: 0` и список `MISSING: … (путь вне /music: …)`.
>
> ### 🔴 БОЕВОЙ ПРОГОН — ТОЛЬКО ПО ПРЯМОМУ «go» ALEX
>
> Alex дословно: «**без подтверждения никакого apply блядь**». Дифф и dry-run — можно,
> запись на диск — только после явного «go»/«Давай».
## ✅ СЕССИЯ 23 (2026-09-27) — ВОЛНА v6: 282/282 ПРИМЕНЕНО, БД ПЕРЕСОЗДАНА (7808)
> **План:** `apply-plan-v6.csv` (7861 стр на момент прогона).
> **Артефакт:** 282 файла (`changed=no` пропущено 7579 · не-mp3 562).
> ```
> === APPLY: 282 файлов === ok=282 err=0
> TPE1 artist 155 · TPE2 albumartist 158 · TALB album 183 · TRCK track 58 · TIT2 0 · TCON 0
> === VERIFY: совпало 282, MISMATCH 0 ===
> ```
> **Приёмка независимым скриптом с диска** (`verify_applied_v6.py`, mutagen):
> 282/282 совпало, расхождений 0.
>
> 🔴 **ДЕФЕКТ, НАЙДЕННЫЙ ПРИЁМКОЙ:** `Т9 - Вдох-Выдох` получил `TPE1='Т9'`, но
> `TPE2` остался `'Вдох-Выдох'` (старое значение artist). Фикс → повторный прогон, `TPE2` 157→158.
> 🔑 **Правя `artist`, ВСЕГДА проверять `albumartist` того же файла.** Детектор: `check_aa_stale.py`.
>
> ### 🔴 СНОС И ПЕРЕСБОР БД NAVIDROME (два раза за сессию)
>
> ```bash
> D=/mnt/RED_2TB/docker/navidrome/data
> mkdir -p "$D/navidrome.db.bak-$(date +%Y%m%d-%H%M%S)"; cp "$D"/navidrome.db* "$D/navidrome.db.bak-$TS"/
> cd /mnt/RED_2TB/docker/navidrome && docker compose stop
> rm -v "$D"/navidrome.db "$D"/navidrome.db-shm "$D"/navidrome.db-wal
> docker compose up -d # fullScan=true, скан ~4-5 мин
> ```
> ⚠️ `-shm`/`-wal` при остановленном контейнере уже отсутствуют — `rm` по ним даёт
> `No such file`, это норма, не ошибка.
> 🔴 **Снос БД — необратимая операция, согласовывать ОТДЕЛЬНО КАЖДЫЙ РАЗ.** Alex на второй
> снос без спроса: «**ты нахуя базу снес?**».
> **Итог:** `media_file` 7811 → **7808** · `album` 718 → **717**.
>
> ### 🔴 КОНСИСТЕНТНЫЙ СНИМОК БД (не `cp`)
>
> ```bash
> sqlite3 "file:$DB?mode=ro" ".backup /tmp/tw306/navidrome-fresh.db"
> scp …:/tmp/tw306/navidrome-fresh.db ~/Downloads/music-tags/navidrome-fresh.db
> ```
> 🔑 `.backup` даёт корректный снимок при работающем контейнере; `cp` — нет.
>
> ### 🔴 НЕ ЛОПАТИТЬ ДИСК, ЕСЛИ ДАННЫЕ ЕСТЬ В БД
>
> Alex: «**Ты базу проверяешь или ты назуя тот файлуху пошел лопатить?!**».
> Обход `/music` через `os.walk` + mutagen — 5+ минут, таймаут 180 s. **Navidrome читает из
> своей БД** — все проверки группировки делать SQL-запросом. Диск — только для точечной
> проверки одного конкретного файла.
> *Плюс:* `os.walk` по `/music` ловит `backup*/` внутри библиотеки — любой обход ОБЯЗАН
> отсеивать пути, содержащие `backup`.
## ✅ СЕССИЯ 21 (2026-09-27) — БОЕВОЙ ПРОГОН 306 ВЫПОЛНЕН, ПРОВЕРЕН READ-BACK; ОТКРЫТ NAVidrome RESCAN
> **ТРИГГЕР:** Alex: «**Гони боевой.**» — после того как задача была сформулирована однозначно: