Отдельный инструмент для входной сортировки видео (inbox → Сериалы / Фильмы / _SortReview), с русскими именами через TMDB, Blu-ray remux и отчётами CSV/TXT.
SeriesToolkit (стабильная линия 0.2.2) остаётся продуктом нормализации уже разложенных библиотек сериалов. Этот пакет — расширяемый конвейер «до библиотеки»; дальнейшая полировка имён эпизодов — отдельным запуском SeriesToolkit по целевым папкам.
- Репозиторий
Script_Rename_ALLVideo: рядом с каталогомMediaInboxToolkitв корне лежитFetch-VideoMetadata.ps1. - Для TMDB: переменная окружения
TMDB_API_KEY(или см.Fetch-VideoMetadata.ps1).
cd <корень репозитория>\MediaInboxToolkit
powershell -NoProfile -ExecutionPolicy Bypass -File .\MediaInboxToolkit.ps1 -UseTmdb -DryRunМинимальный GUI (WinForms):
powershell -NoProfile -ExecutionPolicy Bypass -File .\Start-MediaInboxToolkitGui.ps1Политика по умолчанию: .\sort-inbox.example.json (нейтральные пути). Пример разнесённой библиотеки с папками «Сериалы / Фильмы / Аниме / …»: .\sort-inbox.library-layout-advanced.example.json — скопируйте и замените nasShareRoot на свой UNC; лишние ключи в destinations можно удалить. При -Apply и folders.createDestinationRootsOnApply: true целевые корни из политики создаются, если их ещё нет.
Ни один скрипт не требует персонального UNC. Используйте один из вариантов:
- Сетевой NAS/SMB:
\\NAS\media\Video\Sort - Локальный диск:
D:\Media\Video\Sort - Внешний диск:
E:\Video\Sort
Для оркестрационных скриптов можно не передавать -SortRoot/-InboxPath, а задать переменную окружения:
$env:MIT_INBOX_ROOT = 'D:\Media\Video\Sort'Локальный layout-конфиг для спецвыпусков: скопируйте media-library-layout.local.example.json в media-library-layout.local.json и заполните своими путями. Этот файл не должен попадать в git.
После проверки CSV в LOGS\: добавьте -Apply.
powershell -NoProfile -ExecutionPolicy Bypass -File .\MediaInboxToolkit.Orchestrate.ps1 `
-InboxPath '\\NAS\share\Video\Sort' -UseTmdb -DryRunС -Apply и -RunSeriesToolkitAfter вторым шагом вызывается SeriesToolkit\SeriesToolkit.Engine.ps1. Корни можно задать вручную (-SeriesToolkitRoots) и/или взять из последнего sort-inbox-*.csv шага 1: -SeriesToolkitRootsFromLastCsv (или явный -SeriesToolkitCsvPath).
Из корня монорепо при настроенном remote media-inbox (ваш standalone-репозиторий MediaInboxToolkit) :
powershell -NoProfile -ExecutionPolicy Bypass -File .\MediaInboxToolkit\Publish-MediaInboxStandalone.ps1 -ForceWithLease-ForceWithLease нужен, если на GitHub в main уже есть коммиты вне текущего subtree (типично после ручных правок).
После успешного push скрипт создаёт и отправляет тег v<version> из version.json, если такого тега ещё нет на media-inbox. На GitHub срабатывает workflow Release (.github/workflows/release.yml): оформленное описание из CHANGELOG.md + ZIP с дистрибутивом и SHA-256.
MediaInboxToolkit раскладывает файлы по структуре; SeriesToolkit (стабильная линия 0.2.2) полирует имена эпизодов уже в целевых папках. Общий модуль метаданных — Fetch-VideoMetadata.ps1.
Для ручной партии или узкого инбокса без полного MIT/ffprobe:
cd <repo>\MediaInboxToolkit\Scripts
# sort-rename.batch.example.json → sort-rename.local.json (sortRoot, списки фильмов/сериалов)
powershell -NoProfile -ExecutionPolicy Bypass -File .\Apply-SortRussianRename.ps1 -ConfigPath .\sort-rename.local.json -Apply
powershell -NoProfile -ExecutionPolicy Bypass -File .\Update-SortEpisodeRuTitles.ps1 -SortRoot '\\NAS\share\Video\Sort' -ApplyПосле ошибочного SeriesToolkit или дублей сезонов:
powershell -NoProfile -ExecutionPolicy Bypass -File .\Repair-SortInboxLayout.ps1 -Apply
powershell -NoProfile -ExecutionPolicy Bypass -File .\Sync-SortEpisodeTitlesFromTmdb.ps1 -Apply
powershell -NoProfile -ExecutionPolicy Bypass -File .\Export-SortInboxAudit.ps1Пример политики раскладки в основную библиотеку TNAS: sort-inbox.emilian-tnas.example.json. Конвейер NAS + qBittorrent: docs/TERRAMASTER-QBIT-PIPELINE.md.
Если в каталоге шоу лежат отдельные файлы без SxxEyy (только название выпуска), их можно разнести по подпапкам Сезон N и переименовать по данным TMDB:
- Скрипт:
Scripts/Resolve-LooseCartoonEpisodesFromTmdb.ps1 - Конфиг UTF-8:
Scripts/Resolve-LooseCartoonEpisodesFromTmdb.config.json(cartoonsRoot, список шоу сtvId, опциональноtorrentScanRootsи блокqbittorrent) - Ключ TMDB:
TMDB_API_KEY(или см.Fetch-VideoMetadata.ps1)
Проверяйте tvId на themoviedb.org. Пример: Robot Chicken — 709; число 1433 там — American Dad!, для «Робоцыпа» оно не подходит.
Пример из корня монорепозитория:
powershell -NoProfile -ExecutionPolicy Bypass -File .\MediaInboxToolkit\Scripts\Resolve-LooseCartoonEpisodesFromTmdb.ps1 -WhatIfУберите -WhatIf, когда результат устраивает.
destinations— любые именованные корни (не толькоseries/cartoons/movies/review): напримерanimeSeries,animeMovies; пути относительноnasShareRoot.destinationsByKind— карта вида контента (MediaInboxToolkit.ContentKinds.ps1) → имя ключа изdestinations.destinationsByKindMinConfidence— минимальная уверенность эвристики (0–100), иначе используется прежняя логика (preferCartoonsSubfolder/ сериал vs фильм).safety—requireSourceUnderInbox,skipSourceIfUnderLibrary+libraryRootRelatives, чтобы не трогать файлы уже в библиотеке.tmdbKindRefinement— уточнение «аниме vs мульт» по TMDB (жанр Animation + регион).folders.createDestinationRootsOnApply— перед переносом создать все каталоги изdestinations, если отсутствуют.classification—folderSeasonContext(папкаSeason N/N season+ файлNN.; опциональноorphanSeasonFolderSeriesMapдля одиночной папки сезона без родителя-шоу),tvSpecialFilenameBoost(Robot Chicken Star Wars Episode I→TV),movies.allowMissingYearIfTmdbMatched,cartoonMovieBasenameRegexes(массив regex по имени файла: при совпадении и эвристике «фильм» вид контента принудительноcartoon_movie→destinationsByKind.cartoon_movie, до TMDB; узкие шаблоны, чтобы не задеть живые фильмы).seriesQueryRewrites— до поиска TMDB: массив{ "pattern": "<regex>", "seriesGuess": "<строка для поиска TMDB>", "matchField": "<опционально>" }; правила идут по порядку, при совпадении текущийSeriesGuessподменяется значением поляseriesGuess, затем применяется следующее правило.matchField(по умолчаниюseriesGuess):basename— regex к stem имени файла (без расширения);relativePath— к пути файла относительно инбокса (\);seriesGuessOrBasename— сначалаSeriesGuess, иначе stem. Примеры: Wednesday / Peacemaker из basename, Invincible.2021 в имени файла→Invincible, китайский заголовок папки только вSeriesGuess, путь с «Подозрительная сова»→точное имя шоу.seriesFolderByTmdbTvId— после матча TMDB: объект"<tmdb tv id>": "Имя папки"переопределяетSeriesFolder(например Invincible 95557→Непобедимый); в CSV в заметках появитсяfolder_tv_id_policy.
- docs/FIX-PLAN-SORT-CLASSIFICATION-202605.md — план исправлений после in-place (movies/series, кириллица, RC/Archer, веб→TMDB id).
- docs/SORT-INBOX-PLAN.md — структура NAS, фазы, параметры политики.
- docs/TERRAMASTER-QBIT-PIPELINE.md — TerraMaster, qBittorrent, Sort → Фильмы/Сериалы/Аниме.
- docs/CLASSIFICATION-ROADMAP.md — типы контента 2.x и план сигналов.
- docs/OFFLINE-METADATA.md — постер и описание рядом с медиа.
- docs/INSPIRATION-SERIESTOOLKIT.md — что перенимаем из SeriesToolkit.
- docs/GUI-EXE-ROADMAP.md — GUI и сборка EXE.
MediaInboxToolkit теперь содержит каркас Toolkits/:
Toolkits/SeriesToolkit/— legacy-слот для поэтапной интеграции существующего SeriesToolkit;Toolkits/VideoMetaToolkit/— отдельный слот под новый модуль описаний/постеров/актёров (VideoMetaToolkit.ps1— заготовка launcher).
Текущие рабочие скрипты пока остаются на прежних путях; перенос кода выполняется постепенно.
version.json,CHANGELOG.md,Bump-Version.ps1— как в SeriesToolkit.- Ветка Git:
master.
По умолчанию .\LOGS\ (каталог в .gitignore). Для полного текстового транскрипта прогона (включая ошибки TMDB в консоли) и блока POST-RUN SUMMARY в конце файла: .\Run-DryRunTranscript-Example.ps1 (параметры -InboxPath / -PolicyPath при необходимости).
Разложение только внутри Sort (подкаталог Sort\_Workspace\…, затем SeriesToolkit по сериалам): .\Organize-SortInPlace.ps1 и политика sort-inbox.workspace-inside-sort.json (scope.excludeDirectoryNames: _Workspace). Под _Workspace в политике используются ASCII-имена (series, movies, …), чтобы лаунчер не ломался на кодировке консоли; русские имена шоу/эпизодов задаёт TMDB.
Тот же сценарий, но папка Video вместо _Workspace: политика sort-inbox.video-under-sort.example.json (исключение сканирования: Video). В folders заданы skeletonProfile: ascii, workspaceSeriesToolkitSubfolders и skeletonExtraRelatives — дополнительные пустые каталоги (документалистика, концерты и т.д.); их создаёт .\New-MediaInboxDestinationSkeleton.ps1 (движок сортировки их не использует, пока не добавите ключи в destinations / destinationsByKind). Доп. вариант скелета — зонт «Время приключений» (один корень и три подшоу: Финн и Джейк / Далёкие земли / Фионна и Кейк): готовый массив skeletonExtraRelatives в sort-inbox.skeleton-extras-adventure-time-umbrella.example.json (ветка под …\Video\cartoons\…); для кириллических корней библиотеки — sort-inbox.skeleton-extras-adventure-time-umbrella.cyrillic.example.json (…\Video\Мультсериалы\…). Скопируйте элементы в folders.skeletonExtraRelatives своего sort-inbox.*.local.json. Кириллический обезличенный вариант тех же правил: sort-inbox.video-under-sort.cyrillic.example.json (nasShareRoot в примере нейтральный — скопируйте в sort-inbox.*.local.json и пропишите свой UNC). Этап «скелет + DryRun»: .\Invoke-MediaInboxSortStage1.ps1 или -SkeletonProfile Cyrillic; ожидание нового CSV после долгого DryRun: .\Watch-MediaInboxToolkitCsv.ps1. Перенос: .\Invoke-MediaInboxSortStage3Apply.ps1 (введите YES; -Force без паузы). Полный in-place + SeriesToolkit: .\Organize-SortVideoUnderSort.ps1 (имена подпапок под Sort\Video берутся из политики). GUI: пресет политики + кнопка «Создать скелет». Локальные пути — sort-inbox.<имя>.local.json (в .gitignore).
- DryRun →
sort-inbox-*.csv .\New-MediaInboxReviewCsv.ps1 -CsvPath <csv>→*.review.csv(колонкиHumanOverride/HumanComment/HumanDestOverrideуже пустые). По умолчанию APPLY только приConfidence >= 70. Для сериалов с уже собранным путём вDestFullPath(фрагмент- SxxEyy -) дополнительно разрешается APPLY приConfidence >= 55(параметры-ApplyMinConfidence/-SeriesEpisodeStructuredMinConfidence,0отключает льготу для сериалов)..\Update-MediaInboxReviewCsvAutoDecide.ps1 -CsvPath <review.csv> -TorrentDirectory "C:\Users\<user>\Downloads"→*.auto.csv
Логика торрентов: совпадениеrutracker-…в пути и в имени.torrent; разбор метаданных.torrent(имена файлов внутри раздачи) — если имя видеофайла в CSV встречается ровно в одной локальной раздаче, применяется эта раздача (в т.ч. номер темы из имени.torrent, без id в пути). При одинаковом счёте совпадения слов у нескольких раздач: совпадение имени файла с листом в.torrent, затем SxxEyy / Exx в именах файлов раздачи, затем topic id в пути; при двух кандидатах и совпадении mit_dur_s из CSV с ffprobe по файлу — предпочтение раздаче с одним видео-листом.
Опционально qBittorrent Web UI (если полный путьSourceFullPathв CSV совпадает с путём, который отдаёт клиент вsave_path+ файлы раздачи): тот же базовый URL, что в браузере, без завершающего слэша, напримерhttps://хост:порт/qbittorrent. Если логина нет — учётку не указывайте; при самоподписанном HTTPS:-QbittorrentSkipCertificateCheck. Переменные:MIT_QBIT_WEBUI, при необходимостиMIT_QBIT_USER/MIT_QBIT_PASS.
Если qBittorrent качает в один UNC (например\\NAS\qBittorrent\...\downloads), а в CSV уже пути после переноса в сортировку (\\NAS\media\Video\Sort\...), задайте пару префиксов:-QbittorrentCsvSourcePrefix(корень, как в CSV) и-QbittorrentDownloadRootPrefix(корень каталога загрузок qBittorrent). Относительный хвост пути тогда подставляется под каталог загрузок для поиска в индексе API. То же черезMIT_QBIT_CSV_PREFIXиMIT_QBIT_DOWNLOAD_ROOT. Либо блокqbittorrentвmedia-library-layout.local.json(webUiUrl,csvSourcePrefix,downloadRootPrefix) — подхватывается, если параметры и env пустые. У других пользователей клиент не обязателен — достаточно папки с.torrent. Спецвыпуски (без SxxEyy в имени файла):media-library-layout.example.json→media-library-layout.local.json(в.gitignore). Если лежит рядом со скриптом и не заданы-MediaLibraryLayoutJson/MIT_MEDIA_LIBRARY_JSON, он подхватывается сам. В JSON:videoLibraryRoot(UNC доVideo),scanRoots(подкаталоги с сериалами: Мультсериалы, Сериалы, Анимесериалы и т.д.). Иначе корень:MIT_VIDEO_LIBRARY_ROOTили-MediaLibraryVideoRoot. При запуске строится индекс подпапок; для строкREVIEWбез эпизода срабатываютexplicitRules(regex имени файла + имени папки +libraryRoot). Для Анимесериалов при совпадении сovaFilenameRegexпуть ведёт в подпапкуovaSubfolderName(напримерOVA). Опциональный fuzzy поNotes(fuzzyEnabled,fuzzyUniqueMinScore) — только один явный победитель. Отключить весь блок «плоско в корень сериала»:-SkipCartoonSeriesRootFlat. В консоли смотритеMediaLibraryRootиSeriesIndexEntries(должно быть > 0, если NAS доступен)..\Prepare-MediaInboxReviewForHuman.ps1 -CsvPath <*.auto.csv>→*.for-human.csv+*.for-human.html
Откройте HTML в браузере: цветные блоки REVIEW (жёлтый) / APPLY (зелёный) / SKIP (серый), таблицы по разделам.- Правки в
*.for-human.csv(Excel / LibreOffice):HumanOverride— пусто = братьDecision; иначеAPPLY,SKIP,REVIEW(перекрываетDecisionпри переносе).HumanDestOverride— полный путь файла назначения, если нужно не то, что вDestFullPath.HumanComment— заметка для себя (на перенос не влияет).- Цвет заливки в Excel необязателен; достаточно колонок.
.\Invoke-MediaInboxApplyReviewedCsv.ps1 -CsvPath <ваш исправленный csv>(с-WhatIfдля проверки). Корень инбокса:-InboxRoot(по умолчанию\\…\Video\Sort). Цели в библиотеке (\\…\Video\Мультсериалы,…\Фильмыи т.д.) разрешены, если задан-MediaLibraryVideoRoot, переменнаяMIT_VIDEO_LIBRARY_ROOTилиvideoLibraryRootвmedia-library-layout.local.json.
.\Export-MediaInboxReviewHtml.ps1 -CsvPath <csv>
.\Get-MediaInboxReviewedCsvSummary.ps1 -CsvPath <csv>