[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:
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 СТРОК ИСПРАВЛЕНЫ, НОВЫЙ ДИФФ ГОТОВ
|
||||
|
||||
@@ -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` — в БД это **новые** записи альбомов, а не апдейт старых.
|
||||
|
||||
Reference in new issue
Block a user