Communitygithub.com

dmtrKovalenko/fframes

Crie, anime, revise e renderize vídeos em código com fframes (Rust, cenas SVG, codificação ffmpeg, renderização GPU Skia). Use sempre que o usuário quiser um vídeo, animação, motion graphic, explicativo, promo, clipe social, título, visual de podcast, vídeo de legenda/lyrics ou qualquer .mp4/.webm renderizado programaticamente, ou pedir para alterar, corrigir, acelerar ou verificar um vídeo fframes. Abrange instalação do fframes, criação de projeto, design de movimento de boa aparência, tomadas 3D (fframes::three_d, cenas estilo three.js), som (música, voz, SFX, volume), visualização em janela de pré-visualização em tempo real e verificação do resultado sem assisti-lo: frames e folhas de contato em PNG, detecção automática de problemas, números de loudness, renders rápidos (draft) e por intervalo.

O que é fframes?

fframes é uma biblioteca Rust que permite criar vídeos programaticamente a partir de código, combinando cenas SVG, animações por timeline e molas, áudio sincronizado e codificação ffmpeg. Ela oferece um pipeline completo: desde a instalação e criação de projetos via CLI, até a pré-visualização em tempo real com suporte a GPU Skia (Metal/Vulkan) para renders rápidos. O usuário pode revisar cada frame com comandos como `strip`, `frame` e `inspect`, que detectam automaticamente problemas como pops, texto cortado ou fontes ausentes. A biblioteca também suporta tomadas 3D com `fframes::three_d`, edição de áudio com análise de loudness (LUFS) e exportação final em .mp4 ou .webm. O fluxo de trabalho enfatiza o planejamento do design de movimento antes da codificação, evitando padrões genéricos e garantindo que cada elemento tenha um propósito único e alinhado ao tema do vídeo. É especialmente útil para desenvolvedores que desejam automatizar a criação de vídeos promocionais, explicativos ou mídias sociais com controle preciso sobre cada quadro.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/dmtrKovalenko/fframes/tree/HEAD/skills/fframes-video

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Fazendo vídeos com fframes

fframes é uma biblioteca Rust que renderiza vídeo a partir de código. Um vídeo é uma struct Rust com um método render_frame(frame) -> Svgr: para cada frame ele retorna uma árvore SVG, construída com a macro svgr! (marcação SVG com {expressões rust}). As cenas dividem a linha do tempo, timeline! e molas animam valores, um mapa de áudio coloca o som e o ffmpeg codifica o resultado.

Cada projeto recebe uma linha de comando (de fframes::cli). Use-a para tudo: renderizar um vídeo, abrir a janela de pré-visualização em tempo real e visualizar frames, folhas de contato e números de loudness como arquivos que você pode ler. Leia references/design.md antes de projetar, references/api.md enquanto escreve código, references/audio.md para som e references/3d.md para tomadas 3D (fframes::three_d).

Ao corresponder a um vídeo fornecido, siga primeiro a orientação de análise de referência em references/design.md. Seus cortes, ritmo e movimento têm precedência sobre os padrões de design abaixo; edições rápidas e quadros pretos intencionais podem fazer parte do resultado solicitado.

Duas regras antes de tudo

Planeje antes de escrever código

Não abra o template e comece a animar. Primeiro:

  1. Defina o briefing: quem assiste e onde (a plataforma decide formato e duração), a única coisa que o espectador deve lembrar, o tom e os ativos que existem (logotipo, fotos do produto, filmagens, música, voz-over). Pergunte ao usuário o que está faltando e é importante. Nunca invente fatos, números ou citações do produto.
  2. Quando o vídeo for cortado para música ou voz, escolha o som primeiro. Seu tempo, batidas e frases definem o tempo de tudo o resto.
  3. Planeje o design de movimento primeiro, sincronize o design de movimento com os picos de som para criar um fluxo único: de onde os elementos aparecerão, como eles se transformarão. Tente criar um design de movimento único para cada cena para que pareça único e polido. O vídeo não deve parecer uma apresentação de slides.
  4. Tente refletir sobre a sensação da pessoa que está assistindo ao vídeo final e ajuste cada parte do design que você fizer de acordo: o fluxo, tempo, batidas, movimento e cores.

Sem porcaria

Porcaria é um vídeo feito de escolhas padrão: poderia ser sobre qualquer produto apenas com o texto alterado, e os espectadores o reconhecem em um segundo. A menos que o usuário peça, não entregue:

  • Sobras do template: o layout inicial, cores, fonte ou decorações, texto placeholder, logotipos falsos, números inventados.
  • Spam de batida: toda a tela com zoom, tremor ou piscando em cada batida. Sincronize coisas pequenas com a batida (um traço, uma palavra, uma faísca) e mude a tela inteira apenas em alguns cortes.
  • Um movimento para tudo: todo elemento desvanecendo 40 px com a mesma suavização e duração.
  • Cenas estáticas: uma coisa aparece, segura e desvanece enquanto nada mais se move.
  • Cópia genérica: "Apresentando", "Liberte", "Integrado", "Próximo nível", slogans de três palavras ("Rápido. Simples. Poderoso."). Escreva o texto na tela como uma pessoa diria.
  • Texto em geral: a quantidade de texto deve ser limitada e direta.

Em vez disso, dê a cada elemento uma razão ligada ao assunto e remova o que não tem. Gaste o esforço em detalhe e movimento em vez de palavras: movimento secundário, entradas escalonadas, traços desenhados, objetos que reagem uns aos outros, elementos transportados entre cortes. Antes de mostrar qualquer coisa ao usuário, olhe para uma tira e pergunte se o vídeo ainda funcionaria para um produto diferente apenas com o texto alterado. Se funcionasse, mude a ideia, não as cores.

1. Instalação

Rust de https://rustup.rs, depois as bibliotecas do sistema com as quais o ffmpeg é construído:

# macOS
brew install pkg-config ffmpeg x264 x265 opus nasm ninja
# Debian / Ubuntu
sudo apt-get install -y yasm nasm ffmpeg libx264-dev libx265-dev libopus-dev libclang-dev clang ninja-build libvpx-dev libasound2-dev
# Arch
sudo pacman -S ninja yasm nasm ffmpeg x264 x265 opus clang

Windows vincula uma compilação compartilhada pré-construída do FFmpeg 9 (defina FFMPEG_DIR para a compilação descompactada ffmpeg-n9.0-latest-win64-gpl-shared de BtbN/FFmpeg-Builds, adicione seu bin ao PATH, instale o LLVM com winget install LLVM.LLVM e defina LIBCLANG_PATH). Os detalhes estão no README do fframes.

2. Criar um projeto

curl -fsSL https://raw.githubusercontent.com/dmtrKovalenko/fframes/main/scripts/new-video.sh | bash -s -- my-video --yes
# ou instale o gerador uma vez e use-o diretamente:
cargo install --locked cargo-fframes
cargo fframes new my-video --format landscape --fps 30 --yes

Opções: --template single-scene|multi-scene, --format landscape|portrait|square|uhd, --fps, --title, --backend, --dir. O projeto depende da versão do fframes que corresponde ao cargo-fframes instalado; --git usa o branch main do repositório. Sempre passe --yes para que nada espere por entrada.

Templates:

  • single-scene (padrão): uma cena. Adapta-se a todos os formatos; comece aqui para clipes de uma única tomada, cartões de título e vídeo vertical.
  • multi-scene: duas cenas. Comece aqui para qualquer coisa com várias cenas; aceita apenas landscape e uhd.

O conteúdo do template é código placeholder que mostra a API. Substitua seu layout, cores, fontes e decorações por um design feito para o vídeo que o usuário solicitou.

Use o backend GPU Skia (o padrão). cargo fframes new escolhe Skia no Metal (macOS) ou Vulkan (Linux, Windows). Renderiza cerca de 10x mais rápido que o backend CPU e fornece a janela de preview em tempo real. No macOS e Linux, a primeira compilação baixa Skia e ffmpeg pré-construídos e compila apenas as dependências Rust (cerca de um minuto; outros alvos, ou metal e vulkan juntos, compilam Skia da fonte por ~20 minutos). Inicie logo e escreva o vídeo enquanto ele é executado:

cd my-video && cargo build --release        # execute em segundo plano, a primeira compilação é a mais lenta

--backend cpu não precisa de Skia, mas não tem janela de pré-visualização; escolha-o apenas quando não houver GPU.

O projeto é renderizado conforme gerado:

my-video/
  src/lib.rs        # o vídeo (do template)
  src/main.rs       # a linha de comando
  media/            # fontes, imagens e áudio compilados no binário (uma fonte inicial)
  README.md         # os comandos abaixo

Cada comando abaixo é cargo run --release -- <command>. Defina uma função shell curta (uma variável como R="cargo run --release --" não divide em palavras no zsh, o shell do macOS):

R() { cargo run --release -- "$@"; }

3. O loop

Não escreva testes ao usar esta skill. Não crie testes unitários, de integração, snapshot ou de regressão visual, módulos de teste ou harnesses de teste. Valide o vídeo com inspect, frames renderizados, folhas de contato, verificações de áudio e a pré-visualização nativa.

Pré-visualize, não renderize. Se o vídeo usa o backend de renderização GPU e uma GPU está disponível nesta máquina, execute a pré-visualização nativa (ou mostre o comando ao usuário) em vez de renderizar o vídeo novamente após cada alteração. Depois que as alterações estiverem prontas para revisão:

  1. Mostre um comando completo em um bloco de código shell copiável, usando o caminho real do projeto e o nome do pacote; não exija que o usuário tenha definido o auxiliar $R. Por exemplo: cd /caminho/absoluto/para/fframes && cargo run --release -p meu-video -- preview 0s.
  2. Ofereça-se explicitamente para executar essa pré-visualização para o usuário. Se eles já autorizaram abrir ou atualizar a pré-visualização, mostre o comando e continue dentro dessa autorização.

Após uma alteração solicitada, defina o horário de início do comando para um segundo específico em ou logo antes da seção alterada, com tempo suficiente de lead-in para ver sua entrada ou transição. Por exemplo, preview 8.5s permite que o usuário revise uma alteração por volta de 9 segundos sem reproduzir o início. Indique qual seção eles verão. Renderize o vídeo completo quando o usuário solicitar a exportação final; não exija outra confirmação se essa solicitação já for explícita.

Após cada alteração:

  1. $R timeline lista as cenas com seus intervalos de frame e segundo, e cada faixa de áudio. Verifique a estrutura e o ritmo aqui antes de olhar para os pixels.
  2. $R inspect verifica um frame a cada 0,25 s mais o primeiro e o último frame de cada cena. Relata imagens, fontes ou glifos ausentes, texto cortado pela borda do canvas, SVG inválido (retângulos de tamanho zero, raios ruins), transformações quebradas e panics, cada um com seu tempo e cena. Ele sai com código 2 em erros. Corrija tudo o que relatar. Um aviso que aparece apenas nos primeiros frames de uma cena geralmente é uma entrada; verifique com uma tira.
  3. $R strip <scene or range> -n 12 escreve uma folha de contato (strip.png): frames uniformemente espaçados em uma imagem rotulada. Abra-a com sua ferramenta de imagem. É a maneira mais rápida de julgar layout, ritmo e movimento. $R strip 2s,5s,9s coloca os tempos escolhidos lado a lado.
  4. $R frame Intro@end,Outro@50% escreve PNGs em tamanho real em frames/ para verificações de detalhes (tipografia, alinhamento, contraste) e imprime problemas encontrados nesses frames. Julgue pequenos detalhes (contato entre elementos, bordas, formas pequenas) em um recorte ampliado e nítido, nunca em um frame reduzido: $R frame 3s --crop 1100,520,240,120 (pixels do vídeo, ampliado para cerca de 960 px de largura). --ids contorna e nomeia cada elemento que tem um id, para descobrir qual forma é qual.
  5. $R onion "[email protected]@1s" -n 6 mescla frames em uma imagem (onion.png) para mostrar o caminho e o espaçamento de um movimento: suavização, overshoot, stagger.
  6. $R preview Intro abre uma janela em tempo real com som para o usuário assistir (espaço play/pause, h/l avança um segundo, j/k avança um frame, q sair). Ela bloqueia até ser fechada, então inicie em segundo plano ao executá-la para o usuário. Mostre o comando e ofereça-se para lançá-lo conforme descrito acima; após edições, use um segundo específico próximo à alteração.

Quando uma amostra codificada for necessária, $R render Intro --draft codifica uma cena na metade da resolução. $R render escreve o vídeo completo para uma exportação final solicitada.

Antes de mostrar um vídeo finalizado, execute $R inspect --pops: ele renderiza cada frame pequeno e avisa sobre pops, partes da imagem que mudam em um frame entre frames parados, como um elemento que aparece, desaparece ou salta na frente de outro em vez de se mover para lá. Cada aviso fornece o comando frame ... --crop ... para visualizá-lo; repetições da mesma região (contadores, luzes piscando) são agrupadas em um aviso.

Regras:

  • Olhe para os PNGs antes de dizer que algo parece bom.
  • Prefira strip a muitas chamadas frame; adicione --scale 0.5 quando a composição for tudo que você precisa.
  • Adicione --json ao analisar a saída: o resultado vai para stdout, o progresso para stderr.
  • Mantenha --release: compilações debug renderizam muitas vezes mais devagar.

Endereçando tempo

120 (frame), 3.2s, 500ms, 1:05.5, 50%, start, end; cenas pelo nome da struct, Intro (também corresponde a IntroScene, case-insensitive), #3 (índice da cena), Intro[1] (segunda cena desse tipo); dentro de uma cena [email protected], Intro@12, Intro@50%, Intro@end. Intervalos: a..b (final exclusivo), a.., ..b, all, ou um nome de cena para a cena inteira. Separe vários tempos com vírgulas.

Todos os comandos

comandouse para
timelinever cenas, durações, faixas de áudio e suas configurações de mix
inspect [RANGE] [--every 0.1s | --all-frames] [--fail-on warning] [--pops]encontrar problemas sem renderizar pixels; --pops também encontra elementos que aparecem ou desaparecem
strip [RANGE | TIMES] -n N [--columns 4] [--width 480] [--crop x,y,w,h]revisar fluxo e movimento em uma imagem
frame TIMES [-o dir] [--svg] [--crop x,y,w,h] [--zoom N] [--ids]PNGs em tamanho real (e o SVG layoutado) de frames escolhidos, recortes nítidos, elementos rotulados
onion RANGE -n Nver a trajetória e suavização de um movimento
svg TIMEler o SVG final de um frame como texto (posições, texto, cores)
preview [TIME] [--paused] [--mute]janela em tempo real com som, para o usuário
render [RANGE] [-o out.mp4] [--draft]codificar o vídeo ou uma parte dele (áudio cortado para corresponder)
audio analyze [RANGE] [--waveform w.png]loudness (LUFS), pico real, clipping, silêncio, por cena
audio at TIMESquais sons tocam em um momento, onde em seu arquivo e quão alto
audio render [RANGE] -o a.wavo mix como um arquivo WAV

Editor no navegador

fframes também tem um editor web com linha do tempo e scrubbing, útil quando uma pessoa deseja ajustar um vídeo interativamente. Ele executa o vídeo compilado para WebAssembly e precisa de Node.js mais wasm-pack; a configuração é a pasta editor/ do exemplo hello-world no repositório fframes (https://github.com/dmtrKovalenko/fframes/tree/main/examples/hello-world). Mencione-o quando o usuário pedir um editor GUI. Para assistir, use preview, e para sua própria revisão, use o CLI.

4. Escrevendo o vídeo

impl Video for MyVideo<'_> {
    const FPS: usize = 30; const WIDTH: usize = 1920; const HEIGHT: usize = 1080;
    fn duration(&self) -> Duration<'_> { Duration::Auto }            // soma das cenas
    fn audio(&self) -> AudioMap<'_> { AudioMap::none() }              // veja references/audio.md
    fn define_scenes(&self) -> Scenes<'_> { Scenes::from(vec![&self.intro as &dyn Scene, &self.main]) }
    fn render_frame<'a>(&'a self, frame: Frame, ctx: &FFramesContext<'a, '_>) -> Svgr<'a> {
        fframes::svgr!(<svg xmlns="http://www.w3.org/2000/svg" width={Self::WIDTH} height={Self::HEIGHT}>
            <rect width={Self::WIDTH} height={Self::HEIGHT} fill={BACKGROUND} />
            {ctx.render_scenes(&frame)}
        </svg>)
    }
}
  • Uma cena por ideia, 2-6 s cada. Dentro de uma cena frame.seconds() conta a partir do início da cena.
  • Padrão: use frame.animate(fframes::timeline!(...)) diretamente nos atributos svgr! para movimento com valores fixos. svgr! eleva essas animações para estáticos em cache. Defina suavizações inline no timeline, incluindo Easing::Spring { mass: 1.0, stiffness: 180.0, damping: 20.0 }; constantes de suavização nomeadas são opcionais. Deixe o tempo final fora de uma mola para que ela...

Habilidades Relacionadas