# Como criar legendas SRT de um vídeo com uma API

> Envie o vídeo para POST /transcribe com output_format definido como srt e word_timestamps como false, espere o processamento terminar e salve o texto que voltar em um arquivo .srt. Se quiser a legenda traduzida para outro idioma, basta incluir o parâmetro translate_to. Aqui você vê como montar a requisição exata, o que vem dentro do SRT, como usar os tempos das palavras para quebrar as linhas direitinho, como converter para WebVTT e como colocar a legenda no vídeo.

Última atualização: 2026-10-18 · HTML: https://console.kolwrite.com/pt/guides/srt-subtitles-api

## A requisição

Duas chamadas: iniciar o trabalho e consultá-lo. O `result` de um trabalho `srt` concluído é uma string, não JSON. Esta versão só precisa de curl e jq:

```bash
# 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
```

Você pode mandar um vídeo, já que a API lê a faixa de áudio. Arquivos locais passam antes por `POST /upload` (até 100 MiB). Se o vídeo for longo, extraia o áudio com o ffmpeg. A função auxiliar do [guia de edição de vídeo](https://console.kolwrite.com/pt/guides/video-editing-with-ai) faz as duas coisas em Python.

## O que vem no SRT

Com `"word_timestamps": false`, a saída traz uma linha por trecho, igual à maioria dos arquivos de legenda:

```text
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.
```

Por padrão, os tempos por palavra vêm ativados e a API devolve uma linha para cada palavra. Cada linha repete a frase inteira do trecho e coloca a palavra da vez numa tag `<font>` amarela. Isso serve para destacar a leitura em tempo real, não como legenda comum:

```text
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.
```

Se você quer legendas tradicionais, passe `"word_timestamps": false` ou monte as linhas por conta própria a partir das palavras do JSON, como mostramos abaixo.

## Como montar linhas limpas a partir do tempo das palavras

Peça `output_format: "json"` e agrupe você mesmo as palavras: limite cada linha a 42 caracteres e 6 segundos, e quebre a linha depois de uma pausa. Assim você controla o comprimento exato, o que faz diferença quando a legenda é gravada direto na imagem do vídeo.

srt_tools.py

```python
# 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)` devolve tuplas `(start, end, text)` para o resultado todo e usa os tempos do trecho quando o modelo não traz tempos por palavra. Depois, `write_srt(cues, "talk.srt")` salva o arquivo.

## Legendas traduzidas

Passe `translate_to` com o código do idioma e escolha um modelo Oracle (o `oracle_mini` é o mais barato que faz tradução). O texto já sai traduzido; mantenha `word_timestamps` como false para receber um trecho por linha.

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

Para legendar o mesmo vídeo em vários idiomas, rode um trabalho para cada idioma de destino. Como toda tradução automática é um rascunho, revise nomes, números e termos específicos antes de publicar.

## WebVTT, ASS e outros formatos

A API gera apenas `json`, `txt` ou `srt`. Se precisar de WebVTT para usar na tag `<video>` do HTML5, converta o SRT com o ffmpeg:

```bash
ffmpeg -i video.srt video.vtt
```

O ffmpeg faz a mesma conversão para a maioria dos formatos de legenda; basta mudar a extensão do arquivo de saída.

## Grave a legenda no vídeo ou anexe como faixa

Gravada direto na imagem:

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

Como faixa separada dentro do MP4 (quem assiste pode ligar ou desligar no player):

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

O YouTube Studio e a maioria dos players e editores de vídeo aceitam o arquivo `.srt` direto.

## Legendas em hebraico e árabe

- A API entrega texto Unicode comum. Quem cuida da leitura da direita para a esquerda é o player ou o renderizador de legendas do ffmpeg, que lida bem com hebraico e árabe desde que a fonte escolhida tenha os caracteres.
- Indique uma fonte compatível com o alfabeto e confira um quadro renderizado antes de converter o vídeo inteiro. Nos nossos testes, a fonte Arial funcionou bem para hebraico, mas falhou em um glifo numa palavra em árabe; por isso, teste outra fonte quando for usar árabe.

```bash
ffmpeg -i video.mp4 -vf "subtitles=video.he.srt:force_style='FontName=Arial,FontSize=24'" -c:a copy burned.mp4
```

- Se a linha terminar com pontuação ou caracteres latinos (como uma marca ou um número), a ordem pode sair invertida em players que não tratam bem texto bidirecional. Faça um teste nos players que o seu público costuma usar.

## Quanto custa

| Trabalho | Modelo | Custo |
| --- | --- | --- |
| Aula de 45 minutos, com legendas | `oracle` | US$ 1,08 |
| A mesma aula, com legendas traduzidas | `oracle_mini` | US$ 0,72 |
| Uma hora de áudio limpo, com legendas | `base` | US$ 0,48 |

Cobramos por segundo, sem valor mínimo. Veja a tabela em [/llms/pricing.md](https://console.kolwrite.com/llms/pricing.md).

## Perguntas e respostas

### Como gero um arquivo SRT a partir de um vídeo?

Chame `POST /transcribe` passando a URL do vídeo, `output_format: "srt"` e `word_timestamps: false`. Acompanhe o andamento do trabalho e, quando terminar, salve a string `result` como um arquivo `.srt`.

### A API devolve WebVTT?

Não, apenas `json`, `txt` ou `srt`. Para ter WebVTT, converta o SRT rodando `ffmpeg -i video.srt video.vtt`.

### Por que meu SRT veio com uma linha para cada palavra?

Por padrão, a marcação de tempo por palavra vem ativa, então o SRT traz uma linha para cada palavra e destaca a que está sendo falada. Para receber uma linha por trecho, envie `word_timestamps: false` ou monte você mesmo as linhas usando o JSON.

### Consigo gerar legendas já traduzidas?

Sim. Basta incluir `translate_to` com o código do idioma desejado e usar um modelo Oracle. As linhas já voltam traduzidas.

### Qual a diferença entre legendas comuns e legendas para surdos e ensurdecidos?

A legenda comum só traz o que é falado (transcrito ou traduzido) para quem consegue ouvir o áudio. Já a legenda para surdos e ensurdecidos inclui também a descrição dos sons do ambiente. A API entrega o texto da fala com os tempos; se precisar descrever os sons, adicione essas marcações manualmente.

## Páginas relacionadas

- [Editar vídeo com agentes de IA](https://console.kolwrite.com/pt/guides/video-editing-with-ai)
- [API de carimbos de tempo por palavra](https://console.kolwrite.com/pt/guides/word-timestamps-api)
- [Legendas para podcasts e YouTube](https://console.kolwrite.com/pt/guides/podcast-youtube-captions)
- [Mídia, podcasts e legendas](https://console.kolwrite.com/pt/use-cases/media)
- [Universidades e estudantes](https://console.kolwrite.com/pt/use-cases/education)
- [Documentação da API](https://console.kolwrite.com/pt/public_api_docs)

---
Obter uma chave de API: https://console.kolwrite.com/auth?lang=pt · Documentação da API: https://console.kolwrite.com/pt/public_api_docs · llms.txt: https://console.kolwrite.com/llms.txt
