From 01c7fe6d03a0083ffe29f9f8e3cafd0017037ffa Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Sun, 27 Sep 2026 10:36:34 +0600 Subject: [PATCH] [2026-09-27] eagle: family/how-to/navidrome-truenas-android.md family/plans/music-jellyfin-lidarr-taiga.md personal/tech/jellyfin-music-library-pitfalls.md personal/tech/jellyfin-tags-cp1251-unreadable.md --- family/how-to/navidrome-truenas-android.md | 40 +++- family/plans/music-jellyfin-lidarr-taiga.md | 108 +++++++-- .../tech/jellyfin-music-library-pitfalls.md | 136 +++++++++++ .../tech/jellyfin-tags-cp1251-unreadable.md | 219 +++++++++++++++++- 4 files changed, 478 insertions(+), 25 deletions(-) create mode 100644 personal/tech/jellyfin-music-library-pitfalls.md diff --git a/family/how-to/navidrome-truenas-android.md b/family/how-to/navidrome-truenas-android.md index 41120888..f62d37cc 100755 --- a/family/how-to/navidrome-truenas-android.md +++ b/family/how-to/navidrome-truenas-android.md @@ -15,7 +15,7 @@ | Источник имени артиста | **имя папки** перекрывает тег | **только тег** | | Структура папок | требуется `Artist/Album/Track` | **игнорируется полностью** | | Наша структура `категория/подпапка/файл` | ломает навигацию | **работает как есть** | -| Интернет-метаданные артистов | тянет из MusicBrainz → левые артисты (`Maria Makarova (organ)`) | **не тянет** | +| Интернет-метаданные артистов | тянет из MusicBrainz → левые артисты | **не тянет** | | Пишет в файлы | может | **никогда** (by design) | **Официальная дока Navidrome (Tagging Guidelines), прямая цитата:** @@ -66,13 +66,47 @@ ⚠️ **Но выявлен новый пробел:** в файлах **отсутствует `TPE2` (albumartist)** — проверено `154/154`. Его **не было в плане правок** (`tag-fix-plan.csv` не содержит колонки `album_artist`). -Navidrome строит **альбомы** по `AlbumArtist`; артисты будут правильные и без него, -но альбомы могут склеиваться. **Желательно добавить `TPE2` перед запуском.** + +### ✅ `ALBUMARTIST` для Navidrome — НЕ обязателен (проверено 2026-09-27) + +**Не блокирует запуск.** Мейнтейнер Navidrome `deluan` (обсуждение #5924): +> «when an album artist tag is missing, Navidrome substitutes the **track artist** in its place» + +| Ситуация | Результат | +|---|---| +| `ALBUMARTIST` у всех треков | 1 альбом ✅ | +| Нет `ALBUMARTIST`, сольный альбом | 1 альбом ✅ | +| Нет `ALBUMARTIST`, 4 фита | **5 альбомов** вместо 1 ❌ | +| Нет `ALBUMARTIST`, сборник 18 треков | **до 18 альбомов** ❌ | + +**Обход без правки файлов — конфиг:** +```toml +PID.Album = "musicbrainz_albumid|albumartist,album,albumversion,releasedate" +``` +> 🔑 Сырое `albumartist`, **НЕ** `albumartistid` (тот никогда не пуст). `folder` в спеку +> класть нельзя. ⚠️ Смена `PID.Album` → полный рескан + новые ID → **бэкапить `navidrome.db`**. + +### ✅ Новые закачки тегирует Lidarr сам + +Lidarr матчит по MusicBrainz release groups и пишет полные теги, **включая `Album Artist`** +(действие `Write Metadata Tags`). Связка [`navidrome-lidarr-bridge`](https://github.com/danielbanariba/navidrome-lidarr-bridge) +— закачанное Lidarr'ом подхватывается Navidrome автоматически. + +### ⚠️ Что реально стоит починить до запуска: СЕМАНТИКА `artist` + +Файлы `!Классика` содержат **семантически мусорные** `artist` — формально валидные теги: +``` +artist=Классика в современной обработке ← это не артист +artist=Классика для детей П.И. Чайковский ← это не артист +artist=Maria Makarova (organ) ← исполнитель вместо композитора +``` +**Navidrome покажет их как артистов** — надо смотреть и чистить. Детали — [[personal/tech/jellyfin-tags-cp1251-unreadable]] §ИНВЕНТАРИЗАЦИЯ. ## Следующие шаги - [x] ~~Сначала: ремонт тегов 7906 файлов~~ → ✅ выполнен (волна 38) +- [ ] **Аудит семантики `artist`** — убрать «Классика в современной обработке» и подобное - [ ] **Опционально:** добавить `TPE2` = `TPE1` (нужен НОВЫЙ план правок с колонкой `album_artist`) - [ ] Поднять Navidrome в Docker на TrueNAS - [ ] Пробросить порт / настроить Caddy subdomain (Caddyfile root-owned → через alpine-контейнер) diff --git a/family/plans/music-jellyfin-lidarr-taiga.md b/family/plans/music-jellyfin-lidarr-taiga.md index 7ce1d510..6e1e0c1c 100755 --- a/family/plans/music-jellyfin-lidarr-taiga.md +++ b/family/plans/music-jellyfin-lidarr-taiga.md @@ -1,19 +1,101 @@ -# Music → Jellyfin + Lidarr на Тайге — план (v6, 2026-09-27) +# Music → Jellyfin + Lidarr на Тайге — план (v7, 2026-09-27) -> ✅ **СТАТУС v6: ОТКАТ ЗАВЕРШЁН И ПОДТВЕРЖДЁН.** БД Jellyfin восстановлена на версию до импорта -> музыки. Итог: 6 библиотек, Audio=0, MusicArtist=0, Music отсутствует. Jellyfin работает. -> **MD5 внутри контейнера = `b71b5d659a1262fa98b85a6ab0003f24`** — совпал с бэкапом. -> Задача Lidarr — **не начата, отложена** (Alex не возвращался к ней после отката). +> ✅ **СТАТУС v7: JELLYFIN ОТКАЧЕН И СТАБИЛЕН. КУРС СМЕНЁН НА NAVIDROME.** +> БД Jellyfin восстановлена на версию до импорта музыки: 6 библиотек, Audio=0, MusicArtist=0. +> **MD5 `b71b5d659a1262fa98b85a6ab0003f24`** — совпал с бэкапом. > -> 🔴 **ГЛАВНОЕ ОТКРЫТИЕ v6: поведение Jellyfin — это ОФИЦИАЛЬНО ПОДТВЕРЖДЁННЫЙ БАГ -> [`jellyfin/jellyfin#18162`](https://github.com/jellyfin/jellyfin/issues/18162), а НЕ проблема -> наших тегов.** Jellyfin берёт имя артиста **из имени папки**, перекрывая теги. Гипотеза -> «в файлах нет `TPE2`» **смягчена**: `TPE2` отсутствует у 154/154 (факт), но баг перекрывает -> теги именем папки **даже при валидном `ALBUMARTIST`**. +> 🔀 **РЕШЕНИЕ СЕССИИ: Jellyfin для музыки НЕПРИГОДЕН — ставим Navidrome.** +> Причина — подтверждённый баг [`jellyfin/jellyfin#18162`](https://github.com/jellyfin/jellyfin/issues/18162) +> (имя папки перекрывает теги) + наша 4-уровневая структура. Navidrome читает **только теги**, +> папки игнорирует полностью, бага не имеет. Сравнение движков — +> [[personal/tech/jellyfin-tags-cp1251-unreadable]]. > -> ✅ **Найденное решение: Navidrome** — читает теги, **папки игнорирует полностью**, бага не имеет. -> Детали и сравнение движков — [[personal/tech/jellyfin-tags-cp1251-unreadable]]. -> Деплой-план — [[family/how-to/navidrome-truenas-android]]. +> 🔴 **ИСТОЧНИК `Maria Makarova (organ)` НАЙДЕН (v7):** это **наш собственный тег** +> `artist=Maria Makarova (organ)` в файле `!Классика/Бах — Toccata and Fugue in D minor.mp3`. +> **НЕ MusicBrainz, НЕ «Маша Макарова» из Ногу Свело** — обе версии опровергнуты. +> +> ⏳ **ОТКРЫТЫЕ ЗАДАЧИ (см. §Открытые задачи в конце):** +> 1. Дополнение `Music/backup` — скан готов (1436 файлов не хватало), **ждёт решения Alex** по `.avi`/`.mpg`/`.DS_Store`; +> 2. Бэкап CSV на Mac — ✅ **выполнено**; +> 3. Аудит семантики `artist` — **не начат**; +> 4. Деплой Navidrome — **не начат**; +> 5. Lidarr — **не начат, отложен**. +> +> 📌 **Lidarr:** задача из исходной команды Alex остаётся в силе, но **отложена** — +> сначала библиотека в Navidrome. Новые закачки Lidarr тегирует **сам** через MusicBrainz +> (включая `Album Artist`), поэтому ручная правка нужна только для существующих 7861 файла. + +## 🔀 v7: РЕШЕНИЕ — NAVIDROME ВМЕСТО JELLYFIN ДЛЯ МУЗЫКИ + +**Проверено по официальной доке Navidrome и GitHub (2026-09-27).** + +| | Jellyfin (баг #18162) | Navidrome | +|---|---|---| +| Источник имени артиста | **имя папки** перекрывает тег | **только тег** | +| Структура папок | обязательна `Artist/Album/Track` | **игнорируется** | +| Наша структура `категория/подпапка/файл` | ломает навигацию | **работает как есть** | +| Интернет-метаданные артистов | тянет из MusicBrainz | **не тянет** | +| Пишет в файлы | может | **никогда** (by design) | +| Видео | ✅ (видеотека остаётся здесь) | ❌ | + +**Официальная дока Navidrome:** +> «Navidrome organizes your music library **entirely** based on the metadata tags in your audio +> files. Unlike some music players, **it does not use folder names or file names to group tracks**.» + +### `ALBUMARTIST` в Navidrome — НЕ обязателен (ответ на вопрос Alex) + +**Navidrome подставляет `artist`, если `albumartist` отсутствует** — цитата мейнтейнера +`deluan` (обсуждение #5924): +> «when an album artist tag is missing, Navidrome substitutes the **track artist** in its place» + +**Что при этом происходит:** + +| Ситуация | Результат | +|---|---| +| `ALBUMARTIST` у всех треков | 1 альбом ✅ | +| Нет `ALBUMARTIST`, 4 фита | **5 альбомов** вместо 1 ❌ | +| Нет `ALBUMARTIST`, сборник 18 треков | **до 18 альбомов** ❌ | + +**Обход без правки тегов — конфиг `PID.Album`:** +```toml +PID.Album = "musicbrainz_albumid|albumartist,album,albumversion,releasedate" +``` +> 🔑 Использовать **сырое `albumartist`**, НЕ `albumartistid` (последний никогда не пуст — +> вычисляется после подстановки track artist). `folder` в спеку класть нельзя как fallback. +> ⚠️ Смена `PID.Album` → полный рескан + новые ID → **бэкапить `navidrome.db`**. + +### ✅ Новые закачки тегирует Lidarr сам + +Lidarr матчит по **MusicBrainz release groups** и пишет полные теги, включая `Album Artist` +(штатное действие `Write Metadata Tags`). Существует официальная связка +[`navidrome-lidarr-bridge`](https://github.com/danielbanariba/navidrome-lidarr-bridge): +закачанное Lidarr'ом попадает в папку Navidrome и подхватывается автоматически. + +## 📌 ОТКРЫТЫЕ ЗАДАЧИ (v7, для следующей сессии) + +| # | Задача | Статус | Детали | +|---|---|---|---| +| 1 | Дополнить `Music/backup` | 🟡 **скан готов, ждёт решения** | не хватало **1436 файлов** (876 mp3, 287 jpg, 6 mpg, 5 avi, 18 `.DS_Store`). Вопрос Alex по видео/мусору — ответа нет | +| 2 | Бэкап CSV на Mac | ✅ **выполнено** | `/Users/admin/milestones/music-csv-2026-09-26/` — 3 CSV + MD5SUMS + README | +| 3 | Аудит семантики `artist` | 🔴 не начат | `artist=Классика в современной обработке`, `Maria Makarova (organ)` и т.п. — формально валидны, семантически мусор | +| 4 | Деплой Navidrome | 🔴 не начат | план — [[family/how-to/navidrome-truenas-android]] | +| 5 | Проставить `TPE2` | ⏸ отложено | нужно **только** если в Navidrome раздробятся сборники; для Jellyfin бессмысленно (баг) | +| 6 | Lidarr | 🔴 не начат | задача из исходной команды, отложена до библиотеки | +| 7 | Починить авто-бэкап Jellyfin | 🔴 не начат | `SQLiteBackups` пуста с 3 июня | + +### 📦 Milestone: CSV сохранены на Mac (2026-09-27) + +``` +/Users/admin/milestones/music-csv-2026-09-26/ +├── tag-inventory.csv 1.6 МБ md5 ca2d1767fd784771c44290529972a201 +├── tag-inventory2.csv 1.7 МБ md5 52d90e676930110a76c979c0a2fa800c +├── tag-fix-plan.csv 2.2 МБ md5 8742abff7387e1ae719f3e35c6cf0176 +├── MD5SUMS.txt +└── README.md +``` + +Копии read-only, оригиналы на NAS. **README содержит** описание колонок, распределение +`verdict`/`action`, и главную находку — **отсутствие `album_artist` в плане правок**. ## 🔴 v6: БАГ JELLYFIN #18162 — имя папки перекрывает теги diff --git a/personal/tech/jellyfin-music-library-pitfalls.md b/personal/tech/jellyfin-music-library-pitfalls.md new file mode 100644 index 00000000..71f6648c --- /dev/null +++ b/personal/tech/jellyfin-music-library-pitfalls.md @@ -0,0 +1,136 @@ +# Skill: jellyfin-music-library-pitfalls — зеркало навыка + +**Скилл:** `devops/jellyfin-music-library-pitfalls` +**Путь:** `~/.hermes/hermes-whale/skills/devops/jellyfin-music-library-pitfalls/SKILL.md` +**Создан:** 2026-09-27 +**Category:** devops + +> Зеркало для vault. Полный текст — в SKILL.md скилла. + +## Когда применять + +Любая работа с **музыкальной** библиотекой Jellyfin на удалённом Docker-хосте +(TrueNAS/Taiga, Kraken): добавление, отладка неверной навигации, откат. + +**Сначала читать в vault:** +- [[personal/tech/jellyfin-tags-cp1251-unreadable]] — почему Jellyfin не читает теги +- [[family/plans/music-jellyfin-lidarr-taiga]] — план проекта + +## Ключевые правила (краткая версия) + +### 🔴 RULE 0 — бэкап БД ДО создания библиотеки + +Создание библиотеки + скан пишет тысячи строк в `BaseItems`. **Без бэкапа БД откат невозможен.** + +```bash +docker stop jellyfin +docker cp jellyfin:/config/data/data/jellyfin.db /home/truenas_admin/jellyfin.db.bak-$(date +%Y%m%d-%H%M%S) +docker start jellyfin +``` + +- **WAL чекпоинтится только при остановленном контейнере** — иначе копия битая. +- **`SQLiteBackups/` часто ПУСТА** — не полагаться на авто-бэкапы Jellyfin, проверять. +- **Снапшоты ZFS часто 0 штук** — проверять `zfs list -t snapshot | wc -l`. + +### 🔴 Почему Jellyfin игнорирует ID3-теги — три причины + +1. **Баг `jellyfin/jellyfin#18162`** (confirmed, In Progress): имя MusicArtist берётся + **из имени ПАПКИ**, перекрывая `ARTIST`/`ALBUMARTIST`. Если имя папки произвольное — + Jellyfin идёт в **MusicBrainz** и создаёт артиста оттуда. +2. **Отсутствует `TPE2` (albumartist)** — ключевое поле для иерархии Artist→Album→Track. + При пустом `TPE2` Jellyfin уходит в fallback на папки и **перестаёт читать `TPE1` вообще**. +3. **4-уровневая структура** `категория/подпапка/релиз/файл` — Jellyfin читает как + `Artist/Album`. + +**Сигнатура дефекта:** `число MusicArtist == число папок верхнего уровня`. + +### 🔬 Диагностика — через `od`, НЕ `ffprobe` + +`ffprobe` нормализует вывод и **угадывает кодировку** → может показать `album_artist`, +которого нет как фрейма `TPE2` (из ID3v1-хвоста или TXXX). + +```bash +od -A d -t x1z -N 200 "/path/file.mp3" # заголовок + первые фреймы +od -A d -t x1z -N 2000 "$F" | grep -oE "[A-Z][A-Z0-9]{3}" | sort -u # все фреймы +od -A d -t x1z -N 4000 "$F" | grep "P E 2" # есть ли TPE2 +``` + +**Питфоллы:** +- `-of default=nw=1:nk=1` срезает префиксы `TAG:` → ложный вывод «теги пустые». +- `TAG:ID3v1 Comment=` — это **128-байтный ID3v1-хвост**, где CP1251 нормальна. + Цитировать как доказательство CP1251 в ID3v2 — **ошибка вывода**. +- **Валидация ffprobe ≠ доказательство читаемости для потребителя.** Проверять движком, + который читает в проде. Выборка 1% (108 из 7861) ничего не доказывает. + +### 🔴 НИКОГДА не использовать `DELETE /Items` — он удаляет ФАЙЛЫ + +Удаляет медиафайл с диска, не только запись БД. При rw-монтировании **снесёт музыку**. +Спасает только `ro`-mount. `POST /Library/Media/Deleted` → **404**; `POST /Library/Media/Updated` +→ **415** без JSON body. + +**Для удаления только записей — править SQLite напрямую при остановленном контейнере.** + +### Безопасный откат БД + +Полная процедура (5 шагов) — в SKILL.md. Ключевое: + +1. `docker stop` → бэкап текущей БД; +2. распаковка архивной БД + **проверка MD5**; +3. удаление WAL/SHM **при ЗАПУЩЕННОМ контейнере** (`docker exec` не работает на остановленном); +4. `docker cp` БД внутрь + `chown abc:abc` + `docker start`; +5. **проверка `md5sum` ВНУТРИ контейнера** — не по коду возврата. + +### Питфоллы (проверено) + +| # | Питфолл | +|---|---| +| 1 | `docker exec` НЕ работает на остановленном контейнере → WAL удалять при запущенном | +| 2 | `docker cp` может вернуть `container is not running`, **НО копия проходит** → проверять `md5sum` | +| 3 | Глоб `jellyfin.db*` не раскрывается в zsh контейнера → ложное «файла нет» | +| 4 | `docker stop` возвращает `Exited (137)` (SIGKILL) — не признак поломки данных | +| 5 | Хост и контейнер показывают разное время одного файла (PDT vs +07) — это НЕ расхождение | +| 6 | **Не запускать скрипт-мутатор «для проверки»** — создаст библиотеку обратно | +| 7 | `"a"+"b"` в bash/zsh → пустая строка → HTTP 401. Правильно `"${A}${B}"` | +| 8 | Токен/`os.environ` в файле искажается санитайзером → внешняя обёртка + `export`, сверять `md5sum` | + +### Выбор движка: Jellyfin vs Navidrome + +| | Jellyfin | Navidrome | +|---|---|---| +| Источник имени артиста | **папка перекрывает тег** (баг #18162) | **только тег** | +| Структура папок | `Artist/Album/Track` обязательна | **игнорируется полностью** | +| Интернет-метаданные | тянет MusicBrainz | **не тянет** | +| Пишет в файлы | может | **никогда** | +| Видео | ✅ | ❌ | + +**`ALBUMARTIST` в Navidrome НЕ обязателен** — мейнтейнер `deluan` (#5924): +> «when an album artist tag is missing, Navidrome substitutes the track artist in its place» + +Обход без правки тегов: +```toml +PID.Album = "musicbrainz_albumid|albumartist,album,albumversion,releasedate" +``` +- **сырое `albumartist`**, НЕ `albumartistid` (тот никогда не пуст); +- `folder` в спеку как fallback класть **нельзя**; +- смена `PID.Album` → полный рескан + новые ID → **бэкапить `navidrome.db`**. + +**Lidarr пишет теги сам** при импорте (MusicBrainz + `Write Metadata Tags`) — новые закачки +приходят с `Album Artist`. Связка: `navidrome-lidarr-bridge`. + +### Ловушка: семантически валидные, но бессмысленные теги + +``` +artist=Классика в современной обработке ← не артист +artist=Классика для детей П.И. Чайковский ← не артист +artist=Maria Makarova (organ) ← исполнитель вместо композитора +``` + +Проходят любую проверку на мойибаке/кодировку. **Если имя артиста в UI удивляет — сначала +grep по тегу `artist` реальных файлов**, прежде чем строить версии про внешние базы. + +## Связанные заметки + +- [[personal/tech/jellyfin-tags-cp1251-unreadable]] — полный разбор дефекта +- [[family/plans/music-jellyfin-lidarr-taiga]] — план проекта, открытые задачи +- [[family/how-to/navidrome-truenas-android]] — план деплоя Navidrome +- [[personal/tech/jellyfin-db-schema-mismatch]] — схема БД Jellyfin diff --git a/personal/tech/jellyfin-tags-cp1251-unreadable.md b/personal/tech/jellyfin-tags-cp1251-unreadable.md index 2bcc5abd..3ea035a3 100755 --- a/personal/tech/jellyfin-tags-cp1251-unreadable.md +++ b/personal/tech/jellyfin-tags-cp1251-unreadable.md @@ -204,18 +204,50 @@ TAG:ID3v1 Comment=ñêàçêà ← 🔑 МАРКЕР ^^^^^^^^^^^^ имя папки в запросе ``` -### 🎯 ЭТО ОБЪЯСНЯЕТ `Maria Makarova (organ)` +### 🎯 ЭТО ОБЪЯСНЯЕТ `Maria Makarova (organ)` — v7: ИСТОЧНИК НАЙДЕН, ЭТО НАШИ ТЕГИ -Alex указал на несоответствие: `Maria Makarova` в UI Jellyfin — это **органистка -(Maria Makarova, organ)**, а НЕ «Маша Макарова» из Ногу Свело. +> 🔴 **v7 (2026-09-27, финальная сессия): версия «имя пришло из MusicBrainz» тоже НЕВЕРНА.** +> Источник — **собственный тег `artist` в нашем файле.** Ниже сохранены обе ошибочные версии +> как история; **актуальный факт — в этом блоке.** -- В наших файлах есть только фит: `!Rock&Folk/Ногу Свело!/2004 - Откровенные фотографии/10.Ногу свело - Реки (feat. Маша Макарова).mp3` -- Файлов с тегом `Makarova`/`Макарова` в библиотеке **не найдено** поиском по тегам. -- **Вывод: имя пришло ИЗ ВНЕШНЕЙ БАЗЫ (MusicBrainz/TheAudioDB)**, куда Jellyfin пошёл по - имени папки/файла и получил первое совпадение — западную органистку. +**Файл-источник (найден фактом через CSV + чтение тегов):** -> 🔴 **Версия «она прошла потому, что имя ASCII/латиница» — ОКОНЧАТЕЛЬНО ОПРОВЕРГНУТА.** -> Не тиражировать ни в какой форме. +``` +/storage/Music/!Классика/Бах — Toccata and Fugue in D minor.mp3 + TAG:title=J.S. Bach: Toccata and Fugue (D minor) BWV565 + TAG:artist=Maria Makarova (organ) ← 🔑 ВОТ ОНА, в НАШЕМ теге + raw TPE2 в файле: НЕТ +``` + +**`Maria Makarova (organ)` записан в тег `artist` этого файла** — исполнительница Баха. +Jellyfin честно создал по нему артиста. **Отсюда в UI ровно один артист** — +не баг, не MusicBrainz, не «feat. Маша Макарова», а **наши собственные данные.** + +**Следствие для ремонта:** это **семантическая ошибка в тегах**, а не техническая. +У Баха артист должен быть «И.С. Бах», а исполнитель — в отдельном поле (`TPE2`/`composer`). +Такие файлы стоит искать отдельным аудитом семантики `artist`. + +> ⚠️ **ДВЕ опровергнутые версии этого же имени (не тиражировать ни одну):** +> 1. «feat. Маша Макарова из Ногу Свело» — **неверно**, это фит в другом файле +> (`!Rock&Folk/Ногу Свело!/.../10.Ногу свело - Реки (feat. Маша Макарова).mp3`), +> к органистке отношения не имеет; +> 2. «пришло из MusicBrainz/TheAudioDB» — **неверно**, имя лежит в теге нашего файла. +> 3. «прошла потому что латиница/ASCII» — **неверно** (см. ниже). + +### ⚠️ Уточнение к v6: где именно ломается навигация + +Баг #18162 **подтверждён официально**, но в **нашем** случае действуют **оба** фактора, +и разделить их точно не удалось: + +| Фактор | Статус | +|---|---| +| `TPE2` отсутствует у 154/154 (факт) | ✅ подтверждён | +| Баг #18162 перекрывает теги именем папки | ✅ подтверждён в upstream | +| Наша 4-уровневая структура `категория/папка/папка/файл` | ✅ вклад есть | + +**Практический вывод:** Jellyfin для нашей структуры **непригоден** независимо от того, +какой из факторов главный. Поэтому решение — **сменить движок на Navidrome**, а не +чинить `TPE2` ради Jellyfin. ### Следствие: `TPE2` — НЕ единственная и, вероятно, не главная причина @@ -272,6 +304,80 @@ Alex указал на несоответствие: `Maria Makarova` в UI Jell правильные (по `TPE1`), но альбомы могут склеиваться/дробиться. `TPE2` желателен, но **не блокирует запуск** — в отличие от Jellyfin. +### 🔬 `ALBUMARTIST` в Navidrome — НЕ обязателен (ответ на вопрос Alex, 2026-09-27) + +**Вопрос Alex:** «Ты уверен, что Navidrome это поле обязательно? А новые закачки как в него +попали бы, если оно нигде не заполнено?» + +**Ответ получен из первоисточников.** + +**① Не обязательно — Navidrome подставляет `artist`.** Из официального обсуждения +Navidrome **#5924**, ответ **мейнтейнера `deluan`**: + +> «when an album artist tag is missing, Navidrome substitutes the **track artist** in its place» + +**Что при этом происходит:** + +| Ситуация | Результат в Navidrome | +|---|---| +| `ALBUMARTIST` у всех 12 треков | 1 альбом, 12 треков ✅ | +| `ALBUMARTIST` у 10 из 12 | 1 альбом + 2 «сироты» ⚠️ | +| Нет `ALBUMARTIST`, 4 фита | **5 альбомов** вместо 1 ❌ | +| Нет `ALBUMARTIST`, сборник 18 треков | **до 18 альбомов** ❌ | + +Из технического разбора (dev.to, «tagging and mount anti-patterns»): + +> «Because it is the only tag that tells Navidrome **who owns the album**, and when it is absent +> the scanner falls back to the per track `ARTIST` value. On a solo record that fallback is +> harmless. On anything with a featured guest, a duet, a remixer or an orchestra credit, it +> **shatters one album into several one-track albums**.» + +> **Правило:** `ARTIST` описывает исполнение; `ALBUMARTIST` описывает «полку» — должен быть +> **идентичен у каждого файла альбома**. + +**② Имена тегов по контейнерам:** `TPE2` (ID3v2/MP3), `ALBUMARTIST` (Vorbis/FLAC), +`aART` (MP4/AAC/ALAC). + +**③ Обход без правки тегов — есть конфиг.** Если `ALBUMARTIST` отсутствует массово, можно +поправить **группировку**, не трогая файлы: + +```toml +# navidrome.toml +PID.Album = "musicbrainz_albumid|albumartist,album,albumversion,releasedate" +``` + +> 🔑 **Ключевой нюанс от `deluan`:** использовать в спеке **сырое имя тега `albumartist`**, +> а **НЕ `albumartistid`** — последний вычисляется **после** подстановки track artist и +> поэтому **никогда не пустой**. Сырой `albumartist` = реальное значение тега. +> +> ⚠️ **Использовать в спеку `folder` НЕЛЬЗЯ как «fallback»** — секция спеки пропускается +> только когда **все** её значения пусты, а `album` всегда непуст → первая секция всегда матчится. +> +> ⚠️ **Смена `PID.Album` → полный рескан и новые ID.** Бэкапить `navidrome.db` перед этим: +> play counts / рейтинги / starred привязаны к старым ID. + +**④ Оговорка:** PID управляет **только группировкой, не отображаемым именем**. Слитый альбом +всё равно покажет одного из track-артистов как album artist — это в доке признано и требует +изменения кода. + +### ✅ Новые закачки: Lidarr пишет `albumartist` сам + +**Lidarr работает через MusicBrainz и проставляет полные теги при импорте:** +> «It scans a root folder, matches what it finds to **MusicBrainz release groups**, and imports +> matched files» (Servarr Wiki, Lidarr Library) + +**В Lidarr есть штатное действие записи тегов:** `Write Metadata Tags` (в меню Select Artists +для массовой операции над выбранными артистами). + +**То есть:** новые закачки приходят с полным набором тегов, **включая `Album Artist`** — +MusicBrainz отдаёт его для каждого релиза. Ручная простановка нужна только для **существующей** +библиотеки (7861 файл). + +**Связка Lidarr + Navidrome — штатный, поддерживаемый сценарий:** существует отдельный проект +[`navidrome-lidarr-bridge`](https://github.com/danielbanariba/navidrome-lidarr-bridge) — +звёздочка артиста в Navidrome запускает мониторинг в Lidarr, а закачанное Lidarr'ом попадает +прямо в папку Navidrome и подхватывается автоматически. + **Наша библиотека готова к Navidrome:** 7826 файлов, теги `artist`/`title`/`album` в UTF-16. **Минусы Navidrome:** нет просмотра по папкам вообще (разработчик отказал принципиально: @@ -356,6 +462,101 @@ fix 2935 no_change 1582 + артисты-значения: Savant 237, Сектор Газа 191, Infected Mushroom 187, Ленинград 161, Enigma 107, Любэ 103 ``` +### 🔍 Что такое `clean`-файлы и есть ли у них `albumartist` (ответ Alex) + +**Вопрос Alex:** «В тех которые clean — это какие например? В них есть albumartist?» + +**`clean` = заполнены `title` + `artist`, мойибаке нет.** Критерий — «не кракозябры», +**не** «полный набор тегов». + +**Выборка 12 файлов со `status_title=clean` И `status_artist=clean`** (все из `!Классика`): + +| # | Файл | `artist` | `album_artist` в CSV | raw `TPE2` | +|---|---|---|---|---| +| 1 | Чайковский — Танец маленьких лебедей | Пётр Ильич Чайковский | пусто | НЕТ | +| 2 | Моцарт — Турецкий марш | Классика в современной обработке | пусто | НЕТ | +| 3 | Григ — В пещере горного короля | Эдвард Григ | пусто | НЕТ | +| 4 | Вивальди — Зима | Вивальди | пусто | НЕТ | +| 5 | Бетховен — К Элизе | Людвиг ван Бетховен | пусто | НЕТ | +| 6 | Сен-Санс — Пляска смерти | Kevin MacLeod | **Kevin MacLeod** | НЕТ | +| 7 | **Бах — Toccata and Fugue** | **Maria Makarova (organ)** | пусто | НЕТ | +| 8 | Вагнер — Полёт валькирий | Рихард Вагнер | пусто | НЕТ | +| 9 | Прокофьев — Танец рыцарей | КЛАССИКА. Сергей Прокофьев | пусто | НЕТ | +| 10 | Чайковский — Танец феи Драже | Классика для детей П.И. Чайковский | пусто | НЕТ | +| 11 | Вивальди — Лето | Популярная классика | пусто | НЕТ | +| 12 | Свиридов — Метель | Georgy Sviridov (Moscow City Symphony) | пусто | НЕТ | + +**Итог: 11 из 12 — `album_artist` пуст; `raw TPE2` НЕТ ни у одного.** + +> 🔑 **Важный питфолл:** у файла №6 ffprobe **показывает** `album_artist=Kevin MacLeod`, +> но `raw TPE2` в байтах **не найден**. Значит ffprobe читает это значение **НЕ из `TPE2`**, +> а из другого источника (ID3v1-хвост или TXXX-фрейм). Это объясняет расхождение: +> в CSV `album_artist` заполнен у **3507**, но в реальных ID3v2-фреймах `TPE2` **нет**. +> **Не доверять ffprobe для проверки наличия `TPE2` — только `od` по байтам.** + +### ⚠️ Семантика `artist` — отдельный класс дефектов + +Файлы `!Классика` показывают **семантическую**, не техническую проблему: + +``` +artist=Классика в современной обработке ← это не артист +artist=Классика для детей П.И. Чайковский ← это не артист +artist=КЛАССИКА. Сергей Прокофьев ← это не артист +artist=Maria Makarova (organ) ← исполнитель вместо композитора +``` + +Теги **формально валидны** (заполнены, UTF-16), но **семантически мусорные**. Такие файлы +не ловятся ни `verdict`, ни проверкой на мойибаке. **Нужен отдельный аудит семантики `artist`** +перед тем, как библиотека пойдёт в Navidrome — иначе в списке артистов будут +«Классика в современной обработке». + +### 📦 Дополнение бэкапа: 1436 файлов не хватало (2026-09-27) + +**Задача Alex:** «дополни music/backup файлами которые в него не попали из music». + +**Скан (сравнение по относительному пути, `comm -23`):** + +``` +в backup уже есть: 7041 файлов +в основной библиотеке: 8421 файлов (не только mp3!) +НЕ ХВАТАЕТ: 1436 файлов +``` + +**Разбивка нехватки по расширениям:** + +| Расширение | Файлов | | +|---|---:|---| +| `mp3` | **876** | ← основное | +| `jpg` | 287 | обложки | +| `ini` | 65 | | +| `m3u` | 50 | плейлисты | +| `db` | 28 | | +| `nfo` | 22 | | +| `sfv` | 21 | | +| `gif` | 20 | | +| `.DS_Store` | 18 | мусор macOS | +| `url` | 8 | | +| `txt` | 8 | | +| `mpg` | **6** | видео в папке музыки | +| `directory` | 5 | | +| `avi` | **5** | видео в папке музыки | +| `jpeg` | 4 | | + +**Разбивка по верхним папкам:** +``` +!Pop, Club, Любэ 566 !Рэп 64 +!Rock&Folk 542 z Другое 55 +!A Not sorted 109 !Retro 52 +!Барды 36 !Классика 11 !Детские 1 +``` + +⚠️ **Решение Alex по спорным категориям (видео `.avi`/`.mpg`, `.DS_Store`) не принято** — +вопрос задан, копирование не запущено. + +**Скрипт сканирования:** `/tmp/bkfill_scan.sh` на NAS (чтение-только, списки в `/tmp/bkfill/`). +**Правило сравнения:** строго по **относительному пути** — в библиотеке есть **дубли имён +в разных папках**, сравнение по имени файла ловит оба. + ## Ремонт (предложен, НЕ выполнен) **Цель:** перекодировать ID3v2.3 → **UTF-16 с BOM** (или ID3v2.4 + UTF-8), чтобы Jellyfin читал.