Vídeo com IA: Claude Code, Codex e ElevenLabs · Capítulo 6 de 25 · 27 min
Montar vídeo em HTML com HyperFrames e escolher entre ele e o Remotion
Escreva o vídeo em HTML com HyperFrames e aprove no preview antes de renderizar o lote, com um critério claro para decidir entre ele e o Remotion em cada peça.
Este capítulo faz parte do curso gratuito Vídeo com IA: Claude Code, Codex e ElevenLabs.
Agentes de código escrevem HTML e CSS melhor do que qualquer outra coisa. O HyperFrames parte dessa constatação: se o agente já escreve página, que escreva o vídeo como página. Uma linha do tempo GSAP pausada é avançada quadro a quadro por um Chrome sem interface, e o FFmpeg codifica o resultado.
Sem conhecer o contrato da composição, o vídeo que o agente entregar falha de formas silenciosas: um áudio sem id some do render, um título fica sob a interface do Reels, uma fonte carregada da internet não chega a tempo do primeiro quadro. E sem um critério de escolha, cada peça vira debate entre Remotion e HyperFrames, quando a resposta depende de quatro perguntas objetivas.
Nesta aula você monta à mão uma composição 9:16, passa pelo ciclo de verificação que a skill oficial impõe (ela proíbe renderizar só porque o check passou), renderiza em rascunho, em entrega e em lote, e fecha com a tabela que decide entre os dois motores por peça.
Entender o render determinístico do HyperFrames
O HyperFrames é um framework de código aberto da HeyGen, sob licença Apache-2.0, com o lema “Write HTML. Render video. Built for agents.” Em 12/10/2026, a versão vigente é a 0.8.149, publicada em 11/10/2026; como saem várias versões por dia, confira a sua com npm view hyperframes version e mantenha uma igual ou maior que a do curso. Ela exige Node.js 22 ou superior e FFmpeg. Ele não gera imagem: transforma em MP4 o HTML, o CSS, a mídia e as animações que você escreve.
A palavra que importa é determinístico: a mesma entrada produz sempre o mesmo arquivo, como uma receita pesada em gramas em vez de “uma pitada”. Por isso a timeline GSAP fica com paused: true. Quem decide o instante de cada quadro é o motor do render, e não o relógio do navegador, e um quadro pesado demora mais para sair em vez de ser descartado.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
O laboratório abaixo mostra o lado de cima da figura: uma cena gravada em tempo real pelo próprio navegador. Force o bloqueio de 300 ms e repare no que acontece com os quadros; é o problema que a timeline pausada resolve.
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.
Demonstração feita só com APIs do navegador: uma cena em Canvas 2D com centenas a milhares de partículas, um medidor de quadros por segundo e de quadros longos, e um botão que grava seis segundos da cena com captureStream e MediaRecorder. Quando o quadro fica pesado, o medidor registra os quadros longos e a gravação em tempo real perde suavidade. É o contraste com o render quadro a quadro do HyperFrames, em que o motor espera cada quadro ficar pronto antes de seguir.
A demonstração interativa carrega quando este trecho entra na tela.
A CLI cobre o ciclo inteiro: init cria o projeto (fora de um terminal interativo, como em script ou CI, ele cria direto o modelo em branco; no terminal, --example blank ou --non-interactive pulam as perguntas), catalog e add buscam e instalam blocos do registry, lint e check validam, preview abre o Studio em http://localhost:3002 e render gera o arquivo. Para nuvem, há cloud render (nuvem da HeyGen, com 4K a 1,5x e projeto de até 200 MB), lambda deploy, lambda render e lambda destroy na sua conta AWS, e cloudrun render no Google Cloud. A instalação das skills e do plugin que ensinam tudo isso ao agente está em skills de vídeo no Claude Code.

Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
#!/usr/bin/env bash
# scripts/aula06_ambiente.sh: confere o ambiente, cria o projeto e busca blocos prontos.
# Uso: bash scripts/aula06_ambiente.sh (na raiz video-ia; o projeto nasce em composicoes/cozinha-corte/)
set -euo pipefail
# 1) Pré-requisitos: Node.js 22 ou superior e FFmpeg no PATH
node -v # v22.x ou maior
ffmpeg -version | head -1
npx -y hyperframes@latest doctor # confere Chrome, FFmpeg e o ambiente
# 2) Skills e plugin do HyperFrames para o agente: instalação na Aula 08.
# 3) Projeto. --example blank escolhe o modelo em branco sem perguntar; em script ou CI o init já faz isso sozinho
cd composicoes
npx hyperframes init cozinha-corte --example blank
cd cozinha-corte # daqui em diante, a raiz video-ia fica em ../..
mkdir -p assets
# assets/ recebe CÓPIAS: brutos de midia/raw/ (só lidos), vozes e trilha de audio/, fonte de marca/fontes/
for f in ../../midia/raw/broll_massa.mp4 ../../midia/raw/broll_enrolar.mp4 ../../audio/voz_abertura.mp3 \
../../audio/voz_massa.mp3 ../../audio/voz_enrolar.mp3 ../../audio/trilha.mp3 ../../marca/fontes/fonte-titulo.woff2; do
cp "$f" assets/ 2>/dev/null || echo "Falta $f: grave ou gere o arquivo antes do render"
done
# 4) Procure bloco pronto antes de escrever animação à mão (~400 blocos e componentes).
# A busca é local e funciona melhor com a frase em inglês.
npx hyperframes catalog --type block --tag social
npx hyperframes catalog --query "lower third"
# npx hyperframes add <nome-do-bloco-que-o-catalog-devolveu>Escrever a composição com os atributos data-*
A composição é um index.html comum com um contrato de tempo. A raiz declara o id, o tamanho do quadro e a duração; cada elemento com data-start vira um clip, que o HyperFrames mostra e esconde pela janela de tempo declarada. A timeline GSAP é uma só, pausada e registrada em window.__timelines com a mesma chave do data-composition-id. O que puder vir pronto vem do registry, com cerca de 400 blocos; o vocabulário de movimento por trás das animações está no curso de frontend, em projetar movimento, assinatura e narrativas por rolagem.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
Os atributos que a composição usa
| Atributo | Onde | O que faz |
|---|---|---|
| data-composition-id | Raiz | Nome da composição; igual à chave em window.__timelines |
| data-width e data-height | Raiz | Tamanho do quadro em pixels, como 1080 e 1920 |
| data-duration | Raiz e clips | Na raiz, a duração do render em segundos; no clip, quanto tempo ele fica |
| data-start | Clips | Instante em que o clip entra; é o que transforma o elemento em clip |
| data-track-index | Clips | Faixa de exibição no Studio; o render não lê |
| data-volume | audio | Ganho fixo do áudio: 1 é o original, 0.1 é 10% |
| data-var-text e data-var-src | Texto e mídia | Ligam o texto ou o arquivo a uma variável do lote |
Todo audio precisa de id, vídeo sem som leva muted e nenhuma mídia leva crossorigin.
<!doctype html>
<!-- index.html: cartão de abertura de 6 s, 1080x1920, com b-roll, voz, trilha e texto animado.
As variáveis declaradas no <html> deixam o lote (render --batch) trocar título, b-roll e voz. -->
<html
lang="pt-BR"
data-composition-variables='[
{"id":"titulo","type":"string","label":"Título","default":"Bolo de rolo"},
{"id":"broll","type":"string","label":"B-roll","default":"assets/broll_massa.mp4"},
{"id":"voz","type":"string","label":"Voz","default":"assets/voz_abertura.mp3"}
]'
>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1080, height=1920" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
/* Fonte local em assets/: não depende de rede no instante do primeiro quadro.
Fonte nomeada sem @font-face faz o lint reclamar (font_family_without_font_face). */
@font-face { font-family: "Titulo"; src: url("assets/fonte-titulo.woff2") format("woff2"); }
body { margin: 0; background: #1b0f0a; color: #fff; font-family: "Titulo", system-ui, sans-serif; }
/* A raiz usa 100%: quem define o tamanho do quadro é data-width e data-height */
#root { position: relative; width: 100%; height: 100%; overflow: hidden; }
.clip { position: absolute; inset: 0; }
#broll { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
#sombra { background: linear-gradient(transparent 40%, rgba(0, 0, 0, 0.85)); }
/* 320 px embaixo e 80 px nas laterais: fora da interface do Reels e dentro da área segura */
#texto { display: flex; flex-direction: column; justify-content: flex-end; padding: 0 80px 320px; }
/* Painel escuro atrás do texto: o contraste não depende do b-roll (o check exige 4,5:1 no texto normal e 3:1 no texto a partir de 24 px) */
.painel { background: rgba(20, 10, 6, 0.86); border-radius: 24px; padding: 40px 48px; }
h1 { font-size: 110px; margin: 0; line-height: 1; }
.sub { color: #f5c16c; font-size: 44px; margin: 12px 0 32px; }
.item { font-size: 48px; margin-bottom: 10px; }
</style>
</head>
<body>
<!-- Raiz: id da composição, tamanho do quadro, duração em segundos e fps -->
<div id="root" data-composition-id="corte" data-start="0"
data-width="1080" data-height="1920" data-duration="6" data-fps="30">
<!-- B-roll mudo. Vídeo sem som leva muted; nunca use crossorigin em mídia.
data-var-src troca o arquivo no lote; o src escrito é o reserva. -->
<video id="broll" src="assets/broll_massa.mp4" data-var-src="broll"
data-start="0" data-duration="6" data-track-index="0" muted playsinline></video>
<div id="sombra" class="clip" data-start="0" data-duration="6" data-track-index="1"></div>
<!-- Todo <audio> precisa de id: sem ele o mixer ignora a faixa e o render sai mudo -->
<audio id="voz" src="assets/voz_abertura.mp3" data-var-src="voz"
data-start="0.3" data-duration="5.5" data-track-index="3"></audio>
<!-- data-volume 0.1 = trilha a 10% do volume original -->
<audio id="trilha" src="assets/trilha.mp3"
data-start="0" data-duration="6" data-track-index="4" data-volume="0.1"></audio>
<section id="texto" class="clip" data-start="0" data-duration="6" data-track-index="2">
<div class="painel">
<h1 id="titulo" data-var-text="titulo">Bolo de rolo</h1>
<p class="sub">Cozinha da Rafa, Recife</p>
<div class="item">Farinha de trigo</div>
<div class="item">Manteiga</div>
<div class="item">Açúcar</div>
<div class="item">Ovos</div>
<div class="item">Goiabada</div>
</div>
</section>
</div>
<script>
// Uma timeline GSAP pausada por composição: o motor, não o relógio, decide cada instante.
// Anime os filhos do .clip (h1, .sub, .item), nunca o próprio .clip.
const tl = gsap.timeline({ paused: true });
tl.fromTo("#titulo", { y: 60, opacity: 0 }, { y: 0, opacity: 1, duration: 0.6, ease: "power3.out" }, 0.2)
.fromTo(".sub", { opacity: 0 }, { opacity: 1, duration: 0.4 }, 0.6)
.fromTo(".item", { x: -40, opacity: 0 }, { x: 0, opacity: 1, duration: 0.3, stagger: 0.33 }, 1.0);
// A chave tem de ser igual ao data-composition-id da raiz
window.__timelines["corte"] = tl;
</script>
</body>
</html>Três detalhes do arquivo vieram de falhas reais. A fonte mora em assets/ (cópia de marca/fontes/) com @font-face, porque fonte nomeada sem arquivo local faz o lint reclamar e fonte da internet pode não chegar a tempo do primeiro quadro. O painel escuro atrás do texto existe porque o check mede contraste contra o b-roll pelo critério WCAG AA, 4,5:1 no texto normal e 3:1 no texto grande (24 px ou mais, ou 19 px ou mais em negrito): com um fundo claro, até o título branco de 110 px reprova abaixo de 3:1. E o lint avisa nested_structure_needs_subcomposition porque o bloco de texto tem filhos; é aviso, não erro, e indica o caminho das subcomposições quando a peça crescer.
Verificar, aprovar e renderizar a peça
O ciclo da skill hyperframes-cli tem uma regra que parece burocracia e evita retrabalho: o check passar não autoriza o render. Alguém precisa ver e ouvir o preview. No render, use três níveis de qualidade: draft para o rascunho, looks (o padrão, que codifica em CRF 16 desde setembro de 2026) para a primeira versão real e delivery para a entrega final. A referência da CLI lista mais dois nomes: high, o mesmo preset do delivery, e standard, nome antigo que ainda funciona; npx hyperframes render --help mostra os da versão instalada.
Da composição ao lote de MP4 em nove passos
Rode os scripts da raiz video-ia; eles entram em composicoes/cozinha-corte/, onde ficam index.html, rows.json e as cópias da mídia em assets/.
Passo 1: Confira o ambiente com node -v, ffmpeg -version e hyperframes doctor
Deu certo quando: Node 22 ou superior, FFmpeg presente e o doctor sem itens em falta.
Erro comum: Node 20 num gerenciador de versões diferente do terminal onde o agente roda.
Passo 2: Crie o projeto dentro de composicoes/ com npx hyperframes init cozinha-corte --example blank
Deu certo quando: A pasta composicoes/cozinha-corte tem um index.html pronto para editar.
Erro comum: Rodar init num terminal interativo sem --example e parar na pergunta de qual exemplo usar.
Passo 3: Busque um bloco pronto com catalog antes de escrever animação à mão
Deu certo quando: O catalog devolve blocos para a frase pedida, em inglês, e o add instala o escolhido.
Erro comum: Reescrever um lower third que já existe entre os cerca de 400 blocos do registry.
Passo 4: Escreva o index.html com audio com id e timeline pausada
Deu certo quando: npx hyperframes lint termina com 0 erros.
Erro comum: audio sem id, que deixa o render mudo, ou crossorigin no video, que o lint recusa.
Passo 5: Rode npx hyperframes check --snapshots
Deu certo quando: Check passed, com o contraste aprovado em todos os textos e os quadros anotados gerados.
Erro comum: Título branco direto sobre b-roll claro reprova no contraste; ponha um painel escuro atrás.
Passo 6: Abra o preview com --background e aprove vendo e ouvindo
Deu certo quando: Em http://localhost:3002 o título entra, os ingredientes aparecem no tempo certo e a voz toca.
Erro comum: Aprovar sem som e descobrir o render mudo só no celular.
Passo 7: Se o agente mexeu depois da aprovação, consulte npx hyperframes history
Deu certo quando: O histórico lista a mudança do agente e a composição volta ao estado aprovado no preview, sem git.
Erro comum: Pedir ao agente que desfaça de memória e ganhar uma terceira versão, diferente das duas.
Passo 8: Renderize o rascunho e a entrega
Deu certo quando: O ffprobe mostra h264, 1080x1920, 30/1, uma faixa de áudio e duração de 6 segundos.
Erro comum: Publicar o arquivo do --quality draft por engano; a entrega sai do render com --quality delivery.
Passo 9: Gere o lote com render --batch rows.json
Deu certo quando: renders/ tem um MP4 por linha do rows.json, cada um com 6 segundos, e o manifest.json sem falhas.
Erro comum: Chave do rows.json que não foi declarada em data-composition-variables; o valor não chega à composição.
No fim você tem: Um cartão 9:16 aprovado no preview, o MP4 de entrega com som e um lote de cortes gerado por um comando.
#!/usr/bin/env bash
# scripts/aula06_ciclo.sh: check -> preview -> aprovação humana -> render -> conferência.
# Uso: bash scripts/aula06_ciclo.sh (na raiz video-ia)
set -euo pipefail
cd composicoes/cozinha-corte # o HyperFrames roda de dentro do projeto; o MP4 vai para ../../renders/
# O lint (estrutura, mídia sem id, crossorigin, fonte) fica para enquanto você escreve; o check já roda o lint
npx hyperframes check --snapshots # portão final: roda o lint, abre o navegador e gera quadros anotados
npx hyperframes preview --background # Studio em http://localhost:3002, segue rodando
# A skill proíbe renderizar só porque o check passou: alguém precisa ver e ouvir o preview.
read -r -p "Você viu e ouviu o preview e aprova (s/n)? " ok
[ "$ok" = "s" ] || { echo "Render cancelado"; exit 1; }
# Rascunho rápido para revisar no celular
npx hyperframes render --quality draft --output ../../renders/corte_draft.mp4
# Entrega: --quality delivery, 30 fps, 4 workers (cada um abre um Chrome de cerca de 256 MB; o teto é 24)
npx hyperframes render --quality delivery --fps 30 --workers 4 --output ../../renders/corte_final.mp4
# Conferir contra data-duration="6" e o tamanho 1080x1920
test -s ../../renders/corte_final.mp4 # existe e não está vazio
ffprobe -v error -show_entries stream=codec_type,codec_name,width,height,r_frame_rate \
-show_entries format=duration -of default=nw=1 ../../renders/corte_final.mp4
# esperado: video h264 1080x1920 30/1, uma faixa audio e duration perto de 6.0
# Nuvem, quando precisar (leia antes a página de cada caminho):
# npx hyperframes cloud render # nuvem HeyGen, 4K a 1,5x, projeto até 200 MB
# npx hyperframes lambda deploy # função na SUA conta AWS
# npx hyperframes lambda render ./ --width 1080 --height 1920 --wait
# npx hyperframes lambda destroy # o bucket S3 fica; apague à mão#!/usr/bin/env bash
# scripts/aula06_lote.sh: os dois cortes 9:16 da semana em um comando, um MP4 por linha.
# Uso: bash scripts/aula06_lote.sh (na raiz video-ia)
set -euo pipefail
cd composicoes/cozinha-corte # rows.json fica ao lado do index.html
# Cada linha é o conjunto de variáveis de um render. As chaves titulo, broll e voz
# são as declaradas em data-composition-variables; "name" só nomeia o arquivo de saída.
cat > rows.json <<'JSON'
[
{ "name": "corte1_bolo_de_rolo_massa", "titulo": "Bolo de rolo: a massa", "broll": "assets/broll_massa.mp4", "voz": "assets/voz_massa.mp3" },
{ "name": "corte2_bolo_de_rolo_enrolar", "titulo": "Bolo de rolo: enrolar", "broll": "assets/broll_enrolar.mp4", "voz": "assets/voz_enrolar.mp3" }
]
JSON
# {name} vira o nome do arquivo. Não misture --batch com --variables.
# --batch-concurrency 1 (padrão): cada render já usa vários workers.
# --batch-fail-fast para o lote na primeira linha que falhar: uma chave errada aparece logo.
npx hyperframes render --batch rows.json --output "../../renders/{name}.mp4" --batch-concurrency 1 --batch-fail-fast
# O comando grava ../../renders/manifest.json com o estado de cada linha. Confira as durações:
for f in ../../renders/corte*_bolo_de_rolo_*.mp4; do
printf "%s " "$f"; ffprobe -v error -show_entries format=duration -of csv=p=0 "$f"
doneO lote separa o que muda do que fica, e é essa separação que torna um modelo de edição reaproveitável. O curso Vibe Viral, do Vibehub Academy, consultado em 12/10/2026, trata o modelo de edição como uma receita guardada à parte do conteúdo: ritmo de corte, layouts, cartões, legenda e som de um lado; o vídeo da semana do outro; cada modelo com uma linha de “bom para” e outra de “quando não usar”, salvo como modelo só depois de aprovado. Aqui, o index.html é a receita e cada linha do rows.json é o conteúdo. Se uma linha pede um layout que a composição não tem, crie outra composição em vez de enfiar condicionais na mesma. Está certo quando trocar o conteúdo da semana não exige tocar no index.html.
Depois do primeiro render: motion blur, GPU e a escolha do motor
sparkles Ligar o motion blur só onde ele paga o custo
Desde 17/09/2026, na versão 0.8.45, o motor do HyperFrames calcula motion blur de verdade: cada quadro é renderizado várias vezes em instantes vizinhos, como num obturador de 180 graus, e as amostras são misturadas. Desde a 0.8.46 o número de amostras se adapta ao quadro, de 16 a 64, e desde a 0.8.140, de 07/10/2026, o efeito também vale sobre vídeo. O resultado tira o aspecto recortado de um título que cruza a tela rápido, e o custo é alto: a 16 amostras, um quadro 1080p gasta cerca de 600 ms só na mistura, mais as 16 capturas, e a captura passa a ser em PNG.
Ligue o desfoque do motor (a opção motionBlur do producer; npx hyperframes render --help mostra como na sua versão) só na peça que precisa dele, como o cartão de abertura com movimento rápido. Para desfocar um objeto só, prefira o componente motion-blur do catálogo, reescrito no modelo do After Effects. Nunca ligue os dois na mesma peça: a imagem é desfocada duas vezes e o movimento vira borrão. Se a composição usa HDR ou transição com shader, o motor recusa o motion blur, porque esses caminhos passam pelo compositor em camadas. Deu certo quando o quadro do meio do movimento, extraído com o FFmpeg, mostra o rastro na direção do deslocamento e o texto parado continua nítido.
Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
cpu Codificar na GPU e voltar atrás sem git
Desde 10/10/2026, na versão 0.8.145, a exportação do Studio codifica na GPU do mesmo jeito que render --gpu já fazia na linha de comando. Com NVENC (NVIDIA), VideoToolbox (Mac), AMF (AMD), VAAPI ou QSV (Intel), a codificação sai do processador e o lote da semana termina antes; sem encoder suportado, o render cai para a CPU sem erro. Dois limites: --gpu é recusado com --format hls, e a saída muda byte a byte em relação à da CPU, então o verificar_entrega.py da Aula 04 continua obrigatório. Se pedir H.265 na GPU, confira a tag com ffprobe -show_entries stream=codec_tag_string: sem hvc1, players da Apple não tocam o arquivo.
O segundo recurso do período protege a revisão. Na semana de 21/09/2026, a CLI ganhou o histórico com desfazer de toda mudança, inclusive as do agente: npx hyperframes history lista o que mudou e permite voltar ao estado que você aprovou no preview. Se o render travar, desde a 0.8.147, de 11/10/2026, a mensagem nomeia a etapa em que o Chrome parou; deixe terminar o outro processo pesado de GPU ou CPU e rode de novo. Em Mac ou Linux, dá para revisar no app HyperFrames Studio, aberto com npx hyperframes open e com conta HeyGen; no Windows, o caminho continua sendo o preview em http://localhost:3002.
#!/usr/bin/env bash
# scripts/aula06_gpu.sh: entrega codificada na GPU, conferida do mesmo jeito que a da CPU.
# Uso: bash scripts/aula06_gpu.sh (na raiz video-ia, depois do scripts/aula06_ciclo.sh)
set -euo pipefail
cd composicoes/cozinha-corte
# 1) O que mudou desde a sua aprovação, inclusive o que o agente fez; volte por aqui se precisar
npx hyperframes history
# 2) --gpu usa NVENC, VideoToolbox, AMF, VAAPI ou QSV; sem encoder suportado, cai para a CPU.
# Não combine com --format hls, que recusa --gpu.
npx hyperframes render --gpu --quality delivery --fps 30 --output ../../renders/corte_final_gpu.mp4
# 3) A GPU muda o arquivo byte a byte: quem decide é o verificador da Aula 04.
# A referência de duração é a entrega da CPU, que já foi aprovada.
cd ../..
python scripts/verificar_entrega.py renders/corte_final_gpu.mp4 renders/corte_final.mp4 9:16Se a figura ultrapassar a área visível, deslize para os lados. Pelo teclado, foque a figura e use as setas.
scale Escolher entre Remotion e HyperFrames por peça
Os dois motores fazem a mesma coisa no fim: um navegador sem interface desenha os quadros e o FFmpeg monta o MP4. O que muda é a linguagem, a licença, a nuvem e o que já vem pronto. A tabela compara as versões vigentes em 12/10/2026.
Remotion e HyperFrames lado a lado
| Critério | Remotion 4.0.535 | HyperFrames 0.8.149 |
|---|---|---|
| Linguagem | React e TSX, com props tipadas | HTML, CSS e GSAP, com atributos data-* |
| Licença | Gratuita até 3 pessoas; depois US$ 25 por pessoa por mês ou US$ 0,01 por render (mínimo de US$ 100) | Apache-2.0, sem cobrança por tamanho de equipe |
| Nuvem | Lambda na sua conta AWS, cerca de US$ 0,017 a 0,021 por minuto de vídeo no exemplo oficial | Lambda na sua AWS, Cloud Run ou nuvem da HeyGen, com 4K a 1,5x |
| Validação antes do render | Prévia no Studio | lint e check com layout e contraste, depois preview |
| Lote | Um render por conjunto de props, em script | render --batch nativo, um MP4 por linha |
| Peças prontas | 12 skills, @remotion/captions | 21 skills, registry com cerca de 400 blocos |
| Player no site | @remotion/player, que recebe props do app React e conta como automação em produto | @hyperframes/player, o elemento <hyperframes-player>, que toca e busca a composição em qualquer página |
Existe a skill /remotion-to-hyperframes para migrar composições do Remotion; o caminho inverso não tem skill.
Quatro perguntas resolvem a escolha. Se a equipe tem 4 pessoas ou mais e não quer pagar Creators nem Automators, use HyperFrames; até 3 pessoas, a licença do Remotion é gratuita e o critério passa a ser a linguagem. Se o projeto já é React e o player dentro do site precisa receber props do app, fique no Remotion; para só tocar a composição numa página, o <hyperframes-player> resolve; se a entrega é só o MP4 e o agente vai escrever a maior parte, o HyperFrames com os blocos do registry pede menos código. Se a peça é motion graphics curta sem narração, como tipografia cinética ou lower third, o fluxo /motion-graphics do HyperFrames já existe para isso. Se precisa de 4K vertical, os presets portrait-4k e square-4k do HyperFrames entregam 2160x3840 e 2160x2160 em MP4. Vídeo longo não decide a escolha: o Remotion Lambda divide o render em partes paralelas e, pela estimativa do curso, cobre até cerca de 80 minutos em Full HD.
Na Cozinha da Rafa, a equipe tem duas pessoas, então nenhuma licença pesa e o critério vira linguagem e lote. O editor escreve HTML e CSS, e os dois cortes 9:16 da semana ganham o cartão em HyperFrames: a Rafa aprova o preview, ouve a voz e a trilha baixa, e o rows.json com duas linhas vira dois MP4 em renders/ com um comando, sem conta AWS. Se um dia o canal quiser o cartão tocando dentro do próprio site, o <hyperframes-player> embute a mesma composição; só se o site virar um app React em que o espectador troca a receita, o @remotion/player passa a ser o caminho mais direto. O mesmo raciocínio de abertura forte nos primeiros segundos aparece no curso de Meta Ads, em produzir Reels e Stories que seguram a atenção.
Glossário rápido
HyperFrames
Framework de código aberto da HeyGen (Apache-2.0) que transforma HTML, CSS e animação em MP4; não é modelo generativo.
render determinístico
Render em que a mesma entrada produz sempre o mesmo arquivo, como receita pesada em gramas em vez de “uma pitada”.
timeline pausada
Linha do tempo GSAP criada com paused: true e registrada em window.__timelines; o motor do render, e não o relógio do navegador, escolhe cada instante.
clip
Elemento da composição com data-start; o HyperFrames mostra e esconde o clip pela janela de tempo declarada.
registry do HyperFrames
Catálogo de cerca de 400 blocos e componentes prontos, buscados com catalog e instalados com add.
check
Portão final da CLI do HyperFrames: roda o lint e audita no navegador erros, layout, movimento e contraste antes do preview.
variáveis de composição
Campos declarados em data-composition-variables que o render em lote troca a cada linha, como título, b-roll e voz.
Guia prático: provas visuais da composição antes do render de entrega
O check aprova estrutura, layout e contraste, e o preview pede olhos e ouvidos. Entre os dois cabe uma etapa que a CLI do HyperFrames já oferece: quadros nos instantes exatos que importam, o rastro do movimento numa imagem só, as batidas da trilha e a medição de qual configuração de render compensa na sua máquina. Você sai com scripts/aula06_conferir.sh, que grava essas provas em qa/frames/ e logs/.
Funções, casos de uso e aplicações
Funções
Comandos da CLI do HyperFrames que produzem provas antes da entrega
| Função ou recurso | O que faz | Quando usar | Desde |
|---|---|---|---|
| snapshot --at | Grava PNG nos instantes pedidos, em segundos | Ver a entrada do título e o último ingrediente sem tocar o preview | Instante exato desde 02/10/2026 (0.8.112) |
| keyframes --shot | Desenha o movimento de um elemento em papel cebola, várias posições sobrepostas num PNG | Conferir trajetória e ritmo da animação do título | Na documentação da CLI em 12/10/2026 |
| compare | Junta variantes da composição numa grade PNG com rótulos | Decidir entre duas versões do cartão com o cliente | Na documentação da CLI em 12/10/2026 |
| beats | Detecta as batidas da trilha e grava instante, força e BPM | Alinhar a entrada dos ingredientes ao ritmo da música | Na documentação da CLI em 12/10/2026 |
| benchmark | Compara tempo e tamanho de arquivo entre configurações de render | Escolher workers e qualidade antes do lote da semana | Na documentação da CLI em 12/10/2026 |
| transcribe --to srt ou vtt | Gera legenda direto de um arquivo de mídia | Legenda de prévia; a legenda palavra a palavra fica com o Scribe | 10/10/2026 (0.8.144) |
| data-fx-chain na raiz | Aplica uma cadeia de efeitos de áudio à mixagem inteira, depois dos efeitos de cada clip | Limitador ou equalização final na peça toda | 12/10/2026 (0.8.150) |
Desde a 0.8.149, de 11/10/2026, transcribe e removeBackground também podem ser importados como funções pelo pacote hyperframes/api.
Casos de uso
Designer de uma agência de Natal que entrega cartões de oferta em vídeo para uma rede de supermercados
Marketing digital, varejo alimentar
Dor
O cliente aprovava um quadro parado e reclamava do vídeo final, porque o preço passava rápido demais na animação.
Solução
Ela passou a enviar, junto com o link do preview, os PNG do snapshot nos instantes do preço e o papel cebola do keyframes --shot.
Resultado
Observar se as rodadas de ajuste por peça diminuem e se o cliente passa a comentar o movimento antes do render final.
Cenário construído para fins didáticos. Números não correspondem a cliente específico.
Produtor de um podcast educativo de finanças pessoais em Brasília que transforma episódios em cortes com trilha
Educação financeira, conteúdo em vídeo
Dor
Os textos dos cortes entravam fora do tempo da música e pareciam desencontrados.
Solução
Ele rodou o beats na trilha e pediu ao agente que posicionasse a entrada dos textos nas batidas mais fortes do JSON; o compare mostrou a versão antiga e a nova lado a lado.
Resultado
Acompanhar a retenção dos primeiros segundos dos cortes nas próximas semanas e comparar com os cortes montados antes da mudança.
Cenário construído para fins didáticos. Números não correspondem a cliente específico.
Na prática
Rode depois do scripts/aula06_ciclo.sh, com o preview já aprovado. O script entra em composicoes/cozinha-corte/, grava os quadros em qa/frames/cozinha-corte/, a pasta que a revisão visual do Claude lê, e a medição em logs/. Os instantes saem do index.html da aula: o título anima entre 0,2 e 0,8 s, e os ingredientes entram a partir de 1,0 s, a cada 0,33 s. O benchmark renderiza a peça várias vezes; rode com a máquina livre e só antes do lote.
#!/usr/bin/env bash
# scripts/aula06_conferir.sh: provas visuais e sonoras da composição antes do render de entrega.
# Uso: bash scripts/aula06_conferir.sh (na raiz video-ia, depois do preview aprovado)
set -euo pipefail
cd composicoes/cozinha-corte # a raiz video-ia fica em ../..
PROVAS=../../qa/frames/cozinha-corte # a mesma pasta que a revisão visual do Claude lê
mkdir -p "$PROVAS" ../../logs
# 1) Quadros nos instantes que importam: título no meio da entrada (0,5 s), primeiro
# ingrediente pronto (1,3 s), último ingrediente pronto (2,7 s) e o fim (5,9 s).
# Desde a 0.8.112 (02/10/2026), o --at captura no instante exato pedido.
npx hyperframes snapshot . --at 0.5,1.3,2.7,5.9 --output "$PROVAS"
# 2) Papel cebola do título: várias posições do h1 sobrepostas numa imagem só
# (9 amostras por padrão). Selecione o filho animado, nunca o .clip.
npx hyperframes keyframes . --selector "#titulo" --shot "$PROVAS/titulo-movimento.png"
# 3) Batidas da trilha: grava beats/<arquivo>.json com instante e força de cada batida.
# Precisa do Chrome local, o mesmo que o doctor conferiu na aula.
npx hyperframes beats . --json
# 4) Tempo e tamanho de cada configuração de render nesta máquina (1 rodada por opção).
# Renderiza várias vezes: rode com a máquina livre e antes do lote, não a cada ajuste.
npx hyperframes benchmark . --runs 1 --json > ../../logs/benchmark-cozinha-corte.json
# Opcional: duas variantes lado a lado numa grade com rótulos, para decidir com o cliente.
# npx hyperframes compare ../cozinha-corte ../cozinha-corte-b --labels "Atual,Painel claro" \
# --at 1.3 --out "$PROVAS/comparar.png"
ls "$PROVAS"Provas antes da entrega
Cinco passos; as provas acompanham o pedido de aprovação, sem substituí-lo.
Passo 1: Escolha os instantes pelo index.html
0,5 s no meio da entrada do título, 1,3 s com o primeiro ingrediente, 2,7 s com o último e 5,9 s no fim.
Deu certo quando: Os PNG mostram cada momento sem texto cortado nem sobreposto.
Erro comum: Pedir quadros igualmente espaçados e perder justamente a entrada do título.
Passo 2: Gere o papel cebola do título
Deu certo quando: O PNG mostra o título subindo, com as posições mais juntas no fim do movimento (ease power3.out).
Erro comum: Selecionar o .clip em vez do h1: a aula anima os filhos, nunca o clip.
Passo 3: Leia as batidas da trilha
Deu certo quando: A pasta beats/ ganha um JSON com instantes e BPM da trilha.
Erro comum: Rodar numa máquina sem o Chrome local que o comando usa.
Passo 4: Meça antes do lote
Deu certo quando: logs/benchmark-cozinha-corte.json mostra tempo e tamanho por configuração.
Erro comum: Medir com outro render pesado aberto e escolher a configuração pela máquina ocupada.
Passo 5: Anexe as provas ao pedido de aprovação
Deu certo quando: A aprovação cita os PNG e o JSON, além do link do preview.
Erro comum: Tratar as provas como aprovação: quem aprova ainda vê e ouve o preview.
No fim você tem: Quadros, rastro do movimento, batidas e medição de render guardados onde a revisão já procura, antes de gastar o render de entrega.
Armadilhas
Conferir a composição sem gastar render à toa
Evite
Coluna a evitar
- Renderizar a entrega para descobrir o problema no MP4
- Manter na raiz uma cadeia data-fx-chain esquecida
- Usar a legenda do transcribe como legenda final
- Rodar o benchmark a cada ajuste de texto
- Atualizar a CLI no meio do lote da semana
Faça assim
Coluna recomendada
- snapshot e keyframes antes do render, em segundos
- Na 0.8.150, revisar ou remover a cadeia da raiz
- Legenda final pelo Scribe, no fluxo da aula 22
- benchmark uma vez por máquina e por tipo de peça
- Versão fixa durante o lote e atualização depois
Troque o b-roll por um seu, gere duas linhas no rows.json e passe o ciclo inteiro. Está pronto quando o check passa com o contraste aprovado, você aprovou o preview ouvindo a voz, o MP4 final sai em 1080x1920 a 30 fps com uma faixa de áudio e 6 segundos, e o lote gera um arquivo por linha. Para planejar o vídeo antes de escrever a composição, o capítulo projetar um vídeo a partir da experiência desejada ajuda a decidir o que cada cena precisa mostrar.
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
- Produzir apresentações e PDF com critérios de entregasugerido pelo grafoApresenta o conceito “HTML”, usado em “Produzir apresentações e PDF com critérios de entrega”.
- Descobrir o que a IA não vê na página que você vêsugerido pelo grafoApresenta o conceito “HTML”, usado em “Descobrir o que a IA não vê na página que você vê”.
- Projetar gráficos e painéis pela decisãosugerido pelo grafoApresenta o conceito “HTML”, usado em “Projetar gráficos e painéis pela decisão”.
- Integração com IA (OpenAI, Claude)sugerido pelo grafoApresenta o conceito “Preview”, usado em “Integração com IA (OpenAI, Claude)”.
Conceitos deste capítulo
O mesmo assunto em outros cursos
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
- 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
- 06Montar vídeo em HTML com HyperFrames e escolher entre ele e o Remotion
- 07Estruturar o projeto de vídeo para o Claude Code operar sem improvisar
- 08Instalar e invocar skills de vídeo no Claude Code