Vídeo 100 % com código (Remotion + áudio local)
Ordem de trabalho (não alterar a ordem)
- História primeiro (método HyperFrames
story.md): a única coisa, 3 storylines, gancho nos primeiros 2 segundos, beats com porcentagens, "tells" de vídeo gerado proibidos (tudo entra igual, flutuar sem causa, cartões em fila, logo flutuante). EscreverSCRIPT.mdcom timecodes. - Vozes → durações reais →
timeline.json(cenas, início de cada linha, eventos, seções musicais). Áudio e vídeo leem o mesmo JSON. - Áudio mestre (música + SFX + vozes com ducking, −15.5 LUFS, pico ≤ −1 dBTP).
- Cenas no Remotion, uma composição
Filmcom<Sequence>por cena; revisar fotogramas de controle (contact sheet) antes de renderizar. - Render por cena (
--frames=a-b --muted) → concat → mux com ffmpeg → QC com fotogramas extraídos.
Motor
npx create-video@latest --yes --blank --no-tailwind <dir>;npx remotion add @remotion/transitions @remotion/media @remotion/effects @remotion/noise @remotion/paths @remotion/shapes @remotion/motion-blur @remotion/fonts.- Sandbox sem GPU: em
remotion.config.ts→Config.setBrowserExecutable(<chrome-headless-shell>),Config.setChromiumOpenGlRenderer("swangle"),setConcurrency(2),setCrf(18),setPixelFormat("yuv420p"). - Fontes: pacotes
@fontsource[-variable]/*(npm chega; Google Fonts não). Aguardardocument.fonts.load()comdelayRenderantes de capturar (glifos áéíóúñ¿¡). - Regras Remotion: tudo deriva de
useCurrentFrame();interpolatecom clamp;random(seed)do Remotion; nada de CSStransition/animation,Math.random,Date, timers,useFrame. - Custo medido (2 CPU, 1080p): cena vazia ≈0.1 s/q; 2000 sprites canvas ≈0.7 s/q;
filter: blur()em tela cheia ≈2.5 s/q. Partículas: closed-form (posição = f(seed, i, t)), sprites radiais pré-desfocados,globalCompositeOperation: "lighter". - Um curta de 3 min (5400 fotogramas, 1080×1920) levou ~1 h 30 em 2 CPU. Salvar o bundle (
npx remotion bundle) e renderizar a partir dele.
Kit reutilizável (não vem neste repositório; serve como lista de peças a construir)
anim.ts (easings por papel, spring fechado, keyedState, blink, drift), Camera2D.tsx (camadas com paralaxe/dolly), Particles.tsx (chuva, vaga-lumes, poeira, estrelas, grão), City.tsx (cidade neon procedural + reflexos), Text.tsx (kinetic, neon, legendas por palavra, título variável), Post.tsx (vinheta, flash, letterbox, raios), character/Mia.tsx (rig: pose + expressão + visemas A–H/X + piscada + respiração + rim light + adereço), character/Lucero.tsx, Flat.tsx (mundo plano a lápis com boil), ChatScreen.tsx, lipsync.ts. Scripts em tools/: voice.py, make_voices.py, asr.py, make_timeline.py, make_audio.py, render_all.sh, assemble.sh, sheet.py.
Personagens
- Rig = parâmetros numéricos (pose, expressão, visema) combináveis por quadro; presets de expressão; transições com
keyedState(antecipação → ação → settle). Cabeça guia, corpo segue; piscada a cada 2–5 s semeada; nunca mover tudo ao mesmo tempo com a mesma curva. - Lip-sync: Rhubarb
-r phonetic -f jsonsobre WAV 22 kHz mono 16 bit → cues A–H/X → misturar parâmetros de boca entre cues (blend 50 ms). Intensidade de abertura ×0,7 para sussurros. - Folha de personagem (expressões, visemas, poses) como still ANTES de animar.
Voz (português, local)
- Kokoro-82M ONNX (
kokoro-onnx, vozesef_dora,em_alex,em_santa, langes-419) e Piper (piper-tts,es_MX-claude-high,es_AR-daniela-high). Modelos em GitHub releases (thewh1teagle/kokoro-onnx, k2-fsa/sherpa-onnx). - Crianças: +4…+6 semitons com
rubberband -p N -F(formantes). Graves: −4. "Voz feita de muitas": camada −2 st (26 %) + camada +0,3 st atrasada 12 ms (18 %) + reverb grande. - Verificar sempre com ASR (Parakeet-TDT 0.6B v3 via sherpa-onnx ≥ 2.0): WER contra o texto; regenerar ou reescrever a frase se > 5 %. Verificar ANTES de aplicar efeitos (a reverb confunde o detector de idioma do ASR). Os timestamps por palavra do ASR alimentam as legendas.
- Se o usuário tiver sua própria voz (p. ex. ElevenLabs), substitui-se o WAV de cada linha e regeneram-se cues/timeline sem tocar nas cenas.
Música e SFX
- Compor MIDI com
pretty_midipor seções (bpm, progressão, instrumentos GM) →fluidsynth -ni -g 0.6 -r 48000 -F out.wav MuseScore_General_Full.sf3 in.mid→ pedalboard (HPF, compressor, reverb) → pyloudnorm. - Sincronia visual = mesma aritmética de beats (quadros por beat = fps·60/bpm, calcular cada beat a partir de seu índice).
- SFX com causa na tela; colocar o pico 1 quadro após a imagem; rotacionar tomadas; sintetizar com numpy o que não existir (zumbidos, chuva, lápis, shimmer, impacto sub).
- Mixagem: voz −20 dBFS RMS, música −8 dB abaixo da voz (ducking 120 ms / 700 ms), SFX −4 dB, master −15.5 LUFS, pico 0.6. Revisar com espectrograma (
ffmpeg showspectrumpic) que nenhum bed (chuva) tape a voz.
Direção (das skills lidas: Remotion, HyperFrames, iart-ai motion/kinetic/webgl, nolanx, anatomy, isometric-ops, taste-skill)
- Um movimento por beat; chegadas com cauda longa (
bezier(0.16,1,0.3,1)), saídas 40–50 % mais curtas; câmerainOut; títulos parados uma vez que aterrissam; 3–5 tipos de transição com causa; cortar no quadro mais rápido. - Paralaxe: fundo 0.1–0.3×, médio 0.5–0.7×, frente 1–1.5× com blur. Plano drone = pilha de planos aninhados com escala logarítmica (janela → fachada → quarteirão → mapa → nuvens → planeta).
- Isométrico: uma única projeção; sombras planas 15–30 %; topo mais claro.
- Tipografia: 2 famílias no máximo; títulos 4–9 % da altura; stagger letras 20–40 ms, palavras 40–70 ms; variable fonts para peso/largura.
- Vertical: conteúdo chave nos 80 % centrais; legendas sobre a zona segura inferior (≥ 110 px); texto ≥ 44 px; legendas por palavra para que se entenda sem som.