Reel — Edição de história (tela cheia com movimento)
O orador permanece em tela cheia. A história é contada por cortes para os próprios clipes do criador, adesivos/cartões/widgets que surgem nas palavras faladas, um mascote reagindo e momentos de profundidade onde palavras gigantes ou um fundo de marca ficam atrás do orador (máscara de pessoa). Exemplo prático: examples/story/story_stoodi_inviteraw.py.
Argumentos: $ARGUMENTS
Padrões (alterar apenas se o usuário disser)
Leia reel.config.json primeiro (fallback para reel.config.example.json).
| Coisa | Padrão |
|---|---|
| Legendas | Nenhuma. Gráficos de palavras-chave estão ok; nunca uma transcrição contínua |
| Áudio | Mixagem própria do take, intacta — finish.py remuxa. Sem efeitos sonoros, sem fundo musical |
| Take | Presumir já cortado, corrigido, com música adicionada → não cortar nem corrigir. Bruto/sem corte → perguntar primeiro |
| B-roll | broll_dir do config; descrições em work/_catalog/<pasta>/NOTES.md |
| Marca | brand + palette do config. Sem arquivos de mascote → sem cenas de mascote |
| CTA | Palavra-chave do comentário enorme na tela; cartão de seguir = apenas texto @<handle do criador>, nunca um recorte de rosto |
| Idioma | language do config (Whisper + qual classe de texto usar) |
Entradas
Nome do take + tópico vêm dos argumentos. Pergunte uma vez, em uma mensagem, apenas o que estiver faltando: o take já está cortado/corrigido/com música; palavra-chave do comentário; nomes ou jargões que o Whisper pode ouvir errado; clipes que eles querem incluir ou excluir.
Pipeline
PY = .venv/Scripts/python.exe -X utf8 (Windows) ou .venv/bin/python -X utf8 (macOS/Linux). Etapas longas em segundo plano.
| # | Etapa | Comando / ação | Verificar |
|---|---|---|---|
| 1 | Olhar | ffprobe o take; folha de contato ffmpeg -i raw/<take> -vf fps=1/5,scale=216:384,tile=9x2 -frames:v 1 work/<take>/sheet.jpg e olhar | espaço acima da cabeça, texto no quadro espelhado?, já corrigido? |
| 2 | Transcrever | $PY tools/transcribe.py <take> --prompt "<nomes, jargões>" | revisar nomes; lacunas de palavra > 3 s → re-transcrever essa janela |
| 3 | Rosto | $PY tools/face_track.py <take> | imprime FACE = (x, y) e topo da cabeça |
| 4 | B-roll | $PY tools/story_assets.py <take> catalog; ler NOTES.md; olhar as tiras de clipes ainda não descritas e adicionar suas linhas ao NOTES.md | flags HDR / espelhado / VFR |
| 5 | Roteiro de batidas | escrever work/<take>/beats.md: tempo | palavras | modo | o quê. Regras abaixo, técnicas em references/techniques.md | cada batida ancorada a uma palavra |
| 6 | Máscara | se houver algum momento de profundidade: $PY tools/story_assets.py <take> matte (~8 min CPU para 80 s, segundo plano, sem ffmpeg paralelo) | work/<take>/matte/fg.webm |
| 7 | Módulo do take | copiar examples/story/story_stoodi_inviteraw.py → tools/story_<slug>.py (slug: nome do take, não alfanumérico → _); definir NAME, FACE, BROLL, TILES, MIRRORED, cenas, SCENES (DUR opcional — sondado). Nomes do mascote = os arquivos em assets/mascot (minúsculas, espaços → -) | |
| 8 | Assets | $PY tools/story_assets.py <take> all (mascote, logotipo, cortes de B-roll, tiles) | |
| 9 | Construir | $PY tools/story_build.py <take>; em work/<take>/sc: npx hyperframes lint public → 0 erros (avisos nested_structure são esperados); npx hyperframes snapshot public -o ../snaps --no-end --describe false --at <cada batida>; ler as folhas de contato, corrigir, reconstruir | |
| 10 | Renderização rápida | $PY tools/finish.py <take> --seconds 12; ler work/<take>/sc/quick_sheet.jpg | sobreposições entram e saem; cores não esmaecidas |
| 11 | Renderização completa | $PY tools/finish.py <take> (~12 min para 80 s, segundo plano) → final/<take>/, verificar, qa/sheet.jpg | ler a folha quadro a quadro |
| 12 | Relatório | caminho, duração, batidas, clipes usados, qualquer coisa invertida/remapeada de tom, verificar resultado. Se algo novo foi aprendido, adicionar a este skill |
Regras de batida
- Algo muda a cada 2–4 s; nunca mais de ~5 s de orador puro.
- Misture os modos: orador + adesivos · corte para B-roll (~25–30% do tempo) · momento de profundidade (4–6 por reel) · tela cheia com o orador como bolha de câmera (1–2 no máximo).
- Deixa = tempo de início da palavra falada em
transcript.json. Cada elemento sai antes da próxima batida. - Palavras de profundidade vão acima da cabeça (topo da cabeça da etapa 3): uma palavra gigante por vez, a palavra anterior voa para fora. Linhas empilhadas acabam escondidas atrás da cabeça.
- Zonas seguras: nenhum texto acima de y 150 (cabeçalho do Instagram) ou abaixo de y 1560 (legenda); manter x < 960 entre y 1100–1650 (botões de curtir/comentar).
- Números mostrados como fatos devem vir do take. Rótulos ilustrativos são aceitáveis.
- Texto em persa/árabe: classe
.fa(RTL com escopo no elemento — nuncadir="rtl"no<html>, isso renderiza preto),letter-spacing: 0, dígitos viafa(), um zero grande como0latino (zero persa é um ponto). Texto latino:.en; palavras de exibição gigantes:.blk.
Contrato do mecanismo — bugs já pagos
- Cena =
def scene(c: Comp):c.clip(layer, id, start, end, html, track),c.broll(name, a, b, mstart),c.matte(n, a, b),c.j(js...). Camadas:under(atrás da bolha),tiles,behind(entre take e máscara),fw,broll,over,fx. - Divs de clipe recebem id
k-<id>; animar#<id>-iou ids internos — nunca um.clipem si. - Qualquer coisa que deslize de fora da tela precisa de
autoAlpha:0em seu estado inicial, ou aparece prematuramente. - Primeiro tween de um elemento define seu estado inicial (
fromTorenderiza imediatamente); tweens posteriores:.toouimmediateRender:false. - Nunca usar
from:"random"stagger ouMath.random— embaralhar a ordem DOM em Python comrandom.Random(seed). - Mesma propriedade, mesmo elemento: um tween deve terminar antes do próximo começar (lint
overlapping_gsap_tweens). #camescala/x/y/clipPath/borderRadius controlam aproximações, bolha e mosaico. A máscara fica dentro de#cam, então momentos de profundidade permanecem alinhados em qualquer escala de câmera.- B-roll de câmera frontal com texto legível no quadro → adicionar a
MIRRORED. Nunca inverter o take principal. - Fontes HLG/HDR são remapeadas de tom por
story_assets.py. Sefinish.pyparar em "HDR auto-promotion", uma fonte escapou desse caminho. hyperframes snapshotnão é prova da renderização — para isso serve a etapa 10.