src/techinfo.py — правила по строкам «Видео:», «Тип релиза:»/«Качество», «Контейнер:», «Продолжительность:», «Субтитры:» и заголовку: поля video (кодек, размер кадра, класс разрешения, fps, битрейт, битность, HDR, профиль DV), release (тип, нормализованный источник, контейнер, продолжительность), subtitles (языки с forced/full/SDH, формат, вшитые). audio дорожек и original: khz и atmos (вход модели не меняется). title_from_html больше не рвёт заголовок rutracker пробелами (<span>/<wbr> на каждом слове). Покрытие на 600 страницах каждого трекера: видео 90/93/100%, e2e озвучки без изменений. Тесты 275 ok. Co-Authored-By: Claude Opus 5.5 <[email protected]>
6.8 KiB
Инференс: CLI, Python API, JSON-контракт
CLI (src/predict.py)
# одна дорожка текстом (префикс «Перевод:» не обязателен, но допустим)
python -m src.predict --text "Перевод: Профессиональный (многоголосый закадровый) | HDRezka Studio 18+"
# HTML-страница целиком -> все дорожки релиза
python -m src.predict --html data/samples/rt-topic.html
# текстовый дамп страницы
python -m src.predict --file data/pages/6907007.txt
# результат в файл + выбор модели
python -m src.predict --file page.txt --out result.json --model models/base
Кодировка входных файлов определяется автоматически (utf-8 → cp1251).
HTML распознаётся по содержимому, так что --html и --file
взаимозаменяемы.
Ссылка на раздачу и агрегат релиза
python -m src.predict --url https://rutracker.org/forum/viewtopic.php?t=123
python -m src.predict --url https://kinozal.tv/details.php?id=1 # kinozal без входа
python -m src.predict --url https://kinozal.tv/details.php?id=1 --cookie "uid=..; pass=.." # если раздача закрыта для гостей
Поддерживаются только rutracker / kinozal / nnm-club (allowlist доменов,
редиректы за его пределы запрещены). Для --html, --file и --url ответ —
агрегат релиза: к tracks добавлены
| Поле | Описание |
|---|---|
studios |
уникальные {studio, translation_type, is_18plus} |
translation_types |
отсортированный список типов релиза |
is_18plus |
true, если 18+ хотя бы у одной дорожки |
original, series |
оригинальная дорожка; сезон и серии |
video |
кодек, разрешение, fps, битрейт, битность, HDR (Dolby Vision / HDR10+ / HDR10 / HLG) |
release |
тип релиза («WEB-DL», «BDRemux»…), контейнер, продолжительность |
subtitles |
языки субтитров с пометками forced / full / SDH, формат, вшитые ли |
title |
заголовок раздачи (если найден в HTML) |
tracker |
только для --url |
Дорожки дедуплицируются по (тип, студия). Студии из заголовка раздачи вида
ПМ (LostFilm), которых нет в описании, добавляются с source: "title"
(у остальных source: "page"). --text по-прежнему возвращает только tracks.
Все поля и их значения — в api-reference.md; video, release, subtitles
считаются правилами (src/techinfo.py), без нейросети.
Python API
from src.predict import DubPredictor
model = DubPredictor() # models/best; параметр device определяется сам
model.predict_text("Авторский (одноголосый закадровый) - Ю. Сербин")
# -> dict (см. контракт ниже)
model.predict_html(open("page.html", encoding="utf-8").read())
# -> list[dict] — по одному на каждую найденную дорожку
model.predict_page("Перевод: Дублированный | MovieDalen\n...") # текст без HTML
model.predict_file("page.txt")
JSON-контракт
Полный справочник значений (15 классов translation_type, lang, role, audio, агрегат релиза, принцип работы) — в api-reference.md; ниже краткий пример.
{
"tracks": [
{
"segment": "Профессиональный (многоголосый закадровый) | HDRezka Studio 18+",
"translation_type": "проф. многоголосый",
"type_confidence": 0.99,
"studio_span": "HDRezka Studio",
"studio": "HDrezka",
"studio_confidence": 0.97,
"is_18plus": true,
"age_confidence": 0.99
}
]
}
| Поле | Тип | Описание |
|---|---|---|
segment |
string | текст дорожки, по которому сделано предсказание (префикс снят) |
translation_type |
string | один из 15 классов (см. docs/dataset.md) |
type_confidence |
float | softmax-вероятность класса |
studio_span |
string | null | фрагмент текста, распознанный как имя автора |
studio |
string | null | каноническое имя автора по словарю алиасов; null — автора в тексте нет |
studio_confidence |
float | null | средняя вероятность токенов спана |
is_18plus |
bool | дорожка помечена 18+ |
age_confidence |
float | вероятность предсказанного класса 18+ |
Как обрабатывается страница
- HTML → текст (BeautifulSoup:
div.post_body(rutracker) →#tabs(kinozal) → весь документ); - строки вида «Перевод/Озвучка/Озвучивание/Озвучено/Звук/Аудио N: …»;
- разбиение многострочных дорожек: нумерация «1. … 2. …», разделители «+ ; /» перед словами типов, перечисление типов через запятую;
- строки без признаков типа озвучки (например, чисто кодек-строки) не попадают в результат;
- каждая дорожка — отдельное предсказание модели.
Ограничения
studio— нормализация по словарю; неизвестные имена возвращаются как есть (спан), без канонизации;- если дорожка в тексте написана без какой-либо информации о типе, модель вернёт наиболее вероятный класс (обычно «неизвестно») — фильтрация таких строк уже сделана на этапе сегментации;
- классы с единичными примерами в обучении (см. docs/dataset.md) предсказываются хуже — видно в confusion matrix.