Files
obsidian-vault/personal/tech/jellyfin-music-library-pitfalls.md

8.5 KiB
Executable File
Raw Permalink Blame History

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:

Ключевые правила (краткая версия)

🔴 RULE 0 — бэкап БД ДО создания библиотеки

Создание библиотеки + скан пишет тысячи строк в BaseItems. Без бэкапа БД откат невозможен.

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).

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»

Обход без правки тегов:

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 реальных файлов, прежде чем строить версии про внешние базы.

Связанные заметки