# Como editar vídeo com o Claude, o Codex ou qualquer agente de IA

> Passe para o agente uma transcrição com o tempo exato de início e fim de cada palavra. Ele escolhe quais frases ficam, e um script curto usa esses tempos para cortar o vídeo no ffmpeg. A API do KolWrite gera essa transcrição para áudio e vídeo em 100 idiomas. As mesmas palavras ainda servem para montar as legendas do vídeo pronto.

Última atualização: 2026-10-18 · HTML: https://console.kolwrite.com/pt/guides/video-editing-with-ai

## O que o agente faz e o que não faz

Como a transcrição traz só a fala, o agente edita com base no que foi dito. Ele tira erros de início, vícios de linguagem, tomadas repetidas, desvios de assunto e pausas longas, ou separa as frases certas para montar um clipe curto. Mas ele não vê a imagem. A parte visual, como escolher qual plano entra, continua na sua mão, a menos que você passe alguns quadros do vídeo para ele analisar.

Agentes que rodam comandos no terminal (como Claude Code, Codex CLI ou um agente do Cursor) chamam a API e executam o ffmpeg por conta própria. Um chat comum, que não roda código, não faz isso sozinho, mas pode escrever os scripts para você rodar.

## Prompt para colar no seu agente

Com este prompt, o agente trabalha com os números dos trechos em vez de digitar os tempos direto, o que evita que ele invente marcações que não existem. O texto também aponta para a documentação da API feita para leitura por máquina.

```text
Edit talk.mp4 down to the parts worth keeping, using the KolWrite API for the transcript.
Read https://console.kolwrite.com/agent-instructions.md first. The key is in KOLWRITE_API_KEY.
1. Extract the audio with ffmpeg and transcribe it with model "oracle", output_format "json", word_timestamps true.
2. Print the segments as numbered lines: S<number> [start-end] text.
3. Choose the segments to keep (remove false starts, filler, repeated takes and tangents) and write
   their numbers to keep.json as {"keep": [0, 2, 4]}. Do not invent timestamps; use segment numbers only.
4. Cut the video from those segments' word times with ffmpeg and write edited.mp4.
5. Make edited.srt for the edited video and attach it as a subtitle track.
Show me the list of removed segments before you cut anything.
```

Se quiser deixar a API configurada para todas as sessões, coloque a regra do [guia da ferramenta](https://console.kolwrite.com/pt/guides/transcription-tool-for-ai-agents) no seu arquivo `AGENTS.md` ou `CLAUDE.md`.

## Passo 1: extraia o áudio e faça a transcrição

O envio assinado tem limite de 100 MiB por arquivo. Se o vídeo for longo, separe o áudio antes de subir. Uma hora de áudio mono a 48 kbit/s dá cerca de 21 MB.

```bash
ffmpeg -i talk.mp4 -vn -ac 1 -ar 16000 -b:a 48k talk.mp3
```

Esta função simples sobe um arquivo local, dá a partida no trabalho e espera o resultado ficar pronto:

kolwrite.py

```python
# kolwrite.py — three small functions around the KolWrite REST API
import os, time, requests

API = "https://app.kolwrite.com"
HEADERS = {"x-api-key": os.environ["KOLWRITE_API_KEY"]}


def upload(path):
    """Upload a local file (up to 100 MiB) and return a URL the API can read."""
    name = os.path.basename(path)
    form = requests.post(f"{API}/upload", headers=HEADERS, json={"filename": name}, timeout=30)
    form.raise_for_status()
    form = form.json()
    with open(path, "rb") as media:
        # No x-api-key on this request: it goes to the storage address.
        sent = requests.post(form["uploadUrl"], data=form["uploadFields"],
                             files={"file": (name, media)}, timeout=600)
    sent.raise_for_status()
    return form["fileUrl"]


def transcribe(audio_url, timeout_s=3600, **options):
    """Start a job, wait for it, return the result: a dict for json, a string for srt and txt."""
    body = {"audio_url": audio_url, "model": "oracle", **options}
    job = requests.post(f"{API}/transcribe", headers=HEADERS, json=body, timeout=30)
    job.raise_for_status()
    job_id = job.json()["jobId"]
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        time.sleep(5)
        reply = requests.get(f"{API}/transcribe/{job_id}", headers=HEADERS, timeout=30)
        reply.raise_for_status()
        reply = reply.json()
        if reply["status"] == "COMPLETED":
            return reply["result"]
        if reply["status"] == "FAILED":
            raise RuntimeError(reply.get("error", "transcription failed"))
    raise TimeoutError(f"job {job_id} did not finish in {timeout_s} seconds")
```

O script `edit.py` abaixo pede a saída em JSON com os tempos de cada palavra (esses dois já são o padrão, mas deixamos explícito no código para ficar claro). A resposta vem em `segments[]`, onde cada item traz `start`, `end`, `text`, um `speaker` opcional e `words[]`:

Resumo do que volta:

```json
{
  "jobId": "34c63d45-4cb5-473b-bc60-25c175e69c57",
  "status": "COMPLETED",
  "result": {
    "language": "en",
    "segments": [
      {
        "start": 1.0,
        "end": 3.75,
        "text": "Hello everyone and welcome to the show.",
        "speaker": "Speaker 1",
        "words": [
          { "start": 1.0, "end": 1.35, "word": "Hello" },
          { "start": 1.4, "end": 1.75, "word": "everyone" }
        ]
      }
    ]
  }
}
```

## Passo 2: deixe o agente escolher o que fica

Imprima a transcrição como uma lista de linhas numeradas. É isso que o agente vai ler, o que gasta bem menos tokens do que passar o JSON bruto cheio de palavras.

view.py

```python
# view.py — print the transcript the way an agent can read it
import json, sys

result = json.load(open(sys.argv[1]))
for number, segment in enumerate(result["segments"]):
    who = f'{segment["speaker"]}: ' if segment.get("speaker") else ""
    print(f'S{number} [{segment["start"]:.1f}-{segment["end"]:.1f}] {who}{segment["text"]}')
```

O agente devolve só os números dos trechos escolhidos:

keep.json

```json
{"keep": [0, 2, 4]}
```

Antes de rodar o corte, peça para ele listar o que tirou e o motivo. Refazer um corte errado custa pouco, mas bater o olho numa lista é bem mais rápido do que assistir ao vídeo inteiro depois.

## Passo 3: corte no ffmpeg usando os tempos das palavras

O script pega os números dos trechos e busca o tempo de início na primeira palavra e o de fim na última. Depois, adiciona alguns centésimos de segundo de margem, junta os trechos que estão colados e recodifica tudo de uma vez só para o corte bater no quadro exato. Ele também recalcula os tempos das palavras para a linha do tempo do vídeo novo, já deixando tudo pronto para a legenda.

cut.py

```python
# cut.py — ranges from segment numbers, one ffmpeg pass, word times for the new timeline
import subprocess

PAD = 0.08  # seconds of room kept around every range


def ranges_from_ids(segments, keep_ids, pad=PAD):
    """Turn the segment numbers the agent chose into [start, end] ranges in seconds."""
    ranges = []
    for i in sorted(set(keep_ids)):
        segment = segments[i]
        words = segment.get("words") or []
        start = words[0]["start"] if words else segment["start"]
        end = words[-1]["end"] if words else segment["end"]
        start, end = max(0.0, start - pad), end + pad
        if ranges and start <= ranges[-1][1]:
            ranges[-1][1] = max(ranges[-1][1], end)
        else:
            ranges.append([start, end])
    return ranges


def cut(video, ranges, out):
    """Re-encode the kept ranges into one file (frame accurate)."""
    parts = []
    for i, (start, end) in enumerate(ranges):
        parts.append(f"[0:v]trim=start={start:.3f}:end={end:.3f},setpts=PTS-STARTPTS[v{i}]")
        parts.append(f"[0:a]atrim=start={start:.3f}:end={end:.3f},asetpts=PTS-STARTPTS[a{i}]")
    joined = "".join(f"[v{i}][a{i}]" for i in range(len(ranges)))
    parts.append(f"{joined}concat=n={len(ranges)}:v=1:a=1[v][a]")
    subprocess.run(["ffmpeg", "-y", "-hide_banner", "-loglevel", "error", "-i", video,
                    "-filter_complex", ";".join(parts), "-map", "[v]", "-map", "[a]", out], check=True)


def remap(words, ranges):
    """Move word times onto the edited timeline, so subtitles match the cut video."""
    moved, offset = [], 0.0
    for start, end in ranges:
        for word in words:
            if word["start"] >= start and word["end"] <= end:
                moved.append({**word, "start": word["start"] - start + offset,
                              "end": word["end"] - start + offset})
        offset += end - start
    return moved
```

edit.py

```python
# edit.py — the whole pipeline: transcript in, edited video and subtitles out
import json
from kolwrite import upload, transcribe
from cut import ranges_from_ids, cut, remap
from srt_tools import cues_from_words, write_srt

result = transcribe(upload("talk.mp3"), output_format="json", word_timestamps=True)
with open("talk.json", "w", encoding="utf-8") as out:
    json.dump(result, out, ensure_ascii=False)
# ... the agent reads talk.json (python view.py talk.json) and writes keep.json ...

keep = json.load(open("keep.json"))["keep"]
ranges = ranges_from_ids(result["segments"], keep)
cut("talk.mp4", ranges, "edited.mp4")

words = [w for segment in result["segments"] for w in segment.get("words", [])]
write_srt(cues_from_words(remap(words, ranges)), "edited.srt")
```

Apenas copiar os fluxos sem recodificar (`-c copy`) é mais rápido, mas como o corte só acontece em quadros-chave, ele pode sair alguns segundos fora do lugar. Quando a precisão do corte fizer diferença, faça a recodificação.

## Passo 4: legendas para o vídeo editado

O `edit.py` já salvou o arquivo `edited.srt` usando os tempos recalculados das palavras. Para ver como as linhas são montadas, dê uma olhada no [guia de SRT](https://console.kolwrite.com/pt/guides/srt-subtitles-api).

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")
```

Você pode gravar as legendas direto na imagem ou embutir como uma faixa separada, que dá para ligar e desligar no reprodutor:

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

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

## Outras edições usando os mesmos tempos por palavra

- Cortar silêncios: mantenha os blocos de fala contínua e jogue fora as pausas que passarem de um certo limite (veja como no [guia de carimbos de tempo por palavra](https://console.kolwrite.com/pt/guides/word-timestamps-api)).
- Separar um clipe: busque uma frase específica na lista de palavras e recorte só aquele intervalo.
- Limpar vícios de linguagem: peça para o agente marcar os trechos que são só muleta de fala, ou faça uma busca direto nas palavras.
- Marcar capítulos e destaques: o agente aponta os números dos trechos e o script transforma isso em marcações de tempo (veja o [guia de podcasts e YouTube](https://console.kolwrite.com/pt/guides/podcast-youtube-captions)).
- Isolar a fala de uma pessoa: ative o `include_diarization` e filtre apenas os trechos de quem você quer manter.

## Quanto custa

| Trabalho | Modelo | Custo |
| --- | --- | --- |
| Clipe de 10 minutos, transcrito uma vez | `oracle` | US$ 0,24 |
| Uma hora de vídeo, áudio limpo | `base` | US$ 0,48 |
| Uma hora de vídeo, qualidade de produção | `oracle` | US$ 1,44 |
| Uma hora, áudio difícil | `oracle_max` | US$ 3,60 |

A cobrança é feita por segundo e sem valor mínimo. Se um trecho específico ficar ruim e você quiser passar de novo em um modelo mais pesado, basta cortar só aquele pedaço do áudio antes de enviar para pagar apenas por ele. Veja a tabela em [/llms/pricing.md](https://console.kolwrite.com/llms/pricing.md).

## Limites que você precisa conhecer

- As marcações de tempo servem bem para cortar entre uma palavra e outra, mas podem variar um pouquinho bem na ponta da palavra. A margem que o `cut.py` adiciona já resolve isso, mas vale sempre ouvir como ficaram os cortes antes de publicar.
- Toda transcrição automática erra às vezes. Revise sempre os nomes próprios e números antes de publicar qualquer coisa. O KolWrite não divulga uma taxa de acerto por idioma para esta API.
- Não apague o arquivo original. Os cortes são recodificados a partir dele, e você vai precisar do bruto se resolver mudar a edição depois.
- Se a lista de intervalos ficar grande demais, o filtro gerado para o ffmpeg também fica gigante. Se passar de algumas centenas de cortes, divida o trabalho em lotes.

## Perguntas e respostas

### O Claude consegue editar um vídeo?

O Claude consegue editar vídeos quando pode executar comandos. Ele chama a API do KolWrite para pegar a transcrição com os tempos de cada palavra, escolhe quais frases manter e roda o ffmpeg para fazer os cortes. O Claude Code, o Codex CLI e os agentes do Cursor fazem isso, enquanto uma janela de chat comum apenas escreve os scripts.

### Como corto um vídeo pela transcrição?

Faça a transcrição com tempos por palavra, escolha quais trechos vão ficar e pegue o início da primeira palavra e o fim da última em cada trecho. Com esses números em mãos, use os filtros trim e concat do ffmpeg para cortar os intervalos, do jeito que mostramos no `cut.py`.

### Preciso de um plugin ou de um SDK?

Não. A API é HTTPS e JSON; o agente a chama com curl ou Python. No momento da escrita, não há pacote SDK nem servidor MCP publicados.

### Funciona com hebraico, árabe e outros idiomas?

Para a transcrição, sim. A API aceita 100 idiomas, que ela mesma detecta ou que você define no parâmetro `language`. Os tempos por palavra saem dos modelos listados no [guia de carimbos de tempo por palavra](https://console.kolwrite.com/pt/guides/word-timestamps-api). Vale testar antes com uma amostra dos seus áudios e conferir a página de [idiomas](https://console.kolwrite.com/pt/languages/).

### Como evitar que o agente invente carimbos de tempo?

Nunca peça para o agente devolver marcações de tempo. Entregue os trechos numerados, peça apenas os números de volta e deixe o seu código calcular os tempos reais a partir das palavras.

## Páginas relacionadas

- [API de legendas SRT](https://console.kolwrite.com/pt/guides/srt-subtitles-api)
- [API de carimbos de tempo por palavra](https://console.kolwrite.com/pt/guides/word-timestamps-api)
- [Ferramenta de transcrição para agentes de IA](https://console.kolwrite.com/pt/guides/transcription-tool-for-ai-agents)
- [Agentes de IA e vibe coding](https://console.kolwrite.com/pt/use-cases/ai-agents)
- [Mídia, podcasts e legendas](https://console.kolwrite.com/pt/use-cases/media)
- [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
