[2026-09-27] eagle: family/how-to/navidrome-truenas-android.md personal/plans/tagwriter-container.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-27 18:27:21 +06:00
1 parent 1261d89943
commit 96123c9825
2 files changed
+171 -1

No files matched your search

+132 -1
View File
@@ -4,7 +4,7 @@ created: '2026-09-26'
updated: '2026-09-27'
type: plan
namespace: personal
status: session20-dry-run-306-verified-awaiting-apply-go
status: session21-apply-306-done-navidrome-rescan-pending
tags:
- music
- truenas
@@ -13,6 +13,7 @@ tags:
- id3v1
- plan
- audit
- navidrome
related:
- '[[personal/plans/music-artist-albumartist-repair]]'
- '[[personal/tech/music-tags-repair-truenas]]'
@@ -20,6 +21,136 @@ related:
---
# tagwriter — применение тегов к MP3 (TrueNAS)
## ✅ СЕССИЯ 21 (2026-09-27) — БОЕВОЙ ПРОГОН 306 ВЫПОЛНЕН, ПРОВЕРЕН READ-BACK; ОТКРЫТ NAVidrome RESCAN
> **ТРИГГЕР:** Alex: «**Гони боевой.**» — после того как задача была сформулирована однозначно:
> «**Задача блядь dry run получить с 306 правок так?!**» → «**Да!!**»
>
> **СОСТОЯНИЕ:** ✅ **306/306 применено, ошибок 0, read-back с диска 306/306 совпало.**
> ⏳ Открыто: **Navidrome показывает и старые, и новые album одновременно — нужен полный rescan.**
### ✅ БОЕВОЙ ПРОГОН — ФАКТ
```bash
# бэкап 306 файлов ПЕРЕД записью (обязательно)
scp /tmp/backup_306.py truenas_admin@mallexxx.duckdns.org:/tmp/
ssh … 'python3 /tmp/backup_306.py'
# → скопировано: 306 · не найдено: 0 · md5 до/после сверены
# → /mnt/RED_2TB/storage/Music/backup_before_306/20260927-051727 (+ _MANIFEST.tsv)
# боевой прогон
ssh … 'docker run --rm \
-v /tmp/tw306:/app/data:ro \
-v /mnt/RED_2TB/storage/Music:/music:rw \
tagwriter:v2 --apply'
```
**Вывод apply:**
```
CSV: /app/data/apply-plan.csv ← 306 строк
mp3 на диске: 7861 пропущено не-mp3: 561
пропущено changed=no: 0
не найдено на диске: 0
к обработке: 306
=== APPLY: 306 файлов ===
... 306/306 (100%) ok=306 err=0
=== ИТОГ APPLY ===
обработано: 306 успешно: 306 ошибок: 0
изменения по полям:
TIT2 (title) 0
TPE1 (artist) 0
TPE2 (albumartist) 306
TALB (album) 306
TCON (genre) 264
TRCK (track) 0
```
### ✅ ПРИЁМКА — READ-BACK ТЕГОВ С ДИСКА (не отчёт скрипта)
Скрипт `/tmp/verify_306.py` (в контейнере: `/app/data/verify_306c.py`, пути `PLAN=/app/data/apply-plan.csv`,
`MUSIC=/music`). Читает `mutagen.id3.ID3` и сравнивает **значения** `TALB`/`TPE2` с `new_album`/`new_albumartist`.
```
проверено файлов: 306
совпало (album + albumartist): 306
расхождений: 0
осталось album в скобках: 0 ← 🔑 ключевой индикатор
файлов меньше 100KB: 0 ← аудио целое, не схлопнулось
```
🔴 **Правило: приёмка = чтение тегов с диска по значению, а не `ok=306` из отчёта скрипта.**
Дополнительно проверять **размер файла** (`>100KB`) — он доказывает, что MPEG-поток не тронут (W2).
### ⏳ ОТКРЫТО: NAVidrome — СТАРЫЕ И НОВЫЕ АЛЬБОМЫ СОСУЩЕСТВУЮТ
Navidrome смотрит в **ту же** папку (`/mnt/RED_2TB/storage/Music → /music`), данные
`/mnt/RED_2TB/docker/navidrome/data`, `ND_SCANSCHEDULE=1h`, порт 4533, `https://music.mallexxx.duckdns.org`.
**Проверка БД (sqlite3 есть на NAS: `/usr/bin/sqlite3`, 3.40.1):**
```bash
DB=/mnt/RED_2TB/docker/navidrome/data/navidrome.db
sqlite3 "file:$DB?mode=ro" "SELECT COUNT(*) FROM album WHERE name LIKE '(%';" # → 14
```
| Что | Значение |
|---|---|
| альбомов в БД | 967 |
| со скобками | **14** |
| новые значения (`Философские`, `Морские`, `Москва пьёт пиво`, `Retro`, `Владимир Высоцкий`, …) | ✅ появились |
| старые скобочные (`(Философские)`, `(Авария)` ×2, `(Высоцкий)`, …) | ❌ **НЕ удалены** |
**Диагноз:** watcher/плановый скан **добавил** новые альбомы, но **не вычистил старые записи**,
к которым больше нет файлов. Нормальное поведение инкрементального скана — нужен полный rescan.
**Что нужно (не сделано, ждёт решения Alex):**
1. **Рестарт контейнера** — `docker restart navidrome` (полный скан на старте, чистит пропавшие) —
предпочтительный вариант, без пароля;
2. **Плановый скан** — сам раз в час (`ND_SCANSCHEDULE=1h`);
3. Rescan через API требует пароль `navi_admin` — **неизвестен, не выдумывать**
(`curl …/rest/ping` → `code 40 Wrong username or password`).
Проверка результата — тот же запрос: `LIKE '(%'` должно стать **0**.
🔴 **Питфолл-нюанс:** Navidrome при скане **пересчитывает album из тегов**, поэтому у 306 файлов
кроме `TALB` сменился и `TPE2` — в БД это **новые** записи альбомов, а не апдейт старых.
Пока старые не вычищены, в UI видны оба варианта (со скобками и без).
### 🔴 ИТОГОВЫЙ ПИТФОЛЛ СЕССИИ 21: ЗАДАЧА БЫЛА НЕ СФОРМУЛИРОВАНА — ЧИТАТЬ «СКОЛЬКО ПРАВОК» БУКВАЛЬНО
Alex потратил час, повторяя один вопрос. Разбор:
| Что я говорил | Что было нужно |
|---|---|
| `7649` (весь план) | **`306`** — сколько правок ЖЕЛАЕМ сделать |
| `7963` / `4359` (genre) | не относится к задаче |
| «какой план гонять?» — переспрашивал | задача была уже названа: **dry-run должен показать 306** |
🔴 **ПРАВИЛО: если Alex называет ожидаемое число вывода — это И ЕСТЬ задача.**
Не переспрашивать «какой план», не предлагать варианты меню. Собрать артефакт так, чтобы
вывод был равен названному числу. Переспрашивание после названного числа читается как саботаж.
Ср. D32 (дифф завышает — считать по плану), D33 (путь + md5 + промежуточные/финальные значения),
D35 (не называть числа двух артефактов в одной фразе), D36 (формулировка счёта одним предложением).
### 📁 АРТЕФАКТЫ СЕССИИ 21
```
~/Downloads/music-tags/apply-plan-306.csv 306 строк, md5 8bfa52389a80119e713b88d05a91b9ef
/tmp/make_plan_306.py сборка плана 306 из APPLY-PLAN.csv + ALBUM-FIX-306.csv
/tmp/backup_306.py бэкап 306 файлов + _MANIFEST.tsv (md5, size)
/tmp/verify_306.py (→ verify_306c.py в контейнере) read-back TALB/TPE2 с диска + проверка размера
/tmp/check_navidrome.py проверка БД Navidrome (sqlite3, read-only)
NAS: /mnt/RED_2TB/docker/arr/tagwriter/apply-plan-306.csv
NAS: /tmp/tw306/apply-plan.csv 306-план под именем, которое читает скрипт
NAS: /mnt/RED_2TB/storage/Music/backup_before_306/20260927-051727/ бэкап + _MANIFEST.tsv
```
## 🟢 СЕССИЯ 20 (2026-09-27, поздний вечер) — ПРОИЗВОДНЫЙ ПЛАН НА 306 СОБРАН, DRY-RUN ЖДЁТ «GO»
> **ТРИГГЕР:** Alex спросил про diff с 371 правкой → после разбора выяснилось, что **spor идёт