Vídeo com IA: Claude Code, Codex e ElevenLabs · Capítulo 2 de 25 · 22 min
Desenhar o pipeline de vídeo do briefing à publicação
Transforme o mapa de ferramentas numa linha de produção em que cada etapa recebe um arquivo e entrega outro e em que nada é publicado sem aprovação humana.
Este capítulo faz parte do curso gratuito Vídeo com IA: Claude Code, Codex e ElevenLabs.
Pipeline é uma linha de produção: cada etapa recebe uma entrada, faz um trabalho e entrega um arquivo que a etapa seguinte consegue usar. Quando a narração aprovada existe só dentro de uma conversa com o agente, ninguém sabe qual versão entrou no vídeo, e a automação fica frágil.
Sem esse desenho, cada falha custa caro. O agente regenera tudo porque não sabe o que já estava aprovado, a voz é paga duas vezes, a legenda perde a sincronia com a locução nova e um MP4 antigo, esquecido na pasta, segue para a publicação.
Nesta aula você desenha o caminho inteiro sem gerar mídia paga: pastas, um manifesto em JSON e um fluxograma que respondem, para qualquer etapa, qual arquivo entra, qual sai, quem responde por ele e o que impede o avanço.
Definir o contrato de cada etapa
Contrato de etapa é a etiqueta de entrega da linha de produção: diz o que a etapa recebe, o que faz, o que devolve e o que precisa acontecer para avançar. O agente pode mudar de um dia para o outro; os arquivos e os critérios de aprovação continuam legíveis para você, para o Claude Code e para o Codex. O manifesto, a ficha de produção do vídeo, reúne todos os contratos num arquivo só.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
Alguns limites dos fornecedores entram direto nos contratos, e cada um tem a sua aula. A narração com o Eleven v4 pela Text to Dialogue aceita até 2.000 caracteres por pedido, então roteiro maior vira mais de uma chamada (narrar com Eleven v4 por API); desde 28/09/2026, cada pedido leva até 100 caracteres do trecho anterior e do seguinte em previous_text e future_text, e o contrato da etapa de voz exige esses dois campos para a entonação não quebrar na emenda. A transcrição do Scribe guarda o tempo de cada palavra num JSON que o SRT não carrega, por isso o JSON original fica guardado ao lado da legenda (transcrever com Scribe). A montagem é feita por ferramentas de composição, e não por modelos generativos (Remotion ou HyperFrames).
No vídeo de 40 segundos abaixo, observe a ordem das etapas principais e em qual delas o custo por minuto final se concentra.
Carregando a vídeo-aula: O pipeline de vídeo com IA em seis etapas
- Etapa 1 de 8: Roteiro
Claude Code entrega roteiro.md
- Etapa 2 de 8: Imagens
gpt-image-2.5-flare entrega quadros.json
- Etapa 3 de 8: Voz
eleven_v4 entrega narracao.mp3
- Etapa 4 de 8: Transcrição
scribe_v2 entrega narracao.json
- Etapa 5 de 8: Legenda
Script local entrega narracao.srt
- Etapa 6 de 8: Montagem
FFmpeg entrega revisao.mp4
- Etapa 7 de 8: QA
Claude e você entregam aprovacao.json
- Etapa 8 de 8: Publicação
Script da plataforma entrega recibo.json
O contrato de cada etapa por dentro
workflow Entradas e saídas de cada etapa
O que entra e o que sai de cada etapa do P1
| Etapa | Entra | Sai |
|---|---|---|
| Roteiro | briefing/receita.md | roteiro/roteiro.md e storyboard/cenas.json |
| Imagens | storyboard/cenas.json | storyboard/quadros.json |
| Voz | roteiro/roteiro.md | audio/narracao.mp3 |
| Transcrição | audio/narracao.mp3 | transcricoes/narracao.json |
| Legenda | transcricoes/narracao.json | legendas/narracao.srt |
| Montagem | quadros, narração e legenda | renders/revisao.mp4 |
| QA | renders/revisao.mp4 | qa/parecer.md e qa/aprovacao.json |
| Publicação | revisao.mp4 e aprovacao.json | publicacao/recibo.json |
Nenhum arquivo é escrito por duas etapas, e a publicação lê a aprovação do QA.
A etapa de QA, o controle de qualidade antes da publicação, combina a revisão de frames pelo Claude com a sua revisão de áudio e transições; a rubrica está na aula de QA visual. A publicação usa uma integração por plataforma, com cotas próprias, ensinada na aula de publicação por API.
clock Registrar o modelo e a data de desligamento
Toda etapa que chama um modelo generativo leva dois campos a mais no contrato: o ID exato do modelo e a data em que o fornecedor anunciou que ele sai do ar. Sem isso, um pipeline agendado quebra numa madrugada qualquer, com a falha disfarçada de erro de rede. Desde 24/09/2026, a Videos API da OpenAI e os aliases sora-2 e sora-2-pro estão desligados, sem substituto; os previews do Veo 3.1 saem da Gemini API em 22/10/2026, com gemini-omni-1.1-flash indicado como substituto; e a ElevenLabs desliga o Seedance 1.5 Pro em 11/11/2026. Nenhuma etapa do P1 depende do Sora, e o catálogo da aula anterior não deve listá-lo como opção viva.
Grave esses dados em config/modelos.toml, que já existe na árvore do projeto, e faça cada contrato apontar para a chave dele. Se a data de desligamento está a menos de 30 dias, troque o modelo antes de agendar a próxima semana; se o fornecedor não anunciou data, registre desliga_em = "" e confira a página de descontinuações a cada ciclo. Está pronto quando nenhum contrato cita um ID que já saiu do ar e o script de desenho lê o TOML sem campo vazio em etapa paga.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
# Datas conferidas em 12/10/2026 nas páginas de descontinuação de cada fornecedor.
# Campo vazio em desliga_em significa: sem data anunciada, conferir a cada ciclo.
[voz]
id = "eleven_v4"
fornecedor = "elevenlabs"
desliga_em = ""
continuidade = ["previous_text", "future_text"] # até 100 caracteres cada
[broll]
id = "gemini-omni-1.1-flash"
fornecedor = "google"
desliga_em = ""
substitui = "veo-3.1-fast-generate-preview" # sai da Gemini API em 2026-10-22
[broll_antigo]
id = "veo-3.1-fast-generate-preview"
fornecedor = "google"
desliga_em = "2026-10-22"
substituto = "gemini-omni-1.1-flash"
Criar as pastas e gerar um manifesto que se confere
O manifesto usa só caminhos relativos, como audio/narracao.mp3, para o projeto funcionar em qualquer computador e em qualquer agente; a diferença entre caminho relativo e absoluto está na aula da bancada. Os brutos ficam em midia/raw/ e nunca são sobrescritos, e tudo o que é derivado vai para outra pasta. O hábito de versionar só o que é texto e deixar a mídia fora do Git vem de criar o primeiro repositório; a ideia de um arquivo de regras que o agente lê sempre aparece em o CLAUDE.md como constituição do projeto.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
A árvore abaixo é a única do curso. Todas as aulas seguintes rodam os comandos na raiz video-ia, gravam e leem nestes caminhos e não criam outro projeto. Pastas que só entram em uso mais adiante, como edicao/ para a lista de cortes, estado/ para o pipeline que retoma de onde parou e privado/ para vozes autorizadas e tokens, já nascem aqui. Os projetos de composição do Remotion e do HyperFrames ficam em composicoes/<nome>/, com as pastas internas que cada ferramenta exige, e gravam o MP4 em renders/.
video-ia/
├── CLAUDE.md, AGENTS.md, .mcp.json regras dos agentes
├── .env, .env.example, .gitignore chaves e exclusões do Git
├── .claude/ e .agents/ configuração do Claude Code e do Codex
├── config/ catalogo.json, pipeline.json, modelos.toml
│ └── schemas/ formatos de resposta do Codex
├── briefing/ um briefing por vídeo
├── marca/ paleta e fontes/
├── roteiro/ roteiro.md aprovado
├── storyboard/ cenas.json, quadros, cenas_video.json
│ └── prompts/ prompt de vídeo por cena
├── audio/ narração, trilha e efeitos
├── transcricoes/ JSON do Scribe com tempo por palavra
├── legendas/ SRT e JSON por palavra
├── edicao/ lista de cortes aprovada
├── midia/
│ ├── raw/ brutos, nunca sobrescritos
│ └── gerados/ b-roll gerado, frames e clipes
├── composicoes/<nome>/ projetos Remotion e HyperFrames
├── renders/ MP4 de revisão e de entrega
├── qa/ frames/, parecer, aprovação e auditoria
├── publicacao/ recibo de cada envio
├── estado/ estado do pipeline e das tarefas
├── custos/ custo de cada chamada paga
├── privado/ vozes autorizadas e tokens, fora do Git
├── logs/ saída de comandos e relatórios
└── scripts/ todos os scripts do curso
Rode o bloco do seu sistema na pasta video-ia. Os dois criam as mesmas pastas, escrevem um briefing só se ele ainda não existir e acrescentam ao .gitignore, a lista do que o Git deve ignorar, a chave, o estado local, a pasta privada e os arquivos pesados.
Criar a estrutura de pastas
macOS e Linux
Salve como scripts/criar_pastas.sh (crie a pasta scripts antes, se ela ainda não existir) e rode bash scripts/criar_pastas.sh.
#!/usr/bin/env bash
# Cria a estrutura do projeto sem sobrescrever nada. Rode na pasta video-ia.
set -euo pipefail
# O catálogo da aula 01 prova que você está na pasta certa.
test -f config/catalogo.json || {
printf 'Entre na pasta video-ia antes de continuar.\n' >&2
exit 1
}
mkdir -p briefing marca/fontes roteiro storyboard/prompts audio transcricoes \
legendas edicao midia/raw midia/gerados composicoes renders qa/frames \
publicacao estado custos privado logs scripts config/schemas
# Só escreve o briefing se ele ainda não existir.
if [ ! -e briefing/receita.md ]; then
cat > briefing/receita.md <<'MD'
# Briefing do P1
- Tema: dica rápida de receita
- Idioma: português do Brasil
- Formato final: 9:16
- Duração-alvo: 60 segundos
- Recursos: storyboard, narração e legenda
- B-roll gerado: opcional
- Publicação: só depois da aprovação humana
MD
fi
# Chave e arquivos pesados ficam fora do Git.
touch .gitignore
for regra in '.env' '.venv/' 'node_modules/' 'audio/' 'midia/' 'renders/' \
'logs/' 'qa/frames/' 'publicacao/' 'custos/' 'estado/' 'privado/'; do
grep -Fqx "$regra" .gitignore || printf '%s\n' "$regra" >> .gitignore
done
printf 'Estrutura pronta. Briefing existente preservado.\n'
Windows
Cole no PowerShell aberto na pasta video-ia. O "@ que fecha o briefing precisa ser o primeiro caractere da linha, sem espaço antes; o @" de abertura fica no fim da linha da atribuição, seguido de quebra de linha.
# Cria a estrutura do projeto sem sobrescrever nada. Rode na pasta video-ia (PowerShell).
if (-not (Test-Path "config/catalogo.json")) {
Write-Error "Entre na pasta video-ia antes de continuar."
exit 1
}
$pastas = "briefing", "marca/fontes", "roteiro", "storyboard/prompts", "audio",
"transcricoes", "legendas", "edicao", "midia/raw", "midia/gerados",
"composicoes", "renders", "qa/frames", "publicacao", "estado", "custos",
"privado", "logs", "scripts", "config/schemas"
foreach ($p in $pastas) {
# -Force em diretório só garante que ele exista; não apaga conteúdo.
New-Item -ItemType Directory -Force -Path $p | Out-Null
}
# Só escreve o briefing se ele ainda não existir.
if (-not (Test-Path "briefing/receita.md")) {
$briefing = @"
# Briefing do P1
- Tema: dica rápida de receita
- Idioma: português do Brasil
- Formato final: 9:16
- Duração-alvo: 60 segundos
- Recursos: storyboard, narração e legenda
- B-roll gerado: opcional
- Publicação: só depois da aprovação humana
"@
Set-Content -Path "briefing/receita.md" -Value $briefing -Encoding utf8
}
# Chave e arquivos pesados ficam fora do Git.
if (-not (Test-Path ".gitignore")) { New-Item -ItemType File -Path ".gitignore" | Out-Null }
$atuais = @(Get-Content ".gitignore")
foreach ($regra in ".env", ".venv/", "node_modules/", "audio/", "midia/", "renders/",
"logs/", "qa/frames/", "publicacao/", "custos/", "estado/", "privado/") {
if ($atuais -notcontains $regra) { Add-Content -Path ".gitignore" -Value $regra }
}
Write-Host "Estrutura pronta. Briefing existente preservado."
Com as pastas prontas, o script de desenho grava config/pipeline.json e fluxograma.md. Antes de gravar, ele aplica quatro regras do contrato: nenhum id repetido, nenhuma dependência fora de ordem, nenhum caminho absoluto ou com .. e nenhum arquivo escrito por duas etapas. Salve como scripts/desenhar_pipeline.py e rode python scripts/desenhar_pipeline.py (no macOS e no Linux, python3).
"""Desenha o pipeline do P1: grava config/pipeline.json e fluxograma.md.
Não gera mídia nem chama APIs. Rode na pasta video-ia:
python scripts/desenhar_pipeline.py
python scripts/desenhar_pipeline.py --falhar voz
"""
import argparse
import json
from pathlib import Path
raiz = Path(__file__).resolve().parents[1]
catalogo = json.loads((raiz / "config/catalogo.json").read_text(encoding="utf-8"))
# Ordem do P1: cada etapa só depende de etapas que vêm antes dela.
etapas = [
{"id": "roteiro", "depende_de": [], "responsavel": catalogo["direcao"]["modelo"],
"entradas": ["briefing/receita.md"], "saidas": ["roteiro/roteiro.md", "storyboard/cenas.json"],
"aprovacao_humana": True},
{"id": "imagens", "depende_de": ["roteiro"], "responsavel": catalogo["storyboard"]["modelo"],
"entradas": ["storyboard/cenas.json"], "saidas": ["storyboard/quadros.json"],
"aprovacao_humana": True},
{"id": "voz", "depende_de": ["roteiro"], "responsavel": catalogo["narracao"]["modelo"],
"entradas": ["roteiro/roteiro.md"], "saidas": ["audio/narracao.mp3"],
"aprovacao_humana": True},
{"id": "transcricao", "depende_de": ["voz"], "responsavel": catalogo["transcricao"]["modelo"],
"entradas": ["audio/narracao.mp3"], "saidas": ["transcricoes/narracao.json"],
"aprovacao_humana": False},
{"id": "legendas", "depende_de": ["transcricao"], "responsavel": "script local",
"entradas": ["transcricoes/narracao.json"], "saidas": ["legendas/narracao.srt"],
"aprovacao_humana": False},
{"id": "montagem", "depende_de": ["imagens", "voz", "legendas"], "responsavel": "FFmpeg",
"entradas": ["storyboard/quadros.json", "audio/narracao.mp3", "legendas/narracao.srt"],
"saidas": ["renders/revisao.mp4"], "aprovacao_humana": False},
{"id": "qa", "depende_de": ["montagem"], "responsavel": "Claude sobre frames e revisão humana",
"entradas": ["renders/revisao.mp4"], "saidas": ["qa/parecer.md", "qa/aprovacao.json"],
"aprovacao_humana": True},
{"id": "publicacao", "depende_de": ["qa"], "responsavel": "script da plataforma",
"entradas": ["renders/revisao.mp4", "qa/aprovacao.json"], "saidas": ["publicacao/recibo.json"],
"aprovacao_humana": True},
]
# Quatro regras do contrato, conferidas antes de gravar qualquer arquivo.
vistos, saidas = set(), set()
for etapa in etapas:
if etapa["id"] in vistos:
raise SystemExit(f"Id de etapa repetido: {etapa['id']}")
if not set(etapa["depende_de"]) <= vistos:
raise SystemExit(f"Dependência fora de ordem em: {etapa['id']}")
for caminho in etapa["entradas"] + etapa["saidas"]:
p = Path(caminho)
if p.is_absolute() or ".." in p.parts:
raise SystemExit(f"Use caminho relativo dentro do projeto: {caminho}")
for saida in etapa["saidas"]:
if saida in saidas:
raise SystemExit(f"Duas etapas escrevem o mesmo arquivo: {saida}")
saidas.add(saida)
vistos.add(etapa["id"])
parser = argparse.ArgumentParser()
parser.add_argument("--falhar", metavar="ETAPA", help="simula a falha de uma etapa")
args = parser.parse_args()
if args.falhar:
if args.falhar not in vistos:
raise SystemExit(f"Etapa desconhecida. Use uma destas: {', '.join(e['id'] for e in etapas)}")
paradas = {args.falhar}
for etapa in etapas: # a lista já está em ordem de dependência
if paradas & set(etapa["depende_de"]):
paradas.add(etapa["id"])
livres = [e["id"] for e in etapas if e["id"] not in paradas]
print(f"Falha simulada em: {args.falhar}")
print("Ficam paradas:", ", ".join(e["id"] for e in etapas if e["id"] in paradas - {args.falhar}) or "nenhuma")
print("Seguem livres:", ", ".join(livres) or "nenhuma")
raise SystemExit(0)
manifesto = {"data_referencia": "2026-10-12", "projeto": "P1", "duracao_alvo_s": 60,
"formato": "9:16", "etapas": etapas}
(raiz / "config/pipeline.json").write_text(
json.dumps(manifesto, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
linhas = ["# Fluxograma do P1", "", "Plano de produção; não comprova execução.", ""]
for etapa in etapas:
linhas += [
f"## {etapa['id']}",
f"- Recebe de: {', '.join(etapa['depende_de']) or 'briefing'}",
f"- Responsável: {etapa['responsavel']}",
f"- Entradas: {', '.join(etapa['entradas'])}",
f"- Saídas: {', '.join(etapa['saidas'])}",
f"- Aprovação humana: {'sim' if etapa['aprovacao_humana'] else 'não'}",
"",
]
(raiz / "fluxograma.md").write_text("\n".join(linhas), encoding="utf-8")
print(f"OK: {len(etapas)} etapas conferidas; config/pipeline.json e fluxograma.md gravados.")
Desenhar e conferir o pipeline do P1
Sete passos, nenhuma chamada paga. O catálogo da aula 01 precisa estar em config/catalogo.json.
Passo 1: Abra o catálogo da aula anterior
Deu certo quando: Cada serviço do catálogo tem um papel no pipeline.
Erro comum: Redesenhar tudo do zero em vez de aproveitar o catálogo.
Passo 2: Crie as pastas com o bloco do seu sistema
Deu certo quando: midia/raw e renders existem como pastas separadas.
Erro comum: Gravar o render por cima do arquivo bruto.
Passo 3: Complete o briefing da receita
Deu certo quando: Formato, duração-alvo e idioma estão escritos em briefing/receita.md.
Erro comum: Pedir um vídeo bom sem critério de entrega.
Passo 4: Rode o script de desenho
Deu certo quando: O terminal mostra OK com 8 etapas conferidas.
Erro comum: Achar que o manifesto já contém mídia produzida.
Passo 5: Siga uma saída até a próxima entrada
Deu certo quando: Você vê a transcrição alimentar a legenda e a legenda alimentar a montagem.
Erro comum: Gerar a legenda antes de saber qual áudio será usado.
Passo 6: Marque os pontos de aprovação
Deu certo quando: Roteiro, imagens, voz, QA e publicação aparecem com aprovação humana.
Erro comum: Tratar conclusão técnica como aprovação editorial.
Passo 7: Simule a falha da voz
Deu certo quando: O ensaio lista cinco etapas paradas e duas livres.
Erro comum: Publicar porque um MP4 antigo continua na pasta.
No fim você tem: Um manifesto e um fluxograma do P1 que qualquer agente lê e que nenhuma etapa contradiz.
Simular uma falha antes de gastar
Dry-run, a execução de ensaio, percorre o plano sem fazer as chamadas pagas, como um ensaio geral sem plateia. A opção --falhar do script mostra o que fica parado quando uma etapa quebra e o que pode seguir enquanto você corrige.
# Ensaio de falha: o que para se a narração falhar? (Windows: troque python3 por python)
python3 scripts/desenhar_pipeline.py --falhar voz
# Falha simulada em: voz
# Ficam paradas: transcricao, legendas, montagem, qa, publicacao
# Seguem livres: roteiro, imagens
python3 scripts/desenhar_pipeline.py --falhar imagens
# Falha simulada em: imagens
# Ficam paradas: montagem, qa, publicacao
# Seguem livres: roteiro, voz, transcricao, legendas
Quatro decisões saem desse ensaio. Se a voz mudar, refaça a transcrição e a legenda, porque os tempos mudaram junto. Se o vídeo é só imagem com locução, deixe o b-roll gerado de fora e não pague por ele. Se o QA reprovar, volte à etapa dona do defeito em vez de regenerar tudo. Se faltar aprovação humana, a publicação fica pendente, mesmo com um MP4 pronto na pasta.
Quem já integrou serviços por webhook reconhece a lógica de entrada, saída e condição em projetar integrações com APIs REST. Para pedir uma segunda leitura do desenho, cole o pedido abaixo no Codex aberto na pasta video-ia.
Guia prático: validar o manifesto com JSON Schema e desenhar o fluxo em Mermaid
O script da aula confere quatro regras antes de gravar. Aqui o arquivo ganha um contrato formal: um JSON Schema, a descrição em JSON dos campos que o manifesto precisa ter e do tipo de cada um, que recusa campo com erro de digitação e caminho fora do projeto e lista todos os erros de uma vez. O mesmo script desenha o pipeline em Mermaid, linguagem de diagramas em texto que o GitHub transforma em fluxograma.
Funções, casos de uso e aplicações
Funções
O que valida e o que desenha o manifesto do P1
| Função ou recurso | O que faz | Quando usar | Desde |
|---|---|---|---|
| validate() do jsonschema | Confere um JSON contra o schema e para no primeiro problema | Teste rápido dentro de outro script | jsonschema 4.26.0, de 07/01/2026 |
| Draft202012Validator.iter_errors() | Devolve todos os erros de uma vez, cada um com o caminho do campo | Revisão do manifesto antes de rodar o pipeline | jsonschema 4.26.0, de 07/01/2026 |
| additionalProperties: false | Recusa campo que o schema não conhece, como aprovacao no lugar de aprovacao_humana | Em todo objeto de etapa | JSON Schema Draft 2020-12 |
| pattern nas listas de caminhos | Recusa caminho absoluto, com .. ou com letra de unidade (C:) | Em entradas e saidas de cada etapa | JSON Schema Draft 2020-12 |
| Bloco mermaid no GitHub | Desenha graph TD como fluxograma em issues, pull requests, wikis e arquivos .md | Revisar o pipeline sem ferramenta de desenho | Na documentação do GitHub em 12/10/2026 |
| Bloco mermaid com info | Mostra a versão do Mermaid que o GitHub usa | Quando uma forma do diagrama não aparece | Na documentação do GitHub em 12/10/2026 |
O jsonschema 4.26.0 pede Python 3.10 ou superior; a bancada do curso já usa 3.12.
Casos de uso
Coordenadora pedagógica de um cursinho pré-vestibular em Fortaleza, que transforma aulas gravadas em resumos de 60 segundos
Educação, preparação para vestibular
Dor
Três monitores editavam o manifesto à mão, e um campo escrito aprovacao, no lugar de aprovacao_humana, tirou o portão de QA da publicação sem ninguém perceber.
Solução
Ela pôs o validador como primeiro passo do pipeline. O erro de digitação passou a aparecer com o caminho exato do campo, e o fluxograma em Mermaid entrou no README do repositório.
Resultado
Observar, a cada semana, quantos manifestos o validador recusa e se o número cai depois que os monitores passam a ler o fluxograma antes de editar.
Cenário construído para fins didáticos. Números não correspondem a cliente específico.
Produtor de uma agência de marketing em Porto Alegre que monta pipelines de vídeo para clientes de comércio eletrônico
Marketing digital, agência
Dor
Os clientes precisavam aprovar o processo e recebiam um JSON de 200 linhas que ninguém lia.
Solução
Ele passou a anexar ao pull request o fluxograma-mermaid.md, que o GitHub desenha, com as etapas de aprovação humana em hexágono.
Resultado
Acompanhar se as dúvidas do cliente sobre quem aprova o quê diminuem nas próximas revisões de processo.
Cenário construído para fins didáticos. Números não correspondem a cliente específico.
Na prática
Ative o .venv da aula 03, instale o pacote com pip install "jsonschema>=4.26" e salve o script como scripts/validar_pipeline.py. Ele lê o config/pipeline.json que o desenhar_pipeline.py gravou, imprime cada erro com o caminho do campo (por exemplo, etapas/2/saidas/0) e, só com o manifesto válido, grava fluxograma-mermaid.md. Etapa com aprovação humana vira hexágono no desenho, e cada seta mostra de qual etapa a seguinte depende.
"""Valida config/pipeline.json contra um JSON Schema e desenha o fluxo em Mermaid.
Rode na pasta video-ia (com o .venv ativo):
pip install "jsonschema>=4.26"
python scripts/validar_pipeline.py
"""
import json
from pathlib import Path
from jsonschema import Draft202012Validator
CAMINHO = r"^(?!/)(?!.*\.\.)[^:]*$" # relativo, sem .. e sem letra de unidade (C:)
ETAPA = {
"type": "object",
"required": ["id", "depende_de", "responsavel", "entradas", "saidas", "aprovacao_humana"],
"additionalProperties": False, # campo com erro de digitação vira erro, não passa calado
"properties": {
"id": {"type": "string", "pattern": "^[a-z_]+$"},
"depende_de": {"type": "array", "items": {"type": "string"}, "uniqueItems": True},
"responsavel": {"type": "string", "minLength": 3},
"entradas": {"type": "array", "items": {"type": "string", "pattern": CAMINHO}, "minItems": 1},
"saidas": {"type": "array", "items": {"type": "string", "pattern": CAMINHO}, "minItems": 1},
"aprovacao_humana": {"type": "boolean"},
},
}
SCHEMA = {
"type": "object",
"required": ["data_referencia", "projeto", "formato", "etapas"],
"properties": {
"data_referencia": {"type": "string", "pattern": r"^\d{4}-\d{2}-\d{2}$"},
"formato": {"enum": ["9:16", "16:9"]},
"etapas": {"type": "array", "items": ETAPA, "minItems": 1},
},
}
manifesto = json.loads(Path("config/pipeline.json").read_text(encoding="utf-8"))
erros = sorted(Draft202012Validator(SCHEMA).iter_errors(manifesto), key=lambda e: list(e.path))
for erro in erros: # iter_errors devolve TODOS os erros, não só o primeiro
print("ERRO em", "/".join(map(str, erro.path)) or "raiz", "->", erro.message)
if erros:
raise SystemExit(1)
# Mermaid: o GitHub desenha o bloco ```mermaid como fluxograma no próprio .md
linhas = ["```mermaid", "graph TD;"]
for e in manifesto["etapas"]:
forma = f'{e["id"]}{{{{"{e["id"]}"}}}}' if e["aprovacao_humana"] else e["id"]
linhas += [f" {d}-->{forma};" for d in e["depende_de"]] or [f" {forma};"]
Path("fluxograma-mermaid.md").write_text("\n".join(linhas + ["```", ""]), encoding="utf-8")
print(f"OK: {len(manifesto['etapas'])} etapas válidas; fluxograma-mermaid.md gravado.")Pôr o schema na frente do pipeline
Cinco passos na pasta video-ia, sem chamada paga.
Passo 1: Gere o manifesto com o script da aula
python scripts/desenhar_pipeline.py
Deu certo quando: config/pipeline.json existe com as oito etapas.
Erro comum: Editar o pipeline.json à mão e depois rodar o desenhar_pipeline.py por cima.
Passo 2: Instale o jsonschema dentro do .venv
Deu certo quando: pip show jsonschema mostra 4.26.0 ou superior.
Erro comum: Instalar fora do ambiente virtual e o script não achar o pacote.
Passo 3: Rode o validador
Deu certo quando: Aparece OK: 8 etapas válidas; fluxograma-mermaid.md gravado.
Erro comum: Ler só a primeira linha de erro: o iter_errors lista todas.
Passo 4: Faça um teste negativo e desfaça
Troque aprovacao_humana por aprovacao numa etapa, rode de novo e volte o nome original.
Deu certo quando: Aparece Additional properties are not allowed com o caminho da etapa.
Erro comum: Esquecer a alteração no arquivo e deixar o pipeline parado de verdade.
Passo 5: Abra o fluxograma no GitHub
Deu certo quando: O bloco vira desenho, com roteiro, imagens, voz, QA e publicação em hexágono.
Erro comum: Abrir num editor sem suporte a Mermaid e concluir que o arquivo está quebrado.
No fim você tem: Um manifesto com contrato formal, erros listados pelo caminho do campo e um fluxograma que o GitHub desenha.
Armadilhas
O schema valida a forma; o desenho valida a ordem
JSON Schema confere tipo e nome de cada campo, mas não sabe se uma dependência vem antes da etapa.
- Ordem das etapas e saída duplicada seguem no desenhar_pipeline.py
- Sem additionalProperties false, erro de digitação passa calado
- Mude o schema e o manifesto no mesmo commit
- Hexágono é desenho: a aprovação vale pelo qa/aprovacao.json
O teste: Troque o nome de um campo de propósito e veja o validador recusar com o caminho exato.
alexandrecaramaschi.com/educacao/frontends-com-vibecoding
Na Cozinha da Rafa, cada receita tem um briefing. O vídeo longo do bolo de rolo e os dois cortes 9:16 da semana compartilham o roteiro-base e os brutos, mas cada saída tem enquadramento, legenda, QA e recibo próprios, porque um corte reprovado não pode segurar os outros dois. O manifesto desta aula cobre só o P1, o corte de 60 segundos; a semana inteira entra na aula de orquestração.
Os termos novos desta aula ficam reunidos abaixo.
Glossário rápido
pipeline
Linha de produção do vídeo: cada etapa recebe um arquivo, faz um trabalho e entrega outro arquivo para a etapa seguinte.
contrato de etapa
Etiqueta de entrega de uma etapa: o que entra, o que faz, o que sai e o que precisa acontecer para avançar.
manifesto
Ficha de produção em JSON que reúne os contratos de todas as etapas de um vídeo.
dry-run
Execução de ensaio que percorre o plano sem fazer chamadas pagas, como um ensaio geral sem plateia.
Monte as pastas, rode o script de desenho e simule a falha da voz. Está pronto quando fluxograma.md descreve as oito etapas, nenhum bruto é destino de render, o JSON de palavras e o SRT aparecem como arquivos distintos e a publicação depende do QA e de uma aprovação escrita.
Seu caderno neste capítulo
Abrir o caderno completoSelecione um trecho do capítulo para destacar ou anotar. Nos vídeos e áudios, use Anotar este momento. No teclado, selecione com Shift e as setas e use Alt+Shift+D para destacar ou Alt+Shift+N para anotar.
Salvo neste navegador. Entre na sua conta para levar o caderno a outros aparelhos.
Entre na sua conta para compartilhar o que aprendeu e convidar alguém para estudar com você.
Conexões deste capítulo
Veja o que estudar antes e para onde seguir depois, explore os conceitos e compare abordagens em outros cursos. Sugestões marcadas como “sugerido pelo grafo” vêm dos assuntos em comum, não do índice do curso.
Estude antes
- CursoClaude Code CLI: Programação com IA
- CursoAstra profundosugerido pelo grafoA quinta parte do Astra planeja o vídeo e edita o material bruto com o modelo dirigindo a ferramenta. O curso de vídeo com IA aprofunda esse trabalho com Claude Code, Codex e ElevenLabs, do roteiro à publicação. O grafo já sugeria esta ordem pela regra de entrada da trilha; com a ordem anterior curada, ela passa a ser declarada (Etapa 4, wave 3).
- CursoSetup Completo: do zero ao Claude Codesugerido pelo grafo7 capítulos de “Vídeo com IA: Claude Code, Codex e ElevenLabs” usam conceitos apresentados em “Setup Completo: do zero ao Claude Code”.
Depois, siga para
- CursoFrontends com Vibecodingsugerido pelo grafo21 capítulos de “Frontends com Vibecoding” usam conceitos apresentados em “Vídeo com IA: Claude Code, Codex e ElevenLabs”.
- CursoDo Agile ao Agentic Operating Modelsugerido pelo grafo5 capítulos de “Do Agile ao Agentic Operating Model” usam conceitos apresentados em “Vídeo com IA: Claude Code, Codex e ElevenLabs”.
- CursoAgentes de IA Autônomos: Do Conceito à Produçãosugerido pelo grafo7 capítulos de “Agentes de IA Autônomos: Do Conceito à Produção” usam conceitos apresentados em “Vídeo com IA: Claude Code, Codex e ElevenLabs”.
- CursoLLM FinOps: o custo da IA para quem assina o orçamentosugerido pelo grafo4 capítulos de “LLM FinOps: o custo da IA para quem assina o orçamento” usam conceitos apresentados em “Vídeo com IA: Claude Code, Codex e ElevenLabs”.
Conceitos deste capítulo
O mesmo assunto em outros cursos
- Frontends com VibecodingEspecificar, medir e produzir as cenas da máquinaExaminar conexões de Especificar, medir e produzir as cenas da máquina
- Bastidores: Como Este Portal Foi ConstruídoAgentes em worktrees: produção em paraleloExaminar conexões de Agentes em worktrees: produção em paralelo
- SO nativo de IAOs primeiros 30 diasExaminar conexões de Os primeiros 30 dias
- Astra profundoMontar um filme a partir do material disponívelExaminar conexões de Montar um filme a partir do material disponível
Leve uma ideia para a prática
Escolha uma atividade no painel e volte a este curso quando quiser.
Atividades e evolução ficam reunidas no painel da sua conta.
Laboratórios ao vivo deste curso
Cada laboratório monta a biblioteca real dentro da aula, com controles para você mexer e o código do exemplo para copiar. O texto de reserva descreve a demonstração para quem lê sem JavaScript. O link abre o capítulo já no ponto do laboratório.
MediaRecorder, Canvas 2D e Long Animation Frames (plataforma)
Grave a cena em tempo real e veja os quadros que se perdem
Suba as partículas, force um bloqueio de 300 ms e grave seis segundos; compare com o render quadro a quadro desta aula.
Pacote
Abrir no capítuloMontar vídeo em HTML com HyperFrames e escolher entre ele e o Remotionsem pacoteMotion
Ver agentes em paralelo trocando mensagens numa linha do tempo
Reproduza a cena, percorra o tempo pelo controle e compare o tempo de parede com a soma das barras de cada agente.
Pacote
Abrir no capítuloParalelizar cenas com subagentes sem estourar o limite das APIsmotionReact (sem dependência extra), com as APIs do Veo e do fal.ai
Prompt de vídeo em cinco camadas, pronto para a API
Escolha plano, câmera, luz, ação e áudio e copie o prompt e o JSON para o Veo ou para o fal.ai.
Pacote
Abrir no capítuloEscrever prompt de vídeo em cinco camadas e manter o personagem consistentereactReact (sem dependência extra), com o comando para o FFmpeg
Corte o vídeo apagando palavras da transcrição
Aperte as palavras para removê-las, ligue a remoção de pausas e copie o comando FFmpeg e a legenda SRT gerados.
Pacote
Abrir no capítuloRemover pausas e reenquadrar o vídeo de 16:9 para 9:16 com legenda por palavrareactReact (sem dependência extra)
Quanto custa cada etapa do seu pipeline de vídeo
Troque a ferramenta de cada etapa e o percentual de b-roll e veja qual etapa pesa no custo por minuto e por vídeo.
Pacote
Abrir no capítuloOrquestrar o pipeline com etapas idempotentes e teto de gastoreact
Capítulos vizinhos em Vídeo com IA: Claude Code, Codex e ElevenLabs
- 01Escolher uma arquitetura de vídeo com IA que funciona em outubro de 2026
- 02Desenhar o pipeline de vídeo do briefing à publicação
- 03Montar a bancada de vídeo com IA mesmo sem nunca ter usado o terminal
- 04Cortar, juntar, mixar e exportar vídeo com FFmpeg sem abrir editor
- 05Montar vídeo em React com Remotion e renderizar na sua máquina ou na AWS