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

This commit is contained in:
Alexey Martemyanov committed 2026-09-27 18:42:36 +06:00
1 parent 54adfa9a5a
commit 41ae82ab3c
3 files changed
+173 -38

No files matched your search

@@ -4,7 +4,7 @@ created: '2026-09-27'
updated: '2026-09-27'
type: plan
namespace: personal
status: session20-dry-run-306-verified-awaiting-apply-go
status: session20-APPLY-306-done-nav.md-REBUILT
tags:
- music
- metadata
@@ -363,6 +363,89 @@ Alex: «**это 4359 правки?**» про таблицу из 16 пар. **
> 🔴 Ловушка: `/mnt/RED_2TB/Music` **пуста** — первый прогон смонтировал её и дал `к правке: 0`.
> Подробности и два питфолла — `[[personal/plans/tagwriter-container]]` §СЕССИЯ 20.
### ✅ БОЕВОЙ ПРОГОН 306 — ВЫПОЛНЕН И ПРИНЯТ ПО ДИСКУ (сессия 20, вечер)
Alex: «**Гони боевой**» → «**Navidrome rescan теперь надо**» → «**Просто контейнер пересоздай**»
→ «**Сука базу блядь снеси руками!!!**»
| Шаг | Факт |
|---|---|
| Бэкап ДО правки | `/mnt/RED_2TB/storage/Music/backup_before_306/20260927-051727` — **306 файлов + `_MANIFEST.tsv`** (md5 каждого до/после копии, расхождений 0). Скрипт `/tmp/backup_306.py` |
| План на NAS | `/tmp/tw306/apply-plan.csv`, md5 `8bfa52389a80119e713b88d05a91b9ef` = локальному ✅ |
| **APPLY** | ✅ **306/306, ошибок 0** |
| Изменения по полям | `TALB` 306 · `TPE2` 306 · `TCON` 264 · `TIT2`/`TPE1`/`TRCK` **0** (не тронуты) |
| **READ-BACK с диска** (не отчёт скрипта) | ✅ проверено 306 · **совпало 306** · расхождений **0** · **album в скобках — 0** · файлов < 100 КБ — **0** (аудио целое). Скрипт `/tmp/verify_306c.py` (пути внутри контейнера: `/app/data`, `/music`) |
> 🔴 **МЕТОД-УРОК (приёмка):** `--apply` печатает «306/306, 0 ошибок» — это **не приёмка**
> (ср. W2: «40/40 записано» при уничтоженном аудио). Приёмка = **перечитать теги с диска**
> своим скриптом и проверить ЗНАЧЕНИЕ + размер файла. Здесь это дало `совпало 306 / расхождений 0`.
### 🔴 NAVIDROME: СКАН НЕ ПЕРЕЧИТЫВАЕТ ТЕГИ — ЛЕЧИТСЯ ТОЛЬКО СНОСОМ БД
Хронология (каждый шаг **проверен запросом к БД**, а не на словах):
| Действие | Результат |
|---|---|
| `docker restart navidrome` | `fullScan=false`, `Scan completed` за 3 с → **в БД те же 14 альбомов со скобками** |
| `docker compose down && up -d` (пересоздание) | снова `fullScan=false` → **те же 14**. БД лежит на диске (том `/data`), пересоздание контейнера её не трогает |
| ✅ **Снос БД руками** | бэкап `data/navidrome.db.bak-20260927-053238/` → `rm navidrome.db{,-shm,-wal}` → старт → `Full scan required after migration`, **`fullScan=true`** |
**Финал (факт по `sqlite3`):**
```
БЫЛО: album со скобками 14 | треков 7861
СТАЛО: album со скобками 0 | альбомов 837 | треков 8167
```
Целевые значения в БД: `Философские` 1 · `Морские` 1 · `Блатные` 1 · `Спортивные` 1 ·
`Из Сказок` 1 · `Разное` 1 · `Москва пьёт пиво` 1 · `Старые хиты` 1 · `Дискотека Авария` 2 ·
`Красивые, богатые` 1 · `Retro` 1 · `Вилли Токарев` 1 · `Володимир Высоцкий`→`Владимир Высоцкий` 1 ·
`Несчастный Случай` 1 · `zvezda` 1. **Скобочных дублей — 0.**
> 🔴 **МЕТОД-УРОК (Navidrome):** обычный скан (`fullScan=false`) сверяет **`mtime`/путь**, а не теги.
> Массовая правка тегов **не видна** быстрому скану: Navidrome добавляет **новые** альбомы,
> старые **не удаляет** → дубли «скобочный + чистый». Рестарт и пересоздание контейнера
> **не помогают** (`ND_SCANSCHEDULE=1h` тоже). Рабочий способ — **снести `navidrome.db`**,
> тогда старт даёт `fullScan=true` и база строится заново. Перед сносом — копия `navidrome.db*`.
> **Теряется:** плейлисты/избранное/счётчики Navidrome. **Не теряется:** музыка и теги (на диске).
> Проверочные запросы: `sqlite3 "file:.../navidrome.db?mode=ro" "SELECT COUNT(*) FROM album WHERE name LIKE \"(%\";"`.
### 🗄 ИНФРАСТРУКТУРА (уточнения сессии 20)
| Факт | Значение |
|---|---|
| **Библиотека музыки на NAS** | **`/mnt/RED_2TB/storage/Music`** (100 ГБ, 15 929 mp3). `/mnt/RED_2TB/Music` — **пустая обманка** |
| Карта путей | план хранит `/storage/Music/...`; в контейнере это `/music`; на хосте `/mnt/RED_2TB/storage/Music` |
| Navidrome | контейнер `navidrome`, образ `deluan/navidrome:latest` (0.64.2), порт 4533, `ND_SCANSCHEDULE=1h` |
| Compose Navidrome | `/mnt/RED_2TB/docker/navidrome/docker-compose.yml` (бэкап `.bak-20260927-052857`), том `/mnt/RED_2TB/storage/Music:/music:rw` |
| `tagwriter:v2` | `CSV_IN = "/app/data/apply-plan.csv"` — путь **зашит константой**, CLI-флага для плана нет. Свой план подкладывать под этим именем в отдельную папку |
| Вариант запуска без approval | `docker run --rm -v …:/app/data:ro -v …/Music:/music:rw tagwriter:v2 --dry-run` |
| `/mnt/RED_2TB/IRONWOLF` | пустой второй пул (не библиотека) |
### ❓ ОТКРЫТЫЙ ВОПРОС ALEX (сессия 20, конец)
Alex про песни из `!Детские` — «**А нам все равно, если б я был султан, платы паровоз — какой
albumartist и album? Они же в песнях для детей лежат? Почему они не в одном альбоме для детей
оказались?**»
**Факт:** этих песен в `!Детские` **нет**. Все три — в **`!Retro/Юрий Никулин`** (3 файла):
```
!Retro/Юрий Никулин/Если бы я был султан.mp3
!Retro/Юрий Никулин/Постой паровоз.mp3
!Retro/Юрий Никулин/А нам все равно.mp3
folder = !Retro/Юрий Никулин class = АЛЬБОМ
album = Песни albumartist = Юрий Никулин artist = Юрий Никулин
```
Причина: правило **D21** (файл в папке артиста = один альбом) смотрит только на **путь** и не
учитывает, что песня «детская». `!Детские` (570 файлов) содержит свои альбомы
(`Сборка Песни для детей` 165 · `Детский Хит Сезона` 156), эти три — не там.
**«Храбрый зайчик»** — поиск по плану и по диску (`*зайчик*`, `*заяц*`, `*храбр*`) дал **0**.
Найденные «зайчики» — другие песни (`Мартовский заяц`, `Хор мальчиков-зайчиков`, `Солнечный зайчик` ×2).
⏭ Ждём от Alex точное имя/исполнителя.
---
## 🟣 СЕССИЯ 18 (2026-09-27) — NAVIDROME РАЗВЁРНУТ, ДЕФЕКТ-КЛАСС ВСКРЫТ, ПРАВИЛА ВОССТАНОВЛЕНЫ ИЗ ZULIP, 306 СТРОК ИСПРАВЛЕНЫ, НОВЫЙ ДИФФ ГОТОВ
+45 -8
View File
@@ -4,7 +4,7 @@ created: '2026-09-26'
updated: '2026-09-27'
type: plan
namespace: personal
status: session22-apply-306-done-navidrome-rescan-failed-14-orphans
status: session22-apply-306-done-navidrome-db-rebuilt-0-orphans
tags:
- music
- truenas
@@ -118,15 +118,52 @@ sqlite3 "file:$DB?mode=ro" "SELECT COUNT(*) FROM album WHERE name LIKE '(%';"
Compose не менялся (бэкап `docker-compose.yml.bak-20260927-052857`), данные/музыка целы.
⚠️ Сироты: `updated_at` 10:09–10:23 UTC, `missing=0` — скан их живыми считает.
**🔑 СЛЕДУЮЩИЙ ШАГ (не сделан): `touch` 306 файлов → полный скан.** `touch` меняет только `mtime`,
содержимое/аудио не трогает; Navidrome увидит «изменённые» файлы и перечитает теги. Альтернатива —
UI-скан с галкой **Full scan** (пароль `navi_admin` неизвестен — **не выдумывать**,
`curl …/rest/ping` → `code 40 Wrong username or password`).
🔑 **РЕШЕНИЕ НАЙДЕНО (Alex): «Сука базу блядь снеси руками!!!» → снос `navidrome.db`.**
Проверка результата — тот же запрос: `LIKE '(%'` должно стать **0**.
| # | Способ | Результат |
|---|---|---|
| 1 | `docker restart navidrome` | ❌ `fullScan=false` → те же **14** |
| 2 | `docker compose down` + `up -d` | ❌ `fullScan=false`, `duration=3.12s` → снова **14** |
| 3 | ✅ **снести `navidrome.db*` → старт** | ✅ `Full scan required after migration`, **`fullScan=true`** → **скобок 0** |
🔴 **ПИТФОЛЛ: `docker restart` и `docker compose down/up` для Navidrome НЕ дают полного скана** —
в логе всегда `fullScan=false`. Смена тегов без смены `mtime` не подхватывается.
**Порядок (выполнен и подтверждён):**
```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 # построит БД заново
```
**Результат (факт по `sqlite3`):**
| Метрика | До сноса | После |
|---|---:|---:|
| `album` со скобками | 14 | **0** |
| треков (`media_file`) | 7861 | **8167** |
| альбомов (`album`) | 967 | **837** |
Все целевые значения присутствуют по одному разу: `Философские` · `Морские` · `Блатные` ·
`Спортивные` · `Из Сказок` · `Разное` · `Москва пьёт пиво` · `Старые хиты` · `Дискотека Авария`(2) ·
`Красивые, богатые` · `Retro` · `Вилли Токарев` · `Владимир Высоцкий` · `Несчастный Случай` · `zvezda`.
⚠️ **Что теряется при сносе БД:** плейлисты, избранное, счётчики проигрываний, оценки, пользователи
Navidrome (пароль задаётся заново в UI). **Что НЕ теряется:** музыка и теги — они на диске.
Поэтому бэкап `navidrome.db.bak-<ts>/` обязателен — единственный путь к откату метаданных Navidrome.
**Проверка после:** `sqlite3 "file:$DB?mode=ro" "SELECT COUNT(*) FROM album WHERE name LIKE '(%';"` → **0**.
⚠️ Сироты: `updated_at` 10:09–10:23 UTC, `missing=0` — скан их живыми считает.
🔴 **ПИТФОЛЛ (главный, метод): НИ `docker restart`, НИ `docker compose down/up` не дают полного
скана Navidrome — в логе всегда `fullScan=false`.** Массовая смена тегов без смены `mtime` не
подхватывается: Navidrome **добавляет** новые альбомы и **не удаляет** старые → дубли
«скобочный + чистый». `ND_SCANSCHEDULE=1h` тоже не помогает. **Единственный рабочий способ —
снести `navidrome.db`** (тогда старт форсирует `fullScan=true`). Альтернатива без сноса —
`touch` 306 файлов (меняет `mtime`, не содержимое) + полный скан; в этой сессии не применялась,
сработал снос БД.
🔴 **Питфолл-нюанс:** Navidrome при скане **пересчитывает album из тегов**, поэтому у 306 файлов
кроме `TALB` сменился и `TPE2` — в БД это **новые** записи альбомов, а не апдейт старых.