O que motion-reels faz?
Gráficos em movimento gerados por código para Reels verticais. Cada Reel é composto por um ou mais blocos. Um bloco é um pequeno arquivo JavaScript que posiciona títulos, desenhos, fotos e amostras em um mundo e define quando cada um aparece. Cada instante vem de uma linha do tempo de palavras: seja uma folha de beats (sem voz) ou as marcações de tempo de uma gravação de voz. O motor renderiza cada quadro em sua própria página de navegador, verifica o layout e monta o resultado com voz e/ou música.
A pessoa que é dona da página decide o visual, as palavras e o que é publicado. Claude nunca publica nada.
Configuração (uma vez)
- Python 3.10+ e ffmpeg/ffprobe no PATH. Depois, o
setup.ps1(Windows) ousetup.sh(macOS/Linux), oupip install -r requirements.txt+python -m playwright install chromium(ou envMG_CHROME= um Chrome existente). - Apenas voz:
pip install -r requirements-voice.txt(faster-whisper; a primeira execução baixa o modelo de fala). - Teste:
python engine/selftest.pydeve imprimirSELFTEST OK(verifica se os exemplos passam, testes negativos falham como esperado, legendas em árabe são divididas corretamente e uma renderização curta + varredura de falhas + montagem atinge -14 LUFS).--quickpula a renderização.
Arquivos do motor (todos em engine/): render.py (verificar / storyboard / stills / vídeo), beats.py, words.py, frames.py, faultscan.py, assemble.py, storyboard_sheet.py, make_grain.py, templates/ (shell, reel.js, reel.css, fontes).
Uma pasta por Reel
<nome do reel>/
brief.md para que serve o Reel, a ideia principal, a chamada para ação, fotos disponíveis
beats.txt as palavras na tela, um beat por linha (ou script.txt + take.wav quando há voz)
words.json linha do tempo (a partir de beats.py ou words.py)
photos/ as fotos do proprietário (apenas aquelas com direitos)
A.js, B.js ... blocos
build/ json de verificação, stills do storyboard, vídeos dos blocos, arquivos render.json, folhas de contato
<Reel>_REV01_<data>.mp4 o entregável; uma correção posterior é enviada como _REV02, nunca sobrescreve
Portões (nunca pule ou reordene; pare em cada ⛔ para o OK do proprietário)
- Brief. Uma ideia por Reel (revelação de um cômodo, história de material, mudança de planta, dica). Peça as fotos e o handle. Liste o que cada foto mostra. Engate nos primeiros 2 segundos.
- Folha de beats (
beats.txt): as palavras exatas na tela, em ordem, uma por linha. Mantenha um beat curto (2–7 palavras). Coloque cada item de uma lista em sua própria linha, para que cada um tenha tempo de ser assimilado. ⛔ O proprietário assina as palavras. Após a aprovação, alterar uma palavra significa re-temporizar o bloco (e re-gravar a voz, se houver): avise antes de mudar qualquer coisa. - Linha do tempo.
- Sem voz:
python engine/beats.py beats.txt words.json(ritmo padrão 2,6 palavras/s + 0,7 s após cada beat;[+1.5]no final de uma linha segura por mais tempo;[pause 2]segura sem nada novo). - Voz (qualquer TTS ou uma gravação, um take por bloco, nunca editado):
python engine/words.py take.wav words.json, depois compare a transcrição com o script palavra por palavra. A imagem se ajusta ao take, nunca o contrário.
- Sem voz:
- ⛔ Stills do storyboard. Construa os layouts dos blocos (apenas posições são suficientes), execute
check, depoisrender.py A.js words.json storyboard build/sbestoryboard_sheet.py build/storyboard.png build/sb. Faça uma auto-revisão da folha (lista abaixo) e envie-a. Nada é animado antes de o proprietário aprovar o layout. - Construir o movimento. Ative cada elemento na palavra que o nomeia (regras abaixo). Execute
checkapós cada alteração. - Renderizar.
render.py A.js words.json video build/A.mp4 --workers 4por bloco (nunca--draftpara qualquer coisa enviada). Obuild/A.mp4.render.jsonde cada bloco deve conter"capture": "fresh"e o mesmo navegador que os outros blocos; se o navegador mudou, re-renderize todos os blocos. - Varredura de falhas.
faultscan.py build/A.mp4 --sheet build/A_contact.pngem cada bloco e depois no Reel final. Examine cada momento sinalizado. Uma faixa preta ou um flash de um quadro é uma falha: pare e corrija. Conteúdo escuro em fotos é aceitável. - Montagem.
assemble.py blocks.json <Reel>_REV01_<data>.mp4 [--music bed.mp3]. Ele imprime o loudness medido; deve estar no alvo (-14 LUFS padrão) e o pico verdadeiro em ou abaixo de -1,5 dBTP. - ⛔ Revisão. Envie o Reel e sua folha de contato. Correções apenas visuais re-renderizam apenas os blocos alterados e são enviadas como a próxima _REV. O proprietário publica.
Regras de movimento (por quê: uma sensação calma e premium; nada treme, nada é difícil de ler)
- Palavras nunca se movem. Uma palavra aparece gradualmente (0,28 s) e depois fica parada. Sem deslizamento, escala, salto ou deriva no texto.
- Títulos:
hl(el, text, cue(...))faz cada palavra aparecer na sua própria palavra na linha do tempo. Quando um título parafraseia uma voz, use{stream:true}: as palavras aparecem da esquerda para a direita, com 0,1 s de intervalo, a partir do cue. - Câmera: completamente parada enquanto um plano é mantido; só desliza (0,8 s, ease-in-out) entre planos. Em 9:16, empilhe os planos verticalmente no mundo (plano 2 em y 1920, plano 3 em y 3840) e deslize para baixo:
SHOTS=[[t,540,960,1],[t2,540,2880,1],...]. - Fotos podem fazer zoom suave:
push:[1,1.04]= velocidade constante, nunca mais que +6 % (MOTION.PUSH_MAX; o motor recusa mais). Sem zoom em uma foto que contém texto. - Desenhos são revelados conforme são nomeados, referência primeiro: paredes antes da janela e da porta nelas, linha do piso antes das alturas medidas a partir dela.
at('#walls', cue('Walls'), null, 'draw', 0.9); 0,6–1,0 s por elemento. - Dimensões em uma única escala. Se uma planta mostrar duas dimensões, ambas usam a mesma escala.
- Rotule o que as palavras nomeiam; cada número nomeia sua unidade ("3,2 m", nunca um "3,2" solto).
- Nenhum bounce, overshoot, easing elástico ou de mola em nenhum lugar. Cada temporização vem de
MOTIONemreel.js; altere lá, nunca como literal em um bloco. - Um elemento SVG tracejado solto dado a
at()aparece antes de seu cue: envolva-o em um<g>.
Tokens de temporização (MOTION em reel.js)
| Token | Valor | Uso |
|---|---|---|
| WORD_FADE / WORD_LEAD | 0,28 s / 0,08 s | aparecimento da palavra; começa pouco antes da palavra |
| STREAM | 0,10 s | espaçamento entre palavras em modo stream de título |
| REVEAL / EXIT | 0,5 s / 0,4 s | blocos, chips, amostras, fotos entrando / saindo |
draw (at(...,'draw',dur)) | 0,6–1,0 s | por elemento desenhado |
| CAM_SLIDE / CAM_LEAD | 0,8 s / 0,35 s | deslizamento da câmera; começa antes do cue do plano |
| PUSH_MAX | 0,06 | limite de zoom de foto |
| WIPE | 1,2 s | transição antes/depois |
| Easing: ease-out cúbico para revelações, ease-in-out cúbico para deslizamentos, desenhos e wipes. |
Layout e a verificação
- Zona segura (
SAFEem reel.js): texto, rótulos e legendas permanecem dentro de x 65–1015, y 269–1248 do quadro 1080x1920 (topo 14 %, fundo 35 %, laterais 6 %). Esses números são orientação amplamente usada de terceiros para Reels, não uma regra publicada pelo Meta para postagens orgânicas: meça novamente a partir de uma captura de tela de celular de um Reel publicado e definasafeZone({...})se o aplicativo mudar. Fotos e desenhos podem se estender além disso; texto não pode. render.py <bloco> words.json check build/<bloco>.check.jsoné obrigatório antes de cada renderização. Ele amostra a cada 0,25 s e falha em qualquer sobreposição mantida por 0,5 s ou mais entre elementos separados (texto, desenhos, chips, amostras, fotos, legendas) e em qualquer texto fora da zona segura enquanto a câmera está parada. Uma falha significa corrigir o layout, nunca renderizar. Prove uma nova regra com um teste negativo (reintroduza uma falha conhecida; a verificação deve falhar).- Texto que pertence a uma foto vai dentro do elemento da foto (
parent: photoDiv) com umscrim()atrás, ou a foto é um fundo (bg:true). Caso contrário, a verificação relata texto sobre foto, que é o que você deseja. - A verificação não vê coisas cortadas na borda do quadro: a auto-revisão faz isso.
Construindo blocos (reel.js)
boot(()=>{ // todo bloco começa com boot(...)
handle('@yourstudio'); // handle pequeno no topo da zona segura
$('world').insertAdjacentHTML('beforeend', `<div id="h1" class="abs serif" style="left:90px;top:360px;width:900px;font-size:104px"></div>`);
hl('h1', 'A small room, *re-planned.*', cue('A small')); // *...* = itálico de ênfase; ~palavra = não está na linha do tempo
at('#walls', cue('Walls'), null, 'draw', 0.9); // fx: 'fade' | 'pop' | 'wipe' | 'draw'
photo({src:rel('photos/living.jpg'), x:0, y:1920, w:1080, h:1350, a:cue('Light'), push:[1,1.04]});
beforeAfter({before:rel('photos/before.jpg'), after:rel('photos/after.jpg'), x:90, y:2440, w:900, h:900, a:cue('Before'), t:cue('after')});
swatch({name:'Oak', note:'floor', color:'#B08A62', x:90, y:4480, size:270, a:cue('Oak')}); // ou src: rel('photos/oak.jpg')
clip({dir:rel('clips/walk'), n:240, x:0, y:5760, w:1080, h:1920, a:cue('Walk'), t0:cue('Walk')}); // quadros de frames.py
captions(1120, 3); // legendas queimadas no vídeo a partir da linha do tempo (Reels com voz)
SHOTS=[[0,540,960,1],[cue('Light'),540,2880,1]];
});
rel(path) resolve um arquivo ao lado do bloco. cue('words', after) lança um erro se as palavras não estiverem na linha do tempo, então um erro de digitação falha ruidosamente. Exemplo completo: examples/demo/demo.js.
Reels em árabe e outros RTL
- Chame
rtl()primeiro emboot(). Títulos usam Noto Naskh Arabic, texto IBM Plex Sans Arabic (OFL); o latim recai para as fontes padrão. Sem itálico, espaçamento entre letras ou maiúsculas em árabe (as letras devem se conectar); palavras de destaque mudam apenas de cor. - Caixas de texto mantêm
left+width; o texto alinha à direita. Disponha listas da direita para a esquerda (primeiro nomeado = mais à direita). - Cues ignoram diacríticos, tatweel, variantes de alef/yaa/taa-marbuta e convertem dígitos arábicos-índicos; um cue sem letras lança um erro. ة e ه contam como uma letra, então cue uma frase mais longa onde duas palavras diferem apenas lá. Palavras numéricas correspondem apenas em inglês: em árabe, cue os dígitos ou a palavra como transcrita (
words.py --lang arseleciona o modelo multilíngue). - Legendas quebram em ، ؛ ؟ e pontuação latina, e não a exibem.
- Exemplo:
examples/arabic/.
Visual
O tema vive apenas em engine/templates/reel.css (cores como variáveis CSS, fontes) e nos arquivos de fonte. Padrão "minimalista quente": papel #F4EFE8, tinta #2B2622, destaque #9C6B4E, títulos Cormorant Garamond + texto Jost (ambos SIL OFL 1.1). Para mudar o visual: edite as variáveis, ou adicione fontes OFL a engine/fonts/ com seu arquivo de licença e liste-as em fonts.css e window.FONTS (reel.js). Peça ao proprietário 3–5 capturas de tela de sua grade primeiro e combine com ela.
Auto-revisão (Claude, antes de enviar qualquer folha ou renderização)
- Cada elemento começa em sua palavra; linhas de referência desenham primeiro.
- Palavras paradas após aparecerem; câmera parada enquanto mantém o plano; sem salto no final de um deslizamento.
- Nada cortado na borda do quadro; todo texto dentro da zona segura; nada importante sob os 35 % inferiores.
- Dimensões em uma única escala; cada número tem sua unidade; ortografia corresponde à folha de beats assinada.
- VERIFICAÇÃO PASSOU em cada bloco;
render.jsondizcapture: fresh, mesmo navegador para todos os blocos. - Varredura de falhas limpa, ou cada momento sinalizado inspecionado e explicado.
- Loudness e pico verdadeiro impressos por
assemble.pyno alvo.
Direitos e privacidade
- Apenas as fotos do proprietário, ou aquelas com direitos.
- Casas de clientes: sem rostos, endereços ou documentos sem consentimento.
- Música: apenas faixas para as quais o proprietário tem licença, ou a biblioteca da própria plataforma adicionada no aplicativo ao publicar.
- Sem alegações que o proprietário não tenha feito (preços, prazos, prêmios).
Solução de problemas
cue not found: "...": as palavras não estão emwords.jsonnessa ordem; corrija a folha de beats ou o cue.ERR reqfail:file:///...jpg: um caminho de foto ou clipe está errado; userel()e verifique o nome do arquivo.- Cópias fantasmas de desenhos anteriores ou uma faixa preta: você renderizou com
--draft. Re-renderize sem ele. - Renderizações lentas:
--workers 4(até 8) em uma máquina com esse número de núcleos; verificação e storyboard são rápidos, vídeo não é.