Files
obsidian-vault/family/projects/media-toolbox-kraken.md
T

17 KiB
Raw Blame History

created, updated, status, tags
created updated status tags
2026-05-13 2026-05-14 in-progress
kraken
media
jellyfin
transmission
swift
project

Media Toolbox на Кракене

Цель: полноценный медиасервер на Кракене (RPi 5) — перенос библиотеки с HTPC, автосортировка через media-pipeline (Swift), Jellyfin, торренты.


Архитектура (целевая)

HTPC (Bazzite 192.168.1.86)
  └── rsync → Kraken HDD /srv/.../media/

Kraken (RPi 5, 192.168.1.14)
  ├── /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/media/
  │     ├── movies/          ← фильмы (127 папок)
  │     ├── cartoons/        ← мультфильмы (126 папок)
  │     ├── series/          ← сериалы (45 папок)
  │     ├── documentaries/   ← документальные (35 папок)
  │     └── downloads/complete ← Transmission
  ├── Docker: Transmission (128 торрентов, порт 9091)
  ├── Jellyfin native (порт 8096)
  └── Docker: media-pipeline:kraken (Swift CLI, arm64)

media-pipeline (~/Developer/media_files_db, ветка kraken-agent)
  ├── scan → resolve → apply (sync)
  ├── NFO-файлы для Jellyfin/Kodi
  ├── Transmission RPC для обновления путей
  └── unresolved.json — реестр нераспознанных

Текущий статус (2026-05-14, сессия 5)

Sync результаты (последний запуск — dry_run=false)

Категория Resolved Unresolved Статус
movies 2 (generation.p, Black Mirror dup) NFO пишутся
series 1 (Black Mirror — homonym) NFO пишутся
cartoons 6 в работе
documentaries 6 Tier 4 запускается
Итого 401 15 sync запущен

dry_run выключен (2026-05-14), запущен sync — NFO пишутся на диск.

Что работает

  • Docker образ media-pipeline:kraken задеплоен (ветка kraken-agent)
  • Фильмы: 127/127 NFO
  • Сериалы: все resolved (Black Mirror, Ну погоди!, и др. — через resolve-manual)
  • Кеш API-ответов: /config/cache, 30-дневный TTL
  • Transmission download-complete hook установлен
  • resolve-manual работает для movie/series/single-file

Открытые задачи

1. 🔴 [ОБЯЗАТЕЛЬНО К ИСПОЛНЕНИЮ] Довести media-pipeline до 0 unresolved без resolve-manual

Принцип: resolve-manual — не решение. Тул должен резолвить всё автоматически.
Текущее состояние: 32 unresolved после sync (dry_run=false). Разбивка:

Группа A — старые source-папки (scan подхватывает оригиналы после apply): apply создаёт canonical папки с симлинками, но оригинальные папки (flow.aka.straume..., bezumnyj_maks_3... и т.д.) остаются и при следующем scan снова попадают в unresolved. Это архитектурный баг.

  • Нужно: scanner должен пропускать папки, чьи файлы уже используются как цели симлинков в canonical структуре (или: хранить список resolved source-paths в unresolved.json и пропускать их при scan).

Группа B — мультики (tie/ambiguity): козленок, тигренок, нехочуха.xvid, чебурашка.m4v, котенок по имени гав.m4v, 25е - первый день, рики тики тави, приключения фунтика, незнайка, миграция

  • Причины: KP возвращает несколько кандидатов с одинаковым весом (tie), или IMDB/web search не находит по транслитерации.
  • Нужно: улучшить tie-breaking (год из папки/файла, popularity score из KP), расширить кириллические варианты запроса.

Группа C — документалки: bbc. the real jungle book bear 2012, bbc. секреты собак, penguin meet the family (2020), бегемоты - жизнь в воде, гиганты моря 2011, таинственная жизнь собак (hdtvrip 720p, 2013), тайная жизнь собак (2016г), prehistoric.planet.s02.1080p, жизнь птиц 1998, пингвины. шпион в толпе, супер белки (2018), шпион в снегах 2018

  • Tier 4 (IMDb scrape) запускается, но candidates = 0 — title matching слишком строгий для BBC-документалок.
  • Нужно: для documentaries/ добавить relaxed matching (убирать "bbc.", год, технические теги из запроса перед поиском).

5. 🔴 Торренты: Transmission не видит 271/293 файлов

Проблема: Transmission ищет файл по downloadDir/torrent_name. После pipeline apply файлы переименованы в canonical форму (Furiosa - A Mad Max Saga (2024)/Furiosa - A Mad Max Saga (2024).mkv), а торрент ожидает оригинальное имя (Furiosa.A.Mad.Max.Saga.2024.1080p....mkv) прямо в /media/movies/. Совпадений нет → haveValid=0 у 271 торрентов.

22 торрента с файлами — только те что в /downloads/complete (свежескачанные, pipeline ещё не обработал).

Нужно: реализовать torrent-fix subcommand: для каждого торрента искать файл по имени (case-insensitive fuzzy) в source директориях /media/movies/, /media/cartoons/ и т.д., и вызывать torrent-set-location RPC.

6. 🔴 Мультфильмы в library/movies (классификационный баг)

Проблема: library/cartoons = 0 items, library/movies = 202 items из которых 106 — мультфильмы (симлинки ведут в /media/cartoons/). Pipeline при apply не учитывает source directory для определения выходной категории — всё льётся в movies.

Примеры неправильно классифицированных: Despicable Me, Encanto, Luca, Умка, Чебурашка, Бременские музыканты, Ёжик в тумане, и ещё ~100 советских мультиков.

Нужно: в MediaFinalizer/apply логике использовать source dir (/media/cartoons/output.cartoons, /media/documentaries/output.documentaries) вместо TMDb genre для определения выходной папки.

  • Настроить библиотеки в Jellyfin (http://192.168.1.14:8096)
  • NFO файлы готовы (716 шт.), Jellyfin должен их подхватить

4. 🟢 Hermes cron на Кракене

  • Периодический запуск sync (новые загрузки через Transmission)

Принятые решения (архитектурные)

Решение Описание
Unresolved = last resort unresolved.json — НЕ мусорка. Это очередь для AI-агента (Tier 5), который по крону подбирает нераспознанные и разрешает их через LLM + web search. Для данной библиотеки цель: Tier 0-4 (TMDb → KP → IMDb scrape → web search) должны закрывать всё — в unresolved.json не должно попадать ни одного item'а из текущей библиотеки.
Web search enabled providers.webSearch.enabled=true в config.json. IMDb scrape как Tier 4 для всего, что не нашли TMDb/KP. Tier 4 должен срабатывать до того, как item уходит в unresolved.json
Документалки приоритет KP BBC/Discovery документалки плохо индексированы в TMDb. KP часто знает их под русскими названиями. Стратегия: сначала KP с русским названием из папки, потом IMDb
resolve-manual Только для экстренных случаев, не как регулярный процесс
Single-file NFO Для .mkv/.m4v файлов NFO создаётся рядом (film.nfo), не внутри

Исправленные баги

Баг 1: Двойной вызов binary (КРИТИЧЕСКИЙ)

docker run ... media-pipeline:kraken media-pipeline sync → бинарь получал media-pipeline как аргумент. Фикс: ENTRYPOINT ["media-pipeline"]

Баг 2: TitleSimilarity — симметричный Jaccard

encanto_2021_bdrip_by_dalemake vs Encanto: lengthRatio=0.2 → rejected. Фикс: Asymmetric scoring — candidate-coverage Jaccard когда query длиннее. Коммит 2704ce3

Баг 3: maxCallsPerRun = 8

8 API-вызовов → 192/200 items никогда не искались. Фикс: 8 → 500. Коммит 2704ce3

Баг 4: Series-гипотезы для одиночных файлов

Одиночные .avi/.mkv без S/E маркеров получали series-гипотезу → TMDb искал по /search/tv. Фикс: videos.count < 2 && !hasAnyEpisodeMarkers → return nil. Коммит 17c2ddc

Баг 5: HTTP кеш не персистился

cacheDirectory = /usr/local/bin/cache — удалялся при docker run --rm. Фикс: Autodetect /config mount → /config/cache. Коммит 5a1053c

Баг 7: Tier 4 (web search) не запускался для контента не в TMDb/KP

Проблема: MediaPlanner гейтил Tier 4 на hasLiveUnresolved() — но когда TMDb/KP возвращают 0 кандидатов, арбитр фаерит provider-not-found, который прунит все гипотезы. После этого hasLiveUnresolved=false → Tier 4 никогда не запускался.
Фикс:

  • MediaPlanner: Tier 4/5 теперь гейтятся на !hasWinner (нет .winning гипотезы), а не hasLiveUnresolved
  • ProviderSearchStrategy: добавлен флаг includePrunedHypotheses — когда true, поиск идёт и по .pruned ветками
  • WebSearchStrategy.webSearchDefaults: includePrunedHypotheses=true Коммит: 115f757

Баг 8: KP API URL смена домена (301 redirect)

api.kinopoisk.dev переехал на api.poiskkino.dev. Swift URLSession при редиректе теряет X-API-KEY заголовок → KP возвращает {"docs":[]} → кешируется как валидный пустой ответ → советские мультики и BBC не резолвились неделями. Фикс: (1) обновлён URL в KinopoiskAPI.swift; (2) HTTPClient.fetch получил shouldCache: ((Data) -> Bool)? — KP не кеширует ответы с пустым docs.

Баг 9: Leet-speak в именах файлов

ni4ego_horoshego, o_4em_govoryat_muzh4iny — цифра 4 = ч в русском warez-транслите. Стандартная транслитерация не покрывает. Фикс: String.decodeLeetSpeak() в StringExtensions.swift + дополнительный variant в NameTokenization.variants.

Баг 6: resolve-manual NFO path для single-файлов

resolve-manual писал NFO внутрь файла вместо рядом. Фикс: Detect isDirectory, для файлов → deletingPathExtension().appendingPathExtension("nfo"). Коммит c0fdc59


Конфиг на Кракене

/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker/media-pipeline/
├── config.json          ← TMDb/KP ключи, Transmission RPC, directories
├── unresolved.json      ← реестр нераспознанных (создаётся автоматически)
├── cache/               ← HTTP кеш 30 дней
└── on-download-complete.sh

Запуск sync:

docker run --rm \
  -v /srv/.../media:/media \
  -v /srv/.../docker/media-pipeline:/config \
  media-pipeline:kraken \
  sync --config /config/config.json

Force-resolve одного item:

docker run --rm ... media-pipeline:kraken \
  resolve-manual --config /config/config.json \
  --media-path '/media/cartoons/bremenskie.muzykanty' \
  --tmdb 14327

Технические детали

HTPC bazzite@192.168.1.86, Data: /run/media/bazzite/Data/, WoL: B0:6E:BF:60:6D:64
Кракен kraken@192.168.1.14, HDD: /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/
Jellyfin http://192.168.1.14:8096
Transmission http://192.168.1.14:9091
Исходники ~/Developer/media_files_db/, ветка kraken-agent
Docker образ media-pipeline:kraken (arm64, Colima 24GB)
kraken-ssh ssh kraken-ssh → 10.99.1.2:22 через WireGuard (обновлено 2026-05-14)

Источник торрентов (важно)

Торренты на Кракене (128 шт.) импортированы из Windows Transmission-daemon на HTPC:

/run/media/bazzite/Windows/windows/serviceprofiles/localservice/appdata/local/transmission-daemon/
  ├── torrents/   ← 210 .torrent файлов
  └── resume/     ← 214 resume (пути, статус)

Валидация resume (2026-05-14): 185/214 файлов есть на HTPC. 29 missing:

  • ~15 медиафайлов с утраченного диска X:/Movies/ — потеряны безвозвратно
  • ~14 игр/архивов из Downloads/Unsorted/ — не медиа, не важно

Отдельно: uTorrent (/run/media/bazzite/Windows/program files/utorrent/) — 131 .torrent файл, resume.dat с 18 записями. Из них только 6 хешей совпадают с Кракеном.

Karnavalnaya.noch.1956.BDRip.AVC.mkv — есть в uTorrent и в Transmission на Кракене (downloaded=0). Файла нет нигде — никогда не скачивался.

Журнал

  • 2026-05-13 сессия 1: HTPC разбужен, rsync запущен (~1.3TB), торрент-база импортирована (128 торрентов из Windows Transmission-daemon)
  • 2026-05-13 сессия 2: Docker build arm64, deploy на Кракен, first sync
  • 2026-05-13 сессия 3: kraken-agent ветка: UnresolvedStore, resolve-manual, agent, torrent-fix subcommands
  • 2026-05-14 сессия 4: 5 системных багов исправлены. Sync: 222/317 resolved (70%).
  • 2026-05-14 сессия 5: resolve-manual для 13 items. unresolved: 24 → 8. NFO path bug fix. kraken-ssh → WireGuard.
  • 2026-05-14 сессия 6: dry_run=false, sync запущен → 401 resolved, 32 unresolved. apply создаёт canonical папки + симлинки (оригиналы не трогает). 716 NFO написано. Валидация торрентов HTPC.
  • 2026-05-15 сессия 7: Торренты: 467 скопированы с HTPC, 323 добавлены в Transmission (294 итого после удаления 50 игр/нон-медиа). rsync: movies + мультфильмы + BBC документалки. Фиксы в коде: (1) best-effort collapse при исчерпании tierов, (2) дедупликация dir+file регионов в RegionPartitioner, (3) strip .aka./full.screen из TitleParser, (4) scanner пропускает canonical dirs по маркеру .media-pipeline-canonical, (5) Roman numerals в транслитерации (Ампир V). Финал: 19 unresolved.
  • 2026-05-16 сессия 8: Обнаружен корневой баг: KP API переехал api.kinopoisk.devapi.poiskkino.dev (301 redirect, Swift теряет X-API-KEY). Исправлен URL. Удалены 359 невалидных KP-кеш записей. Добавлен leet-speak decode (4ch: ni4ego→nichego, muzh4iny→muzhchiny). Починен кеш: KP пустые docs:[] больше не кешируются (были причиной повторных промахов после rate-limit/redirect). Текущий unresolved: 22. Завтра KP лимит сбросится → ожидаем ≤5.