MÓDULO 2.5

✅ Validar & renderizar

A etapa final do pipeline: lint sem erros, inspect sem overflow, render draft para conferir frame a frame, validação da locução, render high-quality e geração dos dois formatos — tudo na ordem certa.

6
Tópicos
~35
Minutos
Prático
Nível
Entrega
Tipo
Pipeline de Validação & Render LINT → INSPECT → DRAFT → HIGH → MP4 × 2 lint 0 erros overlapping inspect 0 overflow --samples 16 draft 1 frame/cena ffmpeg -nostdin 👁 high --fps 30 ~3–4 min 16:9 MP4 1920 × 1080 YouTube 9:16 MP4 1080×1920 Shorts ① LINT ② INSPECT ③ DRAFT ④ HIGH
1

🧹 npx hyperframes lint

A primeira barreira de qualidade: o linter analisa o seu index.html gerado e reporta problemas estruturais antes de você gastar tempo de render. Meta: 0 erros.

Conceito Principal

O linter lê o index.html gerado (não o build-index.mjs) e valida a estrutura de composição. Erros param o render — warnings são informativos.

Rode sempre após node build-index.mjs e antes de qualquer render. O lint é rápido (<2 s) e não inicia Chrome.

Comando
# gere o index.html antes de linttar
node build-index.mjs
npx hyperframes lint

# saída esperada (0 erros)
✔ 0 errors, 0 warnings
Os 3 erros mais comuns
overlapping_clips

Dois clipes de cena têm intervalos de tempo que se sobrepõem. Corrija ajustando o array AUDIO[] no build-index.mjs — a soma de durações deve ser estritamente sequencial.

multiple_root_compositions

Mais de um elemento com data-composition na raiz do documento. O HyperFrames só aceita uma composição por arquivo index.html.

google_fonts_import

O lint detecta um @import url('fonts.googleapis.com/...') no CSS. Fontes externas são proibidas porque o Chrome headless não tem acesso à internet durante o render. Use node fetch-fonts.mjs para baixar os .woff2 e servir localmente via assets/fonts/fonts.css.

💡
Lint em loop de desenvolvimento

Durante a composição, rode node build-index.mjs && npx hyperframes lint a cada modificação relevante no build-index.mjs. Custo: menos de 2 segundos. Evita surpresas no momento do render.

Conceitos-chave
🧹
0 erros
Meta obrigatória
⏱️
<2 s
Sem Chrome
🔤
Fontes locais
fetch-fonts.mjs
📋
AUDIO[]
Sequencial
2

🔍 npx hyperframes inspect --samples 16

O inspector abre o Chrome headless, captura 16 frames distribuídos ao longo do vídeo e audita cada um: layout, overflow de texto, elementos fora do canvas. Meta: 0 problemas.

Comando
# 16 amostras cobre bem vídeos de até ~110s
npx hyperframes inspect --samples 16

# saída esperada
✔ Inspected 16 frames — 0 layout issues found
✓ Boas práticas para 0 problemas
  • Adicione data-layout-ignore em elementos decorativos off-canvas (palavras gigantes de fundo, glows, .bg-layer)
  • Prefira left/right em vez de width para markers de highlight
  • Teste código longo em overflow-x: auto com container de largura explícita
  • Use z-index:-1 nos glows para não vazar do bounding box
✗ Causas comuns de overflow
  • Texto em linha de código ultrapassando o container — encurte ou quebre em linhas
  • SVG sem viewBox definido — o auditor não consegue calcular bounds
  • position: absolute sem overflow: hidden no pai
  • Elementos decorativos sem data-layout-ignore — marcados como overflow falso-positivo
⚠️
Inspect não substitui revisão visual

O inspector detecta overflow de bounding-box, não problemas de legibilidade ou contraste. Após 0 problemas no inspect, ainda é necessário revisar frames do render draft visualmente — especialmente em cenas com texto sobre gradiente.

Conceitos-chave
🔍
16 amostras
Cobertura boa
🏷️
data-layout-ignore
Decorativos
📐
Bounding box
Overflow real
🧪
Chrome headless
Render real
3

🎬 Render draft — iterar rápido

O modo --quality draft gera um MP4 de baixa resolução em segundos. Extraia um frame por cena com ffmpeg -nostdin e confira visualmente antes de gastar tempo no render final.

Workflow de conferência frame a frame
1
Gere o draft MP4
node build-index.mjs # gera index.html
npx hyperframes render --quality draft --output renders/draft.mp4
2
Extraia 1 frame por cena com ffmpeg

Use o tempo de início da cena como <t>. Para uma cena que começa em 12,5 s, use -ss 12.5. O flag -nostdin é obrigatório no Windows/git-bash para evitar que o ffmpeg consuma stdin e saia sem gerar o arquivo.

# frame da cena que começa em t=12.5s
ffmpeg -nostdin -y -ss 12.5 -i renders/draft.mp4 \
-vframes 1 -update 1 frame-cena3.png
3
Abra o PNG com a ferramenta Read

O Claude consegue visualizar imagens PNG diretamente. Extraia um frame por cena e verifique: alinhamento de texto, overflow, animações na posição certa, legibilidade sobre fundo. Repita para todas as cenas.

4
Corrija e repita

Edite o build-index.mjs, rode node build-index.mjs && npx hyperframes render --quality draft novamente. O loop draft é barato — itere sem culpa antes do render final.

📊 Draft vs High — quando usar cada um
Aspecto Draft High
Objetivo Conferência visual Entrega final
Velocidade Rápido (<30 s) 3–4 min / 110s de vídeo
Qualidade Reduzida Máxima (30 fps)
Uso Loop de iteração Uma vez, no final
💡
Cobertura mínima recomendada

1 frame por cena cobre bem. Para um vídeo de 8 cenas, são 8 chamadas ffmpeg. Foque nos momentos de transição e nos títulos — são as partes mais propensas a overflow.

Conceitos-chave
🎬
--quality draft
Iteração rápida
📸
-vframes 1
Frame único
🛡️
-nostdin
Win/git-bash
🔁
-update 1
Sobrescreve PNG
4

👂 Validar a locução com o usuário

O Claude não ouve áudio. A validação da narração é responsabilidade do usuário — e deve acontecer antes do render high para não desperdiçar 3–4 minutos de processamento.

⚠️
O Claude não consegue ouvir os WAVs

A ferramenta de análise de imagens (Read) funciona para PNGs e frames, mas áudio WAV não é suportado. Toda validação de locução precisa ser feita pelo usuário ouvindo os arquivos assets/audio/sN.wav diretamente.

O que validar na locução

Antes de render high, confirme com o usuário: pronúncia correta de termos técnicos, velocidade (pf_dora --speed 0.98 é o padrão), pausas naturais entre cenas, e duração coerente com o visual de cada cena.

✓ Checklist de validação de áudio
  • Ouça cada assets/audio/sN.wav antes do render final
  • Confirme que siglas foram expandidas corretamente (ex.: "GSAP" → "ji-sap" soa natural?)
  • Verifique que a duração do WAV é coerente com a cena visual
  • Confira via ffprobe se a duração medida bate com o AUDIO[]
✗ Não pule a validação de áudio
  • Não faça render high sem ouvir os WAVs — retrabalho caro
  • Não confie só na duração medida — a fala pode estar truncada
  • Não use speed acima de 1.05 — voz fica metálica e artificial
  • Não ignore pronúncias erradas de termos em inglês no texto PT-BR
Confirmar duração com ffprobe
# medir duração exata de cada WAV
ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 \
assets/audio/s1.wav

# resultado: ex. 14.2327
14.2327

# use esse valor em AUDIO[0] no build-index.mjs
const AUDIO = [14.23, /* s2 */ 11.80, ...]
💡
Vozes PT-BR disponíveis no Kokoro

Além de pf_dora (feminina, padrão recomendado com --speed 0.98), há pm_alex e pm_santa para variações masculinas. Se a pronúncia de um termo estiver errada, reescreva foneticamente no assets/txt/sN.txt e regenere o WAV.

Conceitos-chave
👂
Revisão humana
Claude não ouve
🎙️
pf_dora
speed 0.98
⏱️
ffprobe
Mede duração
📝
AUDIO[]
Sincroniza cena
5

🚀 Render high — qualidade de entrega

Após lint limpo, inspect sem overflow, draft conferido e locução aprovada, é hora do render final: --quality high --fps 30. Um vídeo de ~110s equivale a ~3.500 frames e leva 3–4 minutos na máquina típica com 22 cores.

O que acontece no render high

O HyperFrames abre Chrome headless em resolução plena (1920×1080 ou 1080×1920), captura cada frame em PNG, passa todos ao FFmpeg e encoda H.264 com o áudio WAV embutido. A 30 fps, 110 segundos = 3.300 frames.

O tempo de render varia com o número de cores disponíveis. Em 22 cores, espere ~3–4 minutos para 110s de vídeo.

Comando (render 16:9 high-quality)
# render final 16:9 (1920×1080)
node build-index.mjs &&
npx hyperframes render \
--quality high \
--fps 30 \
--output renders/meu-video-16x9.mp4

# saída durante render
⠸ Rendering frame 1547/3300 (46.9%)...
✔ Render complete → renders/meu-video-16x9.mp4
📊 Estimativas de tempo de render (22 cores)
Vídeo curto (~60s)
~1.800 frames
≈ 1,5–2 min de render
Vídeo padrão (~110s)
~3.300 frames
≈ 3–4 min de render
Vídeo longo (~180s)
~5.400 frames
≈ 5–7 min de render
✓ Antes de iniciar o render high
  • npx hyperframes lint — 0 erros confirmados
  • npx hyperframes inspect --samples 16 — 0 layout issues
  • Draft conferido visualmente (1 frame/cena)
  • Locução aprovada pelo usuário
✗ Não faça render high se...
  • Lint ainda reporta erros — vai falhar no meio do render
  • Não viu nenhum frame do draft — risco de retrabalho
  • O usuário não ouviu os WAVs — pode precisar re-renderizar
  • O index.html não foi regenerado após a última edição
Conceitos-chave
🚀
--quality high
Resolução plena
🎞️
30 fps
Padrão entrega
~3.500 frames
110s de vídeo
🏁
H.264 MP4
Pronto para upload
6

📐 Gerar os dois formatos — 16:9 e 9:16

Do mesmo projeto, gere o 16:9 (YouTube) e o 9:16 (Shorts/Reels) em sequência. A regra crítica: renderize logo após gerar cada formato — nunca deixe dois index.html simultâneos na raiz.

Regra do index.html único

O build-index.mjs sempre sobrescreve o mesmo index.html. Se você rodar os dois modos antes de renderizar, o segundo sobrescreve o primeiro e você perde a composição. A sequência correta é: gerar → renderizar → gerar outra versão → renderizar.

Sequência completa (ordem correta)
# ── PASSO 1: formato 16:9 ──────────────────────────
node build-index.mjs # sem flag → 1920×1080
npx hyperframes render \
--quality high --fps 30 \
--output renders/meu-video-16x9.mp4

# ── PASSO 2: formato 9:16 ──────────────────────────
node build-index.mjs --vertical # → 1080×1920
npx hyperframes render \
--quality high --fps 30 \
--output renders/meu-video-9x16.mp4

# resultado: 2 arquivos em renders/
renders/meu-video-16x9.mp4 # YouTube
renders/meu-video-9x16.mp4 # Shorts / Reels
📊 Formatos e destinos
16:9 — Horizontal
Resolução: 1920 × 1080 px
Destino: YouTube, Vimeo, LinkedIn
Flag: node build-index.mjs (sem flag)
Output: renders/nome-16x9.mp4
9:16 — Vertical
Resolução: 1080 × 1920 px
Destino: YouTube Shorts, Instagram Reels, TikTok
Flag: node build-index.mjs --vertical
Output: renders/nome-9x16.mp4
💡
Pipeline completo em um script

Para automatizar os dois formatos de uma vez, encadeie com &&:

node build-index.mjs && npx hyperframes render --quality high --output renders/v-16x9.mp4 &&
node build-index.mjs --vertical && npx hyperframes render --quality high --output renders/v-9x16.mp4

O && garante que o render do 9:16 só inicia após o 16:9 terminar com sucesso.

✓ Sequência correta
  • node build-index.mjs → render 16:9 → node build-index.mjs --vertical → render 9:16
  • Sempre confirme qual index.html está ativo antes do render
  • Nomeie os outputs com sufixo -16x9 e -9x16 desde o início
✗ Erros que custam render time
  • Rodar build-index.mjs e build-index.mjs --vertical sem renderizar entre os dois
  • Renderizar sem --output explícito — pode sobrescrever render anterior
  • Usar o mesmo nome de output para os dois formatos
Conceitos-chave
📺
1920×1080
YouTube
📱
1080×1920
Shorts/Reels
🚩
--vertical
Flag único
Gerar → render
Ordem obrigatória

📋 Resumo do Módulo 2.5

O que você aprendeu
  • npx hyperframes lint: os 3 erros fatais e como corrigir cada um
  • npx hyperframes inspect --samples 16: overflow, data-layout-ignore e falsos positivos
  • Render draft + extração de frame com ffmpeg -nostdin -y -ss <t> -vframes 1 -update 1
  • O Claude não ouve áudio — validação de locução é responsabilidade do usuário
  • Render high: --quality high --fps 30 · ~110s ≈ 3.500 frames ≈ 3–4 min
  • Sequência 16:9 → 9:16: gerar e renderizar cada modo antes de gerar o próximo
Próxima trilha
T3
🔧 Por dentro do HyperFrames
Você terminou a Trilha 2 — Pipeline. A próxima trilha mergulha nos internos do framework: como o Chrome headless controla o tempo, como o FFmpeg encoda, como GSAP se integra ao render frame a frame.
Iniciar Trilha 3: Por dentro →