Как получить субтитры SRT из видео через API

Отправьте файл в POST /transcribe, укажите output_format со значением srt и word_timestamps со значением false. Когда задача выполнится, просто сохраните полученный текст с расширением .srt. Если нужен перевод на другой язык, добавьте параметр translate_to. Ниже мы разберем сам запрос, структуру файла SRT, сборку аккуратных коротких строк по меткам слов, конвертацию в WebVTT и наложение субтитров на видео.

Получить ключ API Быстрый старт Поддерживаемые языки

Обновлено: · Markdown

Запрос

Два вызова: запустить задачу, затем опросить её. result завершённой задачи srt — строка, а не JSON. Для этой версии нужны только curl и jq:

# 1. Start the job. "word_timestamps": false gives one cue per segment.
JOB=$(curl -s https://app.kolwrite.com/transcribe \
  -H "x-api-key: $KOLWRITE_API_KEY" -H "Content-Type: application/json" \
  -d '{"audio_url": "https://example.com/talk.mp3", "model": "oracle", "output_format": "srt", "word_timestamps": false}' \
  | jq -r .jobId)

# 2. Poll until it is done and save the result string as a .srt file.
while true; do
  REPLY=$(curl -s "https://app.kolwrite.com/transcribe/$JOB" -H "x-api-key: $KOLWRITE_API_KEY")
  STATUS=$(echo "$REPLY" | jq -r .status)
  if [ "$STATUS" = "COMPLETED" ]; then echo "$REPLY" | jq -r .result > talk.srt; break; fi
  if [ "$STATUS" = "FAILED" ]; then echo "$REPLY" | jq -r .error; break; fi
  sleep 5
done

Подойдет и видеофайл, так как API сам прочитает его аудиодорожку. Локальный файл сначала отправляется через POST /upload (до 100 MiB); из длинных видео предварительно извлеките аудио в ffmpeg. Вспомогательная функция из руководства по монтажу видео делает и то и другое на Python.

Что внутри SRT

Если передать "word_timestamps": false, на каждый фрагмент придётся по одной строке, как в большинстве файлов субтитров:

1
00:00:01,000 --> 00:00:03,750
Hello everyone and welcome to the show.

2
00:00:05,000 --> 00:00:07,750
Today we talk about editing video from a transcript.

По умолчанию временные метки слов включены. В этом режиме API выдаёт отдельную запись на каждое слово: текст всего фрагмента повторяется, а произносимое слово оборачивается в жёлтый тег <font>. Это подсветка в режиме караоке, а не обычные субтитры:

1
00:00:01,000 --> 00:00:01,350
<font color="yellow">Hello</font> everyone and welcome to the show.

2
00:00:01,400 --> 00:00:01,750
Hello <font color="yellow">everyone</font> and welcome to the show.

Чтобы получить обычные субтитры, передайте "word_timestamps": false или соберите строки сами из слов в JSON, как показано ниже.

Сборка аккуратных строк по таймингам слов

Запросите output_format: "json" и сгруппируйте слова в коде: максимум 42 символа и 6 секунд на строку, плюс перенос после паузы. Так вы сами задаёте длину строки, что особенно важно, когда субтитры вшиваются в видео.

srt_tools.py

# srt_tools.py — neat subtitle cues from word timings
def srt_time(seconds):
    ms = round(seconds * 1000)
    h, ms = divmod(ms, 3_600_000)
    m, ms = divmod(ms, 60_000)
    s, ms = divmod(ms, 1000)
    return f"{h:02}:{m:02}:{s:02},{ms:03}"


def cues_from_words(words, max_chars=42, max_seconds=6.0, max_gap=0.8):
    """Group timed words into subtitle cues: (start, end, text)."""
    cues, line = [], []
    for word in words:
        text = word["word"].strip()
        if not text:
            continue
        if line:
            length = sum(len(w["word"]) + 1 for w in line) + len(text)
            if (length > max_chars
                    or word["end"] - line[0]["start"] > max_seconds
                    or word["start"] - line[-1]["end"] > max_gap):
                cues.append(line)
                line = []
        line.append({"start": word["start"], "end": word["end"], "word": text})
    if line:
        cues.append(line)
    return [(c[0]["start"], c[-1]["end"], " ".join(w["word"] for w in c)) for c in cues]


def cues_from_result(result):
    """Cues for a whole JSON result; a segment without word times becomes one cue."""
    cues = []
    for segment in result["segments"]:
        if segment.get("words"):
            cues += cues_from_words(segment["words"])
        elif segment["text"].strip():
            cues.append((segment["start"], segment["end"], segment["text"].strip()))
    return cues


def write_srt(cues, path):
    with open(path, "w", encoding="utf-8") as out:
        for number, (start, end, text) in enumerate(cues, 1):
            out.write(f"{number}\n{srt_time(start)} --> {srt_time(end)}\n{text}\n\n")

Функция cues_from_result(result) возвращает кортежи (start, end, text) по всему ответу (если модель не вернула тайминги отдельных слов, берутся тайминги фрагментов), а write_srt(cues, "talk.srt") сохраняет готовый файл.

Перевод субтитров на другой язык

Передайте код нужного языка в translate_to и выберите модель из линейки Oracle (самая дешёвая с поддержкой перевода — oracle_mini). Субтитры сразу придут переведёнными. Оставьте word_timestamps равным false, чтобы одна запись соответствовала целому фрагменту.

{
  "audio_url": "https://example.com/lecture-he.mp4",
  "model": "oracle_mini",
  "language": "he",
  "translate_to": "en",
  "output_format": "srt",
  "word_timestamps": false
}

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

WebVTT, ASS и другие форматы

Сам API отдаёт результат только в json, txt или srt. Перегнать SRT в WebVTT для HTML5-плеера <video> можно через ffmpeg:

ffmpeg -i video.srt video.vtt

Точно так же ffmpeg переводит субтитры и в большинство других форматов, достаточно поменять расширение выходного файла.

Как вшить субтитры или добавить их дорожкой

Вшиваем в картинку:

ffmpeg -i edited.mp4 -vf "subtitles=edited.srt" -c:a copy burned.mp4

Добавляем отдельной дорожкой в MP4 (зритель сможет отключить её в плеере):

ffmpeg -i edited.mp4 -i edited.srt -c copy -c:s mov_text -metadata:s:s:0 language=eng soft.mp4

YouTube Studio и большинство видеоплееров и видеоредакторов принимают файлы .srt напрямую.

Субтитры на иврите и арабском

  • API возвращает обычный текст в Unicode. За вывод справа налево отвечает видеоплеер или рендерер субтитров в ffmpeg: оба нормально справляются с ивритом и арабским, если в выбранном шрифте есть нужные символы.
  • Выберите шрифт с поддержкой нужного алфавита и проверьте результат на одном кадре, прежде чем кодировать всё видео целиком. В наших тестах со шрифтом Arial иврит отрисовался без проблем, а в одном арабском слове вместо буквы появился пустой прямоугольник, поэтому для арабского лучше взять другой шрифт.
ffmpeg -i video.mp4 -vf "subtitles=video.he.srt:force_style='FontName=Arial,FontSize=24'" -c:a copy burned.mp4
  • Если строка заканчивается знаком препинания или словом на латинице (например, названием бренда или числом), плееры без поддержки двунаправленного текста могут перепутать порядок символов. Проверьте, как субтитры выглядят в плеерах, которыми пользуется ваша аудитория.

Сколько это стоит

ЗадачаМодельСтоимость
Лекция на 45 минут, субтитрыoracle1,08 $
Та же лекция с переводом субтитровoracle_mini0,72 $
Час чистого аудио, субтитрыbase0,48 $

Тарификация посекундная, минимального порога нет. Все цены: /llms/pricing.md.

Вопросы и ответы

Как получить файл SRT из видео?

Отправьте запрос POST /transcribe с URL вашего видео, указав output_format: "srt" и word_timestamps: false. Дождитесь завершения задачи и сохраните строку из поля result как файл .srt.

Возвращает ли API формат WebVTT?

Нет, доступны только json, txt и srt. Перевести SRT в WebVTT можно командой ffmpeg -i video.srt video.vtt.

Почему в моём SRT на каждое слово создаётся отдельная строка?

По умолчанию включены тайминги для каждого слова: в этом режиме SRT дублирует фразу для каждого слова, подсвечивая текущее. Передайте word_timestamps: false, чтобы получать по одной строке на фразу, либо собирайте строки сами из JSON-ответа.

Можно ли сразу получить переведённые субтитры?

Да. Передайте код нужного языка в параметре translate_to и выберите модель Oracle. Субтитры вернутся уже на целевом языке.

Чем обычные субтитры отличаются от субтитров для слабослышащих?

Обычные субтитры передают только речь (в оригинале или переводе) для тех, кто слышит звук видео, а субтитры для людей с нарушениями слуха включают ещё и описание неречевых звуков. Наш API возвращает только текст речи с таймкодами, поэтому пометки о звуках при необходимости нужно дописать вручную.