Edição por Comando Conhecer o ebook

Guia · Atualizado em 4 de outubro de 2026 · 3 min de leitura

Legenda automática palavra por palavra no vídeo

A legenda que mostra uma palavra de cada vez, no ritmo da fala, e destaca em amarelo o que importa. Dois scripts, um que transcreve e outro que cola a legenda no vídeo, e o pedido pronto para o Claude Code.

Você já viu: o vídeo mostra uma palavra de cada vez, grande, no centro da tela, e a que carrega o sentido aparece em amarelo. É o estilo mais usado em Reels, TikTok e Shorts.

Fazer isso à mão exige marcar o tempo de cada palavra. Fazer por script exige duas coisas: saber quando cada palavra é dita e desenhar cada uma no vídeo. Este guia resolve as duas, com código que eu testei num vídeo vertical em português.

O que você vai ter no final

Cada palavra aparece só enquanto é falada, em letras brancas com contorno preto. Números e palavras de impacto saem em amarelo.

Dois quadros de um vídeo com legenda palavra por palavra: a palavra QUERO em branco e a palavra VÍDEO em amarelo, no centro da tela
Dois quadros do vídeo de teste: "QUERO" em branco e "VÍDEO", uma palavra de impacto, em amarelo.

O que você precisa

  • ffmpeg, que junta imagem, legenda e áudio. No Mac: brew install ffmpeg.
  • Python 3 e três bibliotecas: pip install faster-whisper pillow numpy.
  • Um vídeo em que alguém fala. A transcrição funciona melhor com voz clara e sem música alta por cima.

Na primeira vez, o faster-whisper baixa o modelo de transcrição, algumas centenas de MB. Depois disso ele roda no seu computador, sem enviar o vídeo para lugar nenhum.

Passo 1: descubra o tempo de cada palavra

Salve como palavras.py:

#!/usr/bin/env python3
"""Transcreve um vídeo com o tempo de cada palavra. Uso: python3 palavras.py video.mp4"""
import json, subprocess, sys
import numpy as np
from faster_whisper import WhisperModel

# o ffmpeg entrega o áudio pronto (16 kHz, mono), sem depender de outra biblioteca de leitura
pcm = subprocess.run(["ffmpeg", "-v", "error", "-i", sys.argv[1], "-f", "f32le", "-ac", "1", "-ar", "16000", "-"],
                     capture_output=True, check=True).stdout
audio = np.frombuffer(pcm, dtype=np.float32)

modelo = WhisperModel("small", compute_type="int8")
segmentos, _ = modelo.transcribe(audio, language="pt", word_timestamps=True)
palavras = [{"palavra": p.word.strip(), "inicio": round(p.start, 2), "fim": round(p.end, 2)}
            for s in segmentos for p in s.words]
print(json.dumps(palavras, ensure_ascii=False, indent=1))

Rode e guarde o resultado:

python3 palavras.py gravacao.mp4 > palavras.json

O arquivo palavras.json fica assim (no vídeo de teste):

[
 { "palavra": "Fala", "inicio": 0.0, "fim": 0.24 },
 { "palavra": "pessoal,", "inicio": 0.24, "fim": 0.58 },
 { "palavra": "hoje", "inicio": 1.0, "fim": 1.14 }
]

Abra o arquivo e leia antes de seguir. O modelo erra nomes próprios, siglas e palavras em inglês, e o que estiver errado aqui vai aparecer na tela. Corrigir é só editar o texto de palavra.

Passo 2: cole a legenda no vídeo

Salve como legendar.py. Ele desenha cada palavra como uma imagem com fundo transparente e a sobrepõe ao vídeo só no tempo em que ela é falada. Esse caminho funciona em qualquer instalação do ffmpeg, sem depender de suporte a fontes ou a arquivos de legenda:

#!/usr/bin/env python3
"""Coloca legenda palavra por palavra no vídeo.
Uso: python3 legendar.py video.mp4 palavras.json saida.mp4 [fonte.ttf]
Cada palavra vira uma imagem com fundo transparente e é sobreposta só no tempo em que é falada."""
import json, os, re, subprocess, sys, tempfile
from PIL import Image, ImageDraw, ImageFont

video, arquivo_palavras, saida = sys.argv[1:4]
fonte = sys.argv[4] if len(sys.argv) > 4 else "/System/Library/Fonts/Supplemental/Arial Bold.ttf"
BRANCO, AMARELO = (255, 255, 255, 255), (255, 225, 77, 255)
DESTAQUE = {"ia", "vídeo", "video", "editar", "grátis", "agora", "nunca", "sempre"}  # palavras de impacto (ajuste à vontade)

larg, alt = map(int, subprocess.run(
    ["ffprobe", "-v", "error", "-select_streams", "v", "-show_entries", "stream=width,height", "-of", "csv=p=0:s=x", video],
    capture_output=True, text=True, check=True).stdout.strip().split("x"))
tamanho = round(larg * 0.11)
fnt = ImageFont.truetype(fonte, tamanho)
palavras = json.load(open(arquivo_palavras, encoding="utf-8"))

pasta = tempfile.mkdtemp()
entradas, filtros, anterior = [], [], "0:v"
for i, p in enumerate(palavras):
    texto = p["palavra"].strip(".,;:!?…").upper()
    if not texto:
        continue
    cor = AMARELO if (re.search(r"\d", texto) or texto.lower() in DESTAQUE) else BRANCO
    img = Image.new("RGBA", (larg, round(tamanho * 1.8)), (0, 0, 0, 0))
    d = ImageDraw.Draw(img)
    x = (larg - d.textlength(texto, font=fnt)) / 2
    d.text((x, tamanho * 0.3), texto, font=fnt, fill=cor, stroke_width=max(3, tamanho // 14), stroke_fill=(0, 0, 0, 255))
    caminho = os.path.join(pasta, f"p{i:03d}.png")
    img.save(caminho)
    entradas += ["-i", caminho]
    n = len(entradas) // 2
    saida_rotulo = f"v{n}"
    ini, fim = p["inicio"], max(p["fim"], p["inicio"] + 0.15)
    filtros.append(f"[{anterior}][{n}:v]overlay=0:{round(alt * 0.62)}:enable='between(t,{ini},{fim})'[{saida_rotulo}]")
    anterior = saida_rotulo

subprocess.run(["ffmpeg", "-y", "-hide_banner", "-loglevel", "error", "-i", video, *entradas,
                "-filter_complex", ";".join(filtros), "-map", f"[{anterior}]", "-map", "0:a?",
                "-c:v", "libx264", "-crf", "20", "-c:a", "copy", saida], check=True)
print("Pronto:", saida)

Rode:

python3 legendar.py gravacao.mp4 palavras.json gravacao-legendado.mp4

No Windows, informe uma fonte instalada como último argumento, por exemplo C:/Windows/Fonts/arialbd.ttf.

Como ajustar o estilo

O que mudar Onde Dica
Palavras em amarelo DESTAQUE Coloque as palavras-chave do seu assunto. Números já saem em amarelo automaticamente.
Cor do destaque AMARELO Troque pelos valores RGB da cor da sua marca.
Tamanho larg * 0.11 Aumente para 0,13 se o vídeo for assistido em tela pequena.
Altura alt * 0.62 0,62 deixa a legenda abaixo do rosto e acima da zona onde Reels e Stories colocam botões e textos da plataforma. Suba ou desça conforme o enquadramento.

Limites que valem saber

  • Vídeos curtos. O script usa uma imagem por palavra. Em vídeos de poucos minutos tudo bem. Em vídeos longos fica pesado, e o melhor é gerar por trechos.
  • Uma palavra por vez. É o estilo que o título promete. Para legenda em frases, é outro desenho.
  • A transcrição precisa de revisão. Sempre confira o palavras.json.

O jeito mais curto: pedir ao Claude Code

Com o Claude Code, você não copia os dois arquivos. Abra a pasta do vídeo e peça:

Coloque legenda palavra por palavra no vídeo gravacao.mp4, no centro da tela, em letras brancas com contorno preto. Destaque em amarelo os números e as palavras de impacto. Antes de colar no vídeo, me mostre a transcrição pra eu conferir. Salve como gravacao-legendado.mp4 e não altere o original.

Ele transcreve, mostra o texto, espera a sua aprovação e só então gera o vídeo. Veja a instalação e o primeiro pedido em Como editar vídeo com Claude Code. Para tirar as pausas antes de legendar, use o guia de como cortar pausas do vídeo automaticamente: as palavras ficam mais próximas e a legenda corre no ritmo certo.

Perguntas frequentes

A transcrição funciona em português do Brasil?

Sim. O script informa language="pt" e o modelo entende bem português falado com voz clara. Ele erra mais em nomes próprios, gírias e termos em inglês, por isso a revisão do passo 1.

Preciso pagar por alguma coisa?

O ffmpeg e o faster-whisper são gratuitos e rodam no seu computador. Se você pedir ao Claude Code, o custo é o da sua conta do Claude.

Dá pra usar a legenda em vídeo horizontal?

Dá. O tamanho e a altura são calculados pelas dimensões do vídeo. Num vídeo horizontal, reduza o 0.11 do tamanho, porque a largura é maior.

E se eu quiser editar a legenda depois?

Edite o palavras.json e rode o legendar.py de novo. O vídeo original continua intacto, e você gera quantas versões quiser.

Leia também