Gráficos em movimento
Gere vídeos escrevendo uma página da web que o renderizador percorre quadro a quadro. Ambas as abordagens abaixo fazem a mesma coisa; a diferença é o que você escreve.
- HyperFrames — um arquivo HTML, CSS para aparência, uma timeline GSAP pausada para
movimento.
node scripts/hf.mjsexecuta a versão fixada e a instala uma vez a partir de um lockfile confirmado. Apache 2.0. - Remotion — componentes React.
useCurrentFrame()retorna o quadro, você faz a matemática. Maduro, tipado e licenciado gratuitamente apenas para até três pessoas.
Carregue a referência correspondente antes de escrever o código da composição. As regras da estrutura não são adivinháveis e a maioria das falhas é silenciosa: um arquivo HyperFrames que nunca registra sua timeline renderiza um quadro estático sem erro.
O caminho fácil
O usuário descreve o que deseja em qualquer palavra. Ele nunca escreve um brief, uma especificação ou um roteiro — Claude compila um.
/motion uma vinheta de logotipo impactante de 6 segundos para Inkwell
Essa é toda a entrada. Por baixo dos panos:
- Compile a solicitação em
brief.json— duração, tamanho, fps, batidas com tempos, cópia literal, suavização, paleta e uma lista desuposições. Cada lacuna recebe um padrão da tabela emreferences/brief.md; nada fica indefinido e nada é questionado. - Mostre o resumo compacto (uma tabela, ~12 linhas) e construa na mesma rodada. Sem portão de aprovação.
- Construa a partir do modelo, valide, renderize, olhe para os quadros.
A iteração é então uma edição de campo, não uma reconstrução. "Deixe mais impactante" muda
sentir.suavizacao e duas durações; o código não se move a menos que tipo ou movimento
mude.
O brief é o artefato que torna isso barato. Ele fica no disco ao lado da composição, então uma revisão é um diff, e re-renderizar é um comando.
Roteie primeiro
| Sinal | Abordagem |
|---|---|
| Build novo, sem estrutura nomeada | HyperFrames |
| HTML/CSS/GSAP/Lottie existente para reutilizar | HyperFrames |
Sem node_modules, sem etapa de build desejada | HyperFrames |
| Equipe maior que três pessoas | HyperFrames (licença) |
| Usuário nomeia Remotion, ou repositório é React/TS | Remotion |
| Precisa de um sistema de design, biblioteca de gráficos ou componentes complexos | Remotion |
| Portando um projeto Remotion existente | Remotion (portar custa mais do que economiza) |
Quando o usuário nomeia ambos, construa em HyperFrames e diga em uma linha que o port para Remotion está disponível mediante solicitação. Duas construções completas da mesma peça é trabalho desperdiçado, a menos que uma comparação tenha sido solicitada.
O ciclo
1. Compile o brief
Transforme a solicitação em brief.json antes de escrever código. O esquema, a
gramática tipo/movimento, a tabela de padrões e as alavancas de iteração estão em
references/brief.md.
node scripts/brief.mjs brief.json # validar + tabela de resumo
node scripts/brief.mjs brief.json --json # resultado da máquina
Mostre o resumo ao usuário, corrija qualquer ERRO, depois continue na mesma
rodada. Avisos são decisões de julgamento — um aviso que você aceita vai em suposições.
O brief também carrega o ritmo. Escolha audio.bpm para que a grade de batidas divida os
cortes — em bpm, uma batida é 60 / bpm segundos e todo batidas[].inicio deve
cair em uma delas. 120 BPM dá uma batida a cada 0,5 s e serve para a maioria das peças curtas. Se
brief.mjs reportar fora_da_grade, mova o corte ou mude o tempo; não ignore,
porque essa é a diferença entre uma peça que acerta e uma que parece sutilmente errada.
Concluído quando brief.mjs sai com 0, cada batida tem uma janela de tempo, um tipo, um
movimento e cópia literal, e nenhum corte está fora da grade de batidas.
2. Estruture
Comece pelos modelos nesta habilidade em vez de um arquivo em branco — eles estão corretos em relação a ambos os contratos e evitam as duas etapas propensas a falhas (registro de timeline, temporização de sequência).
# HyperFrames — HTML puro. O motor fixado se instala uma vez, o que precisa de rede
cp -R assets/hyperframes/. ./meu-video/
node scripts/hf.mjs lint ./meu-video
# Remotion — projeto React, precisa de suas dependências fixadas uma vez
cp -R assets/remotion/. ./meu-video/
cd meu-video && npm ci
# PowerShell
Copy-Item -Recurse -Force assets\hyperframes\* .\meu-video\
Copy-Item -Recurse -Force assets\remotion\* .\meu-video\
Concluído quando node scripts/hf.mjs lint passa, ou npx remotion compositions src/index.tsx lista o id da composição.
3. Construa as batidas
Um arquivo por batida. Mantenha a timeline plana — tempos absolutos em HyperFrames,
quadros <Sequence> em Remotion. Atualize a folha de batidas quando a construção mudar
a temporização, depois verifique novamente a duração total.
Nomeie cada cena após sua batida, porque é assim que as verificações a encontram:
data-brief-beat="<id>" no host HyperFrames, <Sequence name="<id>"> em
Remotion. Se uma Sequência Remotion calcula sua temporização, também coloque
data-brief-beat="<id>" em um elemento dentro dela, para que a temporização possa ser medida.
Concluído quando cada batida na folha existe no código, a duração da composição
corresponde à folha, e não há TODOs, stubs ou cópia de placeholder.
4. Verifique o movimento
Quadros parados mentem sobre temporização. Olhe para os quadros, depois olhe para a renderização.
node scripts/check-contract.mjs --dir ./meu-video --preflight # estático, sem instalação
node scripts/check-contract.mjs --dir ./meu-video --runtime # também inspeciona em um navegador
node scripts/hf.mjs check ./meu-video # layout, movimento, contraste
node scripts/hf.mjs snapshot ./meu-video --review # quadros de batida + emendas como PNGs
node scripts/hf.mjs keyframes ./meu-video --selector "#card" --shot motion.png
npx remotion still src/index.tsx LaunchCard out/f.png --frame=45
npx remotion studio src/index.tsx # assista em 1x
check-contract.mjs captura as falhas silenciosas sem instalar nada: uma
timeline não registrada, uma chave window.__timelines incompatível, uma timeline
não pausada, uma duração ausente, Math.random() em uma composição, interpolate sem
clamp. É uma pré-verificação, não um substituto para os lintners reais.
Quando brief.json está no projeto (ou --brief aponta para um), ele também
compara a construção com o brief. Todo requisito termina como verificado, falhou
ou não_verificado. não_verificado não é aprovado e bloqueia a renderização.
| Código | Status | Significado |
|---|---|---|
brief_formato_incompativel | falhou | Largura, altura, fps ou duração diferem de formato |
brief_contagem_cenas, brief_cena_nao_mapeada | falhou | Uma batida não tem cena que declare seu id, ou uma cena não tem batida. Posição não é identidade |
brief_temporizacao_incompativel | falhou | Uma cena não começa ou dura o que o brief diz, dentro de um quadro |
brief_copia_ausente | falhou | A linha não está na cena. Comentários e variáveis não utilizadas não contam |
brief_copia_cena_errada | falhou | A linha está apenas em outra cena |
copia_nao_visivel | falhou | Tempo de execução: no DOM mas oculta, transparente, fora da tela, recortada, desfocada ou coberta |
copia_segurar_curto | falhou | Tempo de execução: legível por menos de batidas[].segurar |
primeiro_quadro_vazio | falhou | Tempo de execução: visivelNoInicio está definido e nada da batida é pintado |
primeiro_quadro_nao_verificado | não_verificado | Tempo de execução: apenas um gráfico está no primeiro quadro, ou a batida não tem cópia. Olhe para o quadro |
brief_temporizacao_nao_verificada, brief_formato_nao_verificado | não_verificado | A fonte calcula isso. O tempo de execução pode resolver |
brief_copia_dinamica, brief_copia_nao_verificada | não_verificado | Se é mostrado é uma questão de tempo de execução. A cópia do Remotion é sempre esta até o tempo de execução |
A correspondência ignora maiúsculas/minúsculas e espaços em branco e dobra aspas curvas. Outra pontuação é
significativa, e "12.480" corresponde a uma contagem que se estabiliza em 12480. Quando
os requisitos permanecem não verificados, diga quais, e tente torná-los mensuráveis antes de
aceitá-los. Aceitar um significa nomeá-lo, com
--allow-unverified "batida.linhas.copia[0].visivel", e relatar isso ao usuário.
Nunca aceite um padrão genérico, e falhas não podem ser aceitas de forma alguma. Leia
references/validation.md para as regras e limites exatos.
Corrija a deriva no código, ou mude o brief intencionalmente e execute brief.mjs novamente —
nunca deixe os dois discordarem.
Revise os quadros — toda verificação pode passar em um filme quebrado
Um contrato aprovado diz que temporização e cópia correspondem, e que o texto é legível. Ele não diz nada sobre paleta, suavização, transições, ou se o filme funciona. Os verificadores de lint, layout, movimento, contraste e qualidade passaram no modelo desta própria habilidade enquanto ele cortava para preto em cada batida e encerrava sua contagem no instante em que o número pousava. Apenas olhar para os quadros capturou isso. Capture-os:
# HyperFrames: quadros de batida, uma tira de 5 quadros em torno de cada corte, e uma folha de celular
node scripts/motion-render.mjs --brief ./meu-video/brief.json --snapshot --no-render
# Remotion: para cada corte c (em quadros), pegue c-6, c e c+6, mais o meio de cada batida
# (o modelo corta em 75, 210 e 270)
node scripts/motion-render.mjs --dir ./meu-video --no-render \
--stills 37,69,75,81,142,204,210,216,240,264,270,276,315
Em seguida, leia as imagens e responda a cada pergunta. Corrija o código, recapture, olhe novamente:
- O corte está preto? Mais de um quadro vazio em torno de um corte significa que a saída
termina cedo e a próxima batida aparece do nada. Mova a saída para que ela
termine no corte (
inicio = duração da batida − duração da saída). - A recompensa se sustenta? O número final de uma contagem, ou a última palavra de uma linha,
fica parado na tela por pelo menos uma batida (
60 / bpms) antes de sair. Sair no momento em que pousa significa que nunca é lido. - Dá para ler em um celular? Verifique
review-phone.jpg, ou imagine o quadro com 360 px de largura. Em 1080p, rótulos e tags abaixo de ~40 px geralmente falham. - É a fonte do brief? Uma fonte de fallback como Segoe UI ou Arial significa que a fonte nunca
carregou, e outra máquina renderizará um filme diferente.
--runtimeavisa comfonte_fallback, e o relatório registra as fontes realmente desenhadas. Remotion precisa de@fontsource/*(a escolha do modelo) ou@remotion/fontspara um arquivo local. - É a transição do brief?
sentir.transicaoestá nos quadros em torno de cada corte, não um mergulho no preto.
Concluído quando você leu os quadros de batida e cada tira de emenda, respondeu a cada pergunta acima, e cada linha da checklist sob "Checklist de entrega" se sustenta.
5. Renderize
node scripts/motion-render.mjs --brief ./meu-video/brief.json
node scripts/motion-render.mjs --brief ./meu-video/brief.json --batch rows.json --no-audio
O wrapper lê abordagem, formato, fps e slug do brief, e para antes que qualquer tempo de
renderização seja gasto se o brief, as verificações estáticas, as ferramentas, os assets ou a verificação de
tempo de execução disserem isso. Ele sai com 1 em uma falha e 3 em requisitos não verificados.
--no-checks pula a validação e registra isso no relatório. Em seguida, ele faz lint, renderiza,
mede o arquivo com ffprobe e escreve <saida>.report.json.
Quando audio.politica é gerado, em qualquer abordagem, ele sintetiza a base com
music.mjs, renderiza o vídeo apenas com imagem, e multiplexa os dois com uma chamada ffmpeg
— para que a composição nunca dependa do mixer de áudio de um motor. Em seguida, ele mede
que o arquivo tem um fluxo de áudio e que não está silencioso.
Para transparência: --format webm ou --format mov — H.264 não pode transportar alfa.
--no-audio pula a base e fornece um arquivo sem fluxo de áudio. GIF não pode transportar
áudio, então um brief com uma base é recusado para GIF a menos que você passe --no-audio.
Com --batch, um brief mais um arquivo de linhas se torna N vídeos: HyperFrames renderiza
linhas nativamente, Remotion recebe um arquivo de props por linha. Batch é apenas vídeo, e um brief
com uma base é recusado a menos que você passe --no-audio.
Concluído quando o arquivo existe, o relatório diz renderizado, sua lista naoVerificado está
vazia ou você informou ao usuário o que está nela, e seu primeiro e último quadros são
intencionais.
O contrato que quebra silenciosamente
HyperFrames — quatro coisas, todas obrigatórias:
- A raiz carrega
data-composition-id,data-width,data-height,data-duration,data-start="0". - Cada elemento temporizado carrega
id+data-start+data-duration. - A timeline GSAP é construída com
{ paused: true }. window.__timelines[<data-composition-id>] = tl— mesma chave. Depois que os tweens são adicionados. Perca isso e você obtém um quadro estático, sem erro.
Remotion — três:
registerRoot()no arquivo de entrada,<Composition>no componente raiz.interpolate(..., { extrapolateLeft: "clamp", extrapolateRight: "clamp" })— clamp em ambas as extremidades, todas as vezes.- Sem
Math.random(), semDate.now()em uma composição. Userandom(seed).
As quatro regras que decidem se parece barato
Estas são as que dão errado com mais frequência. Conjunto completo com código em
references/motion-craft.md.
- Mova apenas o que está ativo. Coisas estabilizadas ficam paradas. Uma escala de "respiração" ociosa parece gerada por máquina.
- Sobreponha, não enfileire. Intercale ≈ 15–30% da duração do próprio elemento. A próxima coisa começa enquanto a última ainda está se estabilizando.
- Sem bounce em texto. Overshoot é para objetos com massa — cartões, abas,
personagens. Texto, números e rótulos de UI usam
power3.out/expo.oute nunca overshoot. - Uma ideia por movimento.
y + opacidadeé "chegando". Adicione rotação e escala e a palavra fica ilegível durante o voo.
Também: uma transição é a saída, não um fade-out seguido por um fade-in. Isso renderiza como um corte abrupto com um mergulho no meio.
Checklist de entrega
-
brief.jsonvalida: temporização das batidas, primeiro quadro intencional, segurar final ≥ 2 s. -
check-contract.mjs --runtimedizverificado, ou os ids não verificados são aceitos por nome e reportados ao usuário. - Cópia, números, handles e URLs estão como escritos — sem lorem, sem placeholder.
- Timeline registrada sob o id da composição (HyperFrames), ou composição
listada por
npx remotion compositions(Remotion). - Lint/check limpo.
-
<saida>.report.jsondizrenderizado, com o tamanho, fps, duração e áudio esperados. - Quadros inspecionados: cada batida, cada emenda, largura de celular — sem preto em um corte,
…[truncado para tradução]