Перевод субтитров нейросетью: SRT без сбитых таймкодов

Главный риск при переводе SRT нейросетью — сломанная структура файла. Показываем схему, где таймкоды не попадают к модели, и скрипт на Python с проверкой.

6 мин · · автоматизация · разработка

Если отдать SRT-файл целиком в чат и попросить «переведи», результат часто выглядит правдоподобно, но ломается при проверке: пропали реплики, поплыли номера, слиплись соседние фразы, а иногда изменились сами таймкоды. Надёжнее не просить модель сохранять структуру, а не показывать ей структуру вовсе. Ниже схема, как использовать нейросеть для перевода субтитров, чтобы номера и тайминги остались нетронутыми, плюс скрипт на Python и расчёт стоимости на примере фильма.

Как устроен SRT и что в нём хрупкое

Файл состоит из блоков, разделённых пустой строкой:

12 00:01:05,200 --> 00:01:08,000 <i>I told you not to come here.</i> Why did you?

Номер, строка времени, один или несколько строк текста. Для перевода нужен только текст, всё остальное модель переводить не должна. Хрупких мест четыре:

  1. Таймкоды. Формат ЧЧ:ММ:СС,МММ --> ЧЧ:ММ:СС,МММ, запятая перед миллисекундами. Модель может «исправить» её на точку или поменять цифры.
  2. Номера реплик. При слиянии или потере реплик нумерация уезжает.
  3. Теги и символы. <i>, <b>, музыкальные значки, разметка в фигурных скобках.
  4. Разбиение на строки. Перевод на русский, как правило, длиннее английского оригинала, и в две строки по 42 символа он может не влезть.

Схема: модель видит только текст

  1. Разберите файл программой на реплики: номер, время, текст.
  2. Отправляйте модели только тексты, под служебными ключами (0, 1, 2, ...), а не под номерами SRT.
  3. Просите вернуть JSON с теми же ключами.
  4. Проверьте, что ключи совпали, затем подставьте перевод обратно к исходным номерам и таймкодам.

Так таймкоды физически не могут измениться: они даже не покидают вашу программу. Остаётся проверить число реплик и длину строк.

Блоки и контекст

Реплики в субтитрах обрываются на полуслове, и перевод по одной реплике теряет смысл. Но и весь файл за один запрос отправлять рискованно: ответ может обрезаться по лимиту, а ошибка в одном месте заставит перевести всё заново. Рабочая середина:

  • блок 30-50 реплик на запрос;
  • в запрос добавляются 2-3 предыдущие реплики как контекст с пометкой «не переводить»;
  • при неверном ответе повторяется только этот блок.

В запрос полезно добавить имена и термины из фильма («Mr. Holmes оставить как Мистер Холмс»), чтобы они переводились одинаково во всех блоках. Контекст для длинного видео можно дополнить кратким описанием: жанр, о чём сюжет, кто говорит.

Скрипт на Python

Скрипт использует OpenAI SDK и шлюз Zukko: адрес https://api.zukko.pro/v1, ключ в переменной ZUKKO_API_KEY. Подробнее о подключении — в документации по Python.

bash
import json
import os
import re
import textwrap
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key=os.environ["ZUKKO_API_KEY"])
MODEL = "deepseek-v4.1-flash"
CHUNK = 40      # реплик в одном запросе
CONTEXT = 3     # сколько предыдущих реплик показать как контекст
TIME_RE = re.compile(r"^\d{2}:\d{2}:\d{2}[,.]\d{3} --> \d{2}:\d{2}:\d{2}[,.]\d{3}")


def parse_srt(text):

Что делает код:

  • parse_srt режет файл на реплики и поддерживает файлы с BOM (utf-8-sig) и переносами Windows;
  • ask отправляет блок в виде JSON, а в translate_chunk проверяется, что вернулись ровно те же ключи и что среди значений нет пустых; иначе блок отправляется заново (до трёх попыток);
  • fit_lines переносит слишком длинные строки так, чтобы вышло не больше двух строк по 42 символа; если не получилось, номер реплики попадает в список для ручной правки;
  • в выходной файл записываются исходные номера и таймкоды без изменений.

Реплики без текста скрипт пропускает. Если в вашем файле такие бывают, добавьте их обработку отдельно. Отдельные параметры (размер блока, ширина строки) подберите по своим субтитрам.

Длина строки и скорость чтения

Для субтитров чаще всего ориентируются на две строки по 42 символа. Это распространённое соглашение, а не требование формата SRT: в вашем плеере или на вашей платформе правила могут быть другими. Ещё важнее скорость чтения: если реплика длится секунду, а перевод занимает две строки, зритель не успеет прочитать. Нейросеть можно попросить сокращать перевод («сжимай до смысла, если реплика короче двух секунд»), но длительность реплики модели надо передавать явно. Для этого можно добавить в JSON длительность в секундах, посчитанную вами из таймкодов. Только не просите модель править сами таймкоды.

Проверка результата

После запуска сделайте автоматические проверки и несколько ручных:

  1. Число реплик в исходном и переведённом файле совпадает.
  2. Файл открывается в плеере или редакторе субтитров (VLC, Aegisub и т.п.) без ошибок.
  3. Теги <i> в переводе парные: количество открывающих равно числу закрывающих.
  4. Нет латиницы там, где её быть не должно: оставшиеся английские фразы часто означают пропущенную реплику.
  5. Выборка вручную: 10-20 реплик из разных мест фильма, особенно сленг, шутки и реплики с обращением на «ты» и «вы».

Какая модель и сколько это стоит

Для перевода обычно не нужна самая сильная модель. Попробуйте дешёвые и сравните на отрывке в 100-200 реплик. По таблице на 18 октября 2026 (Zukko, $ за 1M токенов, вход / выход, индекс силы):

МодельВход / выходИндекс
deepseek-v4.1-flash0.013 / 0.03839
glm-5.3-flash0.04 / 0.0442
gpt-6.1-sol0.27 / 1.3252
claude-sonnet-5-50.4 / 248

Расчёт для фильма на 1 500 реплик. Допущения (проверьте на своём файле по полю usage): 60 000 токенов входа вместе с инструкциями и контекстом и 50 000 токенов выхода, потому что русский текст токенизируется длиннее английского.

Формула: вход × цена входа + выход × цена выхода.

  • deepseek-v4.1-flash: 0.06 × 0.013 + 0.05 × 0.038 = 0.00078 + 0.0019 = $0.00268.
  • glm-5.3-flash: 0.06 × 0.04 + 0.05 × 0.04 = 0.0024 + 0.002 = $0.0044.
  • gpt-6.1-sol: 0.06 × 0.27 + 0.05 × 1.32 = 0.0162 + 0.066 = $0.0822.
  • claude-sonnet-5-5: 0.06 × 0.4 + 0.05 × 2 = 0.024 + 0.1 = $0.124.

(Здесь 0.06 и 0.05 — миллионы токенов.) Полный фильм обходится от долей цента до примерно 12 центов в зависимости от модели. Многие ищут нейросеть для перевода бесплатно; в Zukko бесплатного тарифа нет, оплата идёт за токены с баланса от $1, но по расчёту выше перевод фильма стоит заметно меньше доллара. Оплатить можно через СБП (платёжная страница добавляет комиссию 8,5% сверху), криптовалютой или картой MasterCard.

Если качество дешёвой модели не устроило (юмор, идиомы, много сленга), поднимайтесь по таблице и сравнивайте на том же отрывке.

Практические советы

  • Сохраняйте оригинал и работайте с копией.
  • Держите словарь имён и терминов в начале каждого запроса.
  • Для двуязычного результата можно оставить в файле английский текст первой строкой, но это уже отдельная задача.
  • Другие форматы (VTT, ASS) работают по той же схеме, но разбор файла другой. Для ASS структура сложнее, и тексты лучше извлекать специальной библиотекой.
  • Не публикуйте переводы чужих фильмов без прав: это вопрос правообладателя, а не техники.

Для запуска создайте ключ в кабинете Zukko. Для больших серий полезно поставить дневной лимит на ключ: подробности — в статье Как поставить дневной и месячный лимит на API-ключ. Если нужно переводить много файлов, обратите внимание на статьи Перевод текстов через API и Перевод i18n файлов.

Частые вопросы

Можно ли отправить SRT модели целиком?

Для коротких файлов можно, но структура может пострадать. Надёжнее разбор в программе: модель получает только тексты, а номера и таймкоды остаются у вас.

Почему перевод получается длиннее оригинала?

Русский текст обычно длиннее английского. Поэтому нужны сокращение перевода и перенос строк, а для коротких реплик ещё и проверка скорости чтения.

Подойдёт ли способ для перевода не с английского?

Да. Меняется только инструкция в запросе: языки, имена и правила. Схема с ключами и проверкой остаётся прежней.

Сколько стоит перевод одного фильма?

Зависит от модели и объёма. В расчёте выше для 1 500 реплик получается от долей цента на deepseek-v4.1-flash до примерно 12 центов на claude-sonnet-5-5. Цены на 18 октября 2026; точные цифры возьмите из поля usage ответов.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.