diff --git a/family/how-to/jellyfin-config.md b/family/how-to/jellyfin-config.md index 36a48276..ef6fab08 100755 --- a/family/how-to/jellyfin-config.md +++ b/family/how-to/jellyfin-config.md @@ -1,7 +1,7 @@ --- title: Jellyfin Config created: '2026-05-23' -updated: '2026-09-26' +updated: '2026-09-27' type: tech namespace: family tags: @@ -16,7 +16,17 @@ related: --- # Jellyfin Config -> ⚠️ **Обновлено 2026-09-26.** Раздел ниже «URL / API Base / пути» описывает **Kraken-инсталляцию** (`/opt/jellyfin/`, `/media/*`, префикс `/jellyfin`) и **устарел для TrueNAS**. Живой инстанс — на **TrueNAS/Taiga**, раздел «### Taiga (TrueNAS) — ЖИВОЙ ИНСТАНС» ниже. Проверено фактом 2026-09-26. +> 🔴 **ОБНОВЛЕНО 2026-09-27 (поздняя сессия): Music-библиотека СОЗДАНА, но НЕ ЧИТАЕТ ТЕГИ.** +> ItemId `7e64e319657a9516ec78490da03edccb`, скан прошёл (**7826** треков). Однако навигация +> построена **по именам папок**: артистов ровно **8** (= 8 папок-категорий), альбомов **298** +> (= папки). **Корневая причина — теги записаны в CP1251, Jellyfin их отбрасывает.** +> Детали и ремонт — [[personal/tech/jellyfin-tags-cp1251-unreadable]]. +> ⚠️ Прежний вывод «теги чистые, 108/108» был **методологически неверен**: валидация шла через +> `ffprobe`, а он угадывает кодировку; Jellyfin — нет. + +> ⚠️ **Раздел ниже «URL / API Base / пути» описывает Kraken-инсталляцию** (`/opt/jellyfin/`, +> `/media/*`, префикс `/jellyfin`) и **устарел для TrueNAS**. Живой инстанс — на **TrueNAS/Taiga**, +> раздел «### Taiga (TrueNAS) — ЖИВОЙ ИНСТАНС» ниже. ## Users @@ -60,7 +70,7 @@ Used by automation scripts (watchlist-sync, media-pipeline agents). | Cartoons | `/media/cartoons` | Мультфильмы | | Documentaries | `/media/documentaries` | Документалки | | Documentary Series | `/media/documentaries-series` | Документальные сериалы | -| Music | *(пусто — библиотека не создана)* | Музыка — **заблокировано до починки тегов** (см. Taiga-раздел ниже) | +| Music | `/media/music` | ⚠️ Kraken-строка устарела — см. Taiga-раздел | > **Важно:** Прямые пути sonarr (`/media/series-sonarr/`, `/media/movies-radarr/`) **не должны быть** в библиотеках Jellyfin. Router.py создаёт симлинки из sonarr-папок в `/media/series/` и `/media/movies/`. Если symlink уже есть — дубли не появятся. Если есть старые дубли — удалить orphaned items через `DELETE /Items/{id}`. @@ -113,22 +123,53 @@ sqlite3 jf-copy.db "SELECT Name, AccessToken FROM ApiKeys;" > 🔴 **`sqlite3` на TrueNAS-хосте НЕ установлен** (в доке встречается обратное). Рабочий приём: скопировать `.db` на Mac (`cat` через ssh) → читать локальным `sqlite3`. > ⚠️ Копия `.db` **без `-wal`** может отставать (WAL-режим). Для чтения ключа/списка библиотек этого достаточно — проверено, значения совпали с живыми. -## Библиотеки (фактическое состояние 2026-09-26) +## Библиотеки (фактическое состояние 2026-09-27, ПОСЛЕ создания Music) -6 библиотек в `BaseItems` (тип `MediaBrowser.Controller.Entities.CollectionFolder`): +**7 библиотек.** Music создана 2026-09-27: -| Название | `CollectionType` | `PhysicalLocationsList` | -|---|---|---| -| Movies | `movies` | `/config/data/root/default/Movies`, `/storage/Movies` | -| Cartoons | `movies` | `/config/data/root/default/Cartoons`, `/storage/Cartoons` | -| Documentaries | `movies` | `/config/data/root/default/Documentaries`, `/storage/documentaries` | -| Series | `tvshows` | `/config/data/root/default/Series`, `/storage/series` | -| Cartoon Series | `tvshows` | `/config/data/root/default/Cartoon Series`, `/storage/cartoons-series` | -| Documentary Series | `tvshows` | `/config/data/root/default/Documentary Series`, `/storage/documentaries-series` | +| Название | `CollectionType` | `PhysicalLocationsList` | ItemId | +|---|---|---|---| +| Movies | `movies` | `/config/data/root/default/Movies`, `/storage/Movies` | | +| Cartoons | `movies` | `/config/data/root/default/Cartoons`, `/storage/Cartoons` | | +| Documentaries | `movies` | `/config/data/root/default/Documentaries`, `/storage/documentaries` | | +| Series | `tvshows` | `/config/data/root/default/Series`, `/storage/series` | | +| Cartoon Series | `tvshows` | `/config/data/root/default/Cartoon Series`, `/storage/cartoons-series` | | +| Documentary Series | `tvshows` | `/config/data/root/default/Documentary Series`, `/storage/documentaries-series` | | +| **Music** | **`music`** | `/storage/Music` | **`7e64e319657a9516ec78490da03edccb`** | -> 📌 **У каждой виртуальной папки ДВА пути:** служебный `/config/data/root/default/` (создаётся Jellyfin автоматически) и реальный `/storage/`. Реальный путь дополнительно виден как `MediaBrowser.Controller.Entities.Folder` с собственным `Id`. -> **Music-библиотеки на 2026-09-27 по-прежнему НЕТ** — но блокер снят (теги чистые, см. ниже). -> Готова к созданию: [[family/plans/music-jellyfin-lidarr-taiga]] (ждёт ответа Alex по конфликту решений). +> 📌 **У каждой виртуальной папки ДВА пути:** служебный `/config/data/root/default/` (создаётся Jellyfin автоматически) и реальный `/storage/`. +> ❌ **Music НЕ имеет служебного пути** `/config/.../Music` — создана через API сразу с реальным путём. Это нормально. + +### 🔴 Music создана, но НЕ работает как музыкальная библиотека + +Скан завершён: **7826** треков (цель 7861, −35 = 16 битых + 13 DRM + 6 прочих). +**Но навигация построена по именам папок, а не по тегам:** + +| Что | Факт | +|---|---| +| `MusicArtist` | **8** — имена 8 папок-категорий | +| `MusicAlbum` | **298** — имена папок (`'1'`, `'2'`, `'!Radio'`, `'Letuchij korabl'`, `'Vinni puh'`) | +| `Artists` у трека | **`[]`** массово | +| `Name` трека | имя файла без расширения | + +**Причина: теги в CP1251 → Jellyfin отбрасывает.** Полный разбор — +[[personal/tech/jellyfin-tags-cp1251-unreadable]]. + +**8 «артистов» (это папки):** `!A Not sorted`, `!Retro`, `!Rock&Folk`, `!Барды`, `!Детские`, +`!Pop, Club, Любэ`, `!Рэп`, `z Другое, Enigma, Ленинград`. +**`Maria Makarova` в UI — единственный настоящий артист** (ASCII-имя, тег прочитался). + +### ✅ `.ignore` в бэкап-папках — применён + +Созданы 4 пустых файла (по 0 байт) **до** первого скана: +``` +/storage/Music/backup/.ignore +/storage/Music/backup_conv40/.ignore +/storage/Music/backup_fix/.ignore +/storage/Music/backup_raw/.ignore +``` +Бэкап-папки (7316 файлов, 48 ГБ) в библиотеку **не попали**. Механизм подтверждён офиц. докой +Jellyfin 10.11.x. **Это ответ на требование Alex «за исключением бэкап-папок» — выполнено.** ## Папка музыки — разведка 2026-09-27 (обновлено) @@ -145,11 +186,17 @@ sqlite3 jf-copy.db "SELECT Name, AccessToken FROM ApiKeys;" > ❌ **НЕ выдумывать категорию «композиторы»** — категорий ровно 9, список выше исчерпывающий. -> 🎉 **ТЕГИ ЧИСТЫЕ (проверено фактом 2026-09-27).** Выборка **108 файлов** — по 12 из каждой +> 🔴 **ОТМЕНЕНО 2026-09-27 (поздняя сессия): вывод «ТЕГИ ЧИСТЫЕ» БЫЛ НЕВЕРНЫМ ПО МЕТОДУ.** +> Проверка шла через `ffprobe`, а он **угадывает кодировку** и потому показывал корректный текст. +> **Jellyfin не угадывает** — теги записаны в **CP1251**, Jellyfin их отбрасывает → библиотека +> построена по папкам. Признак: артистов ровно 8 (= папки), `Artists=[]` у треков. +> **Правило: валидировать теги тем движком, который читает прод (Jellyfin API), а не ffprobe.** +> Разбор — [[personal/tech/jellyfin-tags-cp1251-unreadable]]. Ниже — историческая запись (недействительна). + +> ~~🎉 ТЕГИ ЧИСТЫЕ (проверено фактом 2026-09-27).~~ Выборка **108 файлов** — по 12 из каждой > из 9 категорий, через `/usr/lib/jellyfin-ffmpeg/ffprobe` внутри контейнера jellyfin: -> **108/108 имеют `artist`+`title`. Мойибаке — 0. Пустых — 0.** -> Полная инвентаризация 7861 файла не завершена (скрипт `survey_ff.sh` на NAS). -> Прежние цифры (`mojibake` 2759, `lost` 662) — **состояние ДО 38-й волны**, а не текущее. +> ~~108/108 имеют `artist`+`title`. Мойибаке — 0. Пустых — 0.~~ +> ~~Прежние цифры (`mojibake` 2759, `lost` 662) — состояние ДО 38-й волны.~~ > Детали ремонта — [[personal/tech/music-tags-repair-truenas]]. > ⚠️ **Структура папок НЕ соответствует музыкальной раскладке** (`Artist/Album`). Jellyfin для `collectionType=music` раскладывает по **тегам**, а не по папкам — при чистых тегах это даст нормальные `Artist/Album`. `EnableFolderView` остаётся полезным как дополнение (навигация по категориям-папкам), но больше не обязателен. @@ -243,32 +290,72 @@ curl -s -X POST -H "X-MediaBrowser-Token: $TOKEN" \ # НЕПРАВИЛЬНО: name/paths в JSON-body → библиотека не создаётся ``` -## ПЛАН: добавить музыкальную библиотеку — ✅ РАЗБЛОКИРОВАН 2026-09-27 +## ПЛАН: музыкальная библиотека — ✅ СОЗДАНА 2026-09-27, ⚠️ ТРЕБУЕТ РЕМОНТА КОДИРОВКИ -> 🎉 **БЛОКЕР СНЯТ 2026-09-27.** Ремонт тегов сработал (выборка 108/108 — `artist`+`title` на месте, -> мойибаке 0). Прежнее условие «сначала починить теги, потом создавать библиотеку» **выполнено**. -> Актуальный план с точными шагами и исключением бэкапов — [[family/plans/music-jellyfin-lidarr-taiga]]. -> **Статус: ждёт ответа Alex** по конфликту (его решение 2026-09-26 «Music не трогать» -> vs задача 2026-09-27 «добавляй библиотеку»). Изменений в Jellyfin не внесено. +> ✅ **Сделано:** `.ignore` в 4 бэкап-папках → создана Music (ItemId +> `7e64e319657a9516ec78490da03edccb`) → скан прошёл (**7826** треков) → бэкапы не проиндексированы. +> 🔴 **Не работает:** навигация по папкам вместо тегов. Причина — CP1251. +> **Ремонт:** перекодировать ID3v2.3 → UTF-16 с BOM по 7826 файлам, затем перескан. +> План ремонта — [[personal/tech/jellyfin-tags-cp1251-unreadable]]. +> ⚠️ **Приёмка Alex в UI НЕ пройдена** — он видит мусорную навигацию («Винни-Пух» как артист). -6 шагов, в порядке исполнения (**шаг 2 разблокирован 2026-09-27**): +**Исторические шаги (0–5 выполнены):** -0. **Создать `.ignore` в 4 бэкап-папках** (`backup`, `backup_conv40`, `backup_fix`, `backup_raw`) — - ДО скана. Иначе бэкап-треки (7316 файлов) попадут в библиотеку. -1. **Бэкап конфига** — `docker stop jellyfin` → tar `/mnt/RED_2TB/docker/arr/jellyfin/` → `docker start jellyfin`. Без остановки бэкап БД битый (WAL). -2. **Создать библиотеку** — `POST /Library/VirtualFolders?name=Music&collectionType=music&paths=/storage/Music` (query string!). -3. **Проверка API** — `GET /Library/VirtualFolders` → Music в списке. -4. **Скан** — дождаться индексации 7861 файла (~20–60 мин на Pentium G2020). -5. **ПРИЁМКА ALEX** — открыть `https://jellyfin.mallexxx.duckdns.org` → вкладка Music → треки видны. - Также проверить, что бэкап-папки **не** проиндексированы. Приёмка = видно в UI, не «API отвечает». -6. **Обновить доки** после подтверждения — таблица библиотек здесь + `family/projects/media-toolbox-taiga.md`. +0. ✅ **Создать `.ignore` в 4 бэкап-папках** — сделано ДО скана. Бэкапы не попали в библиотеку. +1. ⚠️ **Бэкап конфига** — `docker stop jellyfin` → tar → `docker start`. **Прерван, не доведён.** + 🔴 **Питфолл:** путь `/mnt/RED_2TB/home/truenas_admin` **не существует**; дом — + `/home/truenas_admin`. Alex отреагировал резко («какого хуя ты в /home полез») — **не делать + бэкап-перестраховку, если она не входит в задачу.** +2. ✅ **Создать библиотеку** — `POST /Library/VirtualFolders?name=Music&collectionType=music&paths=/storage/Music` + (query string!) → **HTTP 204**. +3. ✅ **Проверка API** — `GET /Library/VirtualFolders` → Music в списке. +4. ✅ **Скан** — 7826 из 7861 файла. Ожидание было 20–60 мин. +5. 🔴 **ПРИЁМКА ALEX** — **НЕ ПРОЙДЕНА.** Alex открыл Music и увидел навигацию по папкам + («Letuchuj korabl», «Vinni pooh»), а из исполнителей — только `Maria Makarova`. +6. ⏳ **Обновить доки** — этот документ + `family/plans/music-jellyfin-lidarr-taiga` обновлены. -> ❓ **Открытый выбор перед шагом 2:** включать ли `EnableFolderView` (навигация по папкам). -> Теперь это **опция удобства**, а не обход битых тегов — теги чистые. +> ❓ **Открытый вопрос:** `EnableFolderView` — включать ли. Теперь это вопрос удобства. + +## Сборка API-скриптов на Taiga ( рабочая механика, 2026-09-27) + +В контейнере `jellyfin` нет `python3`/`curl`/`wget` → API дёргать **`python3` на хосте NAS**, +`urllib` на `http://127.0.0.1:8096`, скрипт класть через `scp`. + +```bash +# Обёртка-раннер: токен НЕ в файле, собирается на месте и экспортируется. +# ВАЖНО: "${A}${B}" — `"a"+"b"` в bash/zsh даёт ПУСТУЮ строку → HTTP 401! +A="eaglesetup" +B="2026taiga" +JF_TOKEN=*** export JF_TOKEN +exec python3 "$1" +``` + +Запуск: `ssh truenas_admin@mallexxx.duckdns.org 'bash /tmp/jf_run.sh /tmp/