Communitygithub.com

dmtrKovalenko/fframes

Crea, anima, revisa y renderiza videos escribiendo código con fframes (Rust, escenas SVG, codificación ffmpeg, renderizado GPU Skia). Úsalo siempre que el usuario quiera un video, animación, gráfico en movimiento, explicativo, promocional, clip social, tarjeta de título, visual de podcast, video de letras/capciones o cualquier .mp4/.webm generado mediante programación, o pida cambiar, arreglar, acelerar o revisar un video de fframes. Cubre la instalación de fframes, creación de proyectos, diseño de movimiento atractivo, planos 3D (`fframes::three_d`, escenas estilo three.js), sonido (música, voz, efectos de sonido, volumen), visualización en una ventana de vista previa en tiempo real y verificación del resultado sin necesidad de verlo: fotogramas y hojas de contacto como PNG, detección automática de problemas, valores de volumen, renders rápidos (borrador) y por rangos.

¿Qué es fframes?

Esta habilidad habilita la creación de videos completamente programáticos utilizando la biblioteca Rust fframes. Convierte tus diseños en animaciones renderizadas con GPU (Skia) y codificadas con ffmpeg, permitiendo crear desde clips promocionales hasta videos musicales con escenas 3D y audio sincronizado. La habilidad prioriza el diseño intencional sobre plantillas genéricas, evitando 'slop' (contenido genérico y sin personalidad) y fomentando un flujo de trabajo que comienza con un plan detallado, selección de sonido y diseño de movimiento único para cada escena. Soporta los agentes de IA Claude Code, Cursor y Codex, y proporciona un ciclo de desarrollo completo: instalación, creación de proyectos con plantillas, un bucle de revisión que incluye vista previa en tiempo real, inspección de problemas, hojas de contacto (contact sheets) y análisis de audio, todo desde la línea de comandos. La documentación detallada incluye referencias para diseño, API, audio y escenas 3D, y establece reglas estrictas contra el slop: sin textos genéricos, sin animaciones repetitivas, sin elementos decorativos sin propósito. Cada elemento debe tener una razón vinculada al tema del video.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Creación de videos con fframes

fframes es una biblioteca Rust que renderiza videos a partir de código. Un video es una estructura Rust con un método render_frame(frame) -> Svgr: para cada fotograma devuelve un árbol SVG, construido con la macro svgr! (marcado SVG con {expresiones rust}). Las escenas dividen la línea de tiempo, timeline! y los muelles animan valores, un mapa de audio coloca el sonido, y ffmpeg codifica el resultado.

Cada proyecto tiene una línea de comandos (de fframes::cli). Úsala para todo: renderizar un video, abrir la ventana de vista previa en tiempo real, y ver fotogramas, hojas de contacto y valores de volumen como archivos que puedes leer. Lee references/design.md antes de diseñar, references/api.md mientras escribes código, references/audio.md para sonido y references/3d.md para planos 3D (fframes::three_d).

Al hacer coincidir un video proporcionado, primero sigue la guía de análisis de referencias en references/design.md. Sus cortes, ritmo y movimiento tienen prioridad sobre los valores predeterminados de diseño a continuación; las ediciones rápidas y los fotogramas negros intencionales pueden ser parte del resultado solicitado.

Dos reglas antes que nada

Planifica antes de escribir código

No abras la plantilla y empieces a animar. Primero:

  1. Define el briefing: quién lo ve y dónde (la plataforma decide formato y duración), lo único que el espectador debe recordar, el tono y los recursos existentes (logotipo, fotos del producto, metraje, música, voz en off). Pregunta al usuario lo que falta y es importante. Nunca inventes hechos, números o citas del producto.
  2. Cuando el video se corta con música o voz, elige el sonido primero. Su tempo, ritmos y frases marcan la sincronización de todo lo demás.
  3. Planifica primero el diseño de movimiento, sincronízalo con los picos de sonido para crear un flujo único: de dónde aparecerán los elementos, cómo se transformarán. Intenta crear un diseño de movimiento único para cada escena para que se vea único y pulido. El video no debería parecer una presentación de diapositivas.
  4. Intenta razonar sobre la sensación de la persona que ve el video final y ajusta cada pieza de diseño en consecuencia: el flujo, tempo, ritmos, movimiento y colores.

Sin slop

Slop es un video hecho de opciones predeterminadas: podría tratarse de cualquier producto con solo cambiar el texto, y los espectadores lo reconocen en un segundo. A menos que el usuario lo solicite, no entregues:

  • Restos de plantilla: el diseño inicial, colores, fuente o decoraciones, texto de marcador de posición, logotipos falsos, números inventados.
  • Espam de ritmo: todo el fotograma acercándose, sacudiéndose o parpadeando en cada ritmo. Sincroniza cosas pequeñas con el ritmo (un trazo, una palabra, una chispa) y cambia todo el fotograma solo en unos pocos cortes.
  • Un solo movimiento para todo: cada elemento desvaneciéndose hacia arriba 40 px con la misma suavización y duración.
  • Escenas estáticas: una cosa aparece, se mantiene y se desvanece mientras nada más se mueve.
  • Copia genérica: "Presentamos", "Desata", "Sin fisuras", "Siguiente nivel", eslóganes de tres palabras ("Rápido. Sencillo. Potente."). Escribe el texto en pantalla como lo diría una persona.
  • Texto en general: la cantidad de texto debe ser limitada y precisa.

En su lugar, dale a cada elemento una razón vinculada al tema y elimina lo que no tenga ninguna. Dedica esfuerzo al detalle y al movimiento en lugar de las palabras: movimiento secundario, entradas escalonadas, trazos dibujados, objetos que reaccionan entre sí, elementos que se trasladan entre cortes. Antes de mostrar algo al usuario, mira una tira y pregúntate si el video seguiría funcionando para un producto diferente con solo cambiar el texto. Si es así, cambia la idea, no los colores.

1. Instalación

Rust desde https://rustup.rs, luego las bibliotecas del sistema con las que se construye ffmpeg:

# 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 enlaza una compilación compartida precompilada de FFmpeg 9 (establece FFMPEG_DIR en la compilación ffmpeg-n9.0-latest-win64-gpl-shared descomprimida de BtbN/FFmpeg-Builds, agrega su bin a PATH, instala LLVM con winget install LLVM.LLVM y establece LIBCLANG_PATH). Los detalles están en el README de fframes.

2. Crear un proyecto

curl -fsSL https://raw.githubusercontent.com/dmtrKovalenko/fframes/main/scripts/new-video.sh | bash -s -- my-video --yes
# o instala el generador una vez y úsalo directamente:
cargo install --locked cargo-fframes
cargo fframes new my-video --format landscape --fps 30 --yes

Opciones: --template single-scene|multi-scene, --format landscape|portrait|square|uhd, --fps, --title, --backend, --dir. El proyecto depende de la versión de fframes que coincida con el cargo-fframes instalado; --git usa la rama main del repositorio. Siempre pasa --yes para que no espere entrada.

Plantillas:

  • single-scene (predeterminada): una escena. Se adapta a todos los formatos; empieza aquí para clips de una sola toma, tarjetas de título y video vertical.
  • multi-scene: dos escenas. Empieza aquí para cualquier cosa con varias escenas; solo acepta landscape y uhd.

El contenido de la plantilla es código de marcador de posición que muestra la API. Reemplaza su diseño, colores, fuentes y decoraciones con un diseño hecho para el video que el usuario solicitó.

Usa el backend de GPU Skia (el predeterminado). cargo fframes new elige Skia en Metal (macOS) o Vulkan (Linux, Windows). Renderiza aproximadamente 10 veces más rápido que el backend de CPU y te da la ventana de preview en tiempo real. En macOS y Linux, la primera compilación descarga Skia y ffmpeg precompilados y solo compila las dependencias de Rust (aproximadamente un minuto; otros destinos, o metal y vulkan juntos, compilan Skia desde la fuente durante ~20 minutos). Inícialo de inmediato y escribe el video mientras se ejecuta:

cd my-video && cargo build --release        # ejecuta en segundo plano, la primera compilación es la lenta

--backend cpu no necesita Skia pero no tiene ventana de vista previa; elígelo solo cuando no haya GPU.

El proyecto se renderiza tal como se genera:

my-video/
  src/lib.rs        # el video (desde la plantilla)
  src/main.rs       # la línea de comandos
  media/            # fuentes, imágenes y audio compilados en el binario (una fuente inicial)
  README.md         # los comandos a continuación

Cada comando a continuación es cargo run --release -- <comando>. Define una función corta de shell (una variable como R="cargo run --release --" no se divide en palabras en zsh, el shell de macOS):

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

3. El bucle

No escribas pruebas en absoluto al usar esta habilidad. No crees pruebas unitarias, de integración, de instantáneas o de regresión visual, módulos de prueba o infraestructura de pruebas. Valida el video con inspect, fotogramas renderizados, hojas de contacto, comprobaciones de audio y la vista previa nativa.

Previsualiza, no renderices. Si el video usa el backend de renderizado GPU y hay una GPU disponible en esta máquina, ejecuta la vista previa nativa (o muéstrale al usuario el comando) en lugar de renderizar el video después de cada cambio. Cuando los cambios estén listos para revisar:

  1. Muestra un comando completo en un bloque de código de shell copiable, usando la ruta real del proyecto y el nombre del paquete; no requieras que el usuario haya definido el ayudante $R. Por ejemplo: cd /ruta/absoluta/a/fframes && cargo run --release -p my-video -- preview 0s.
  2. Ofrece explícitamente ejecutar esa vista previa para el usuario. Si ya han autorizado abrir o actualizar la vista previa, muestra el comando y continúa dentro de esa autorización.

Después de un cambio solicitado, establece la hora de inicio del comando en un segundo específico en o justo antes de la sección modificada, con suficiente anticipación para ver su entrada o transición. Por ejemplo, preview 8.5s permite al usuario revisar un cambio alrededor de 9 segundos sin reproducir el principio. Indica qué sección verán. Renderiza el video completo cuando el usuario solicite la exportación final; no requieras otra confirmación si esa solicitud ya es explícita.

Después de cada cambio:

  1. $R timeline lista las escenas con sus rangos de fotogramas y segundos, y cada pista de audio. Verifica la estructura y el ritmo aquí antes de mirar los píxeles.
  2. $R inspect verifica un fotograma cada 0.25 s más el primer y último fotograma de cada escena. Reporta imágenes, fuentes o glifos faltantes, texto cortado por el borde del lienzo, SVG no válido (rectángulos de tamaño cero, radios incorrectos), transformaciones rotas y pánicos, cada uno con su hora y escena. Sale con código 2 en caso de error. Arregla todo lo que reporta. Una advertencia que solo aparece en los primeros fotogramas de una escena suele ser una entrada; verifícala con una tira.
  3. $R strip <escena o rango> -n 12 escribe una hoja de contacto (strip.png): fotogramas espaciados uniformemente en una imagen etiquetada. Ábrela con tu herramienta de imágenes. Es la forma más rápida de juzgar el diseño, el ritmo y el movimiento. $R strip 2s,5s,9s coloca las horas elegidas una al lado de la otra.
  4. $R frame Intro@end,Outro@50% escribe PNG de tamaño completo en frames/ para comprobaciones de detalle (tipografía, alineación, contraste) e imprime problemas encontrados en esos fotogramas. Juzga los detalles pequeños (contacto entre elementos, bordes, formas pequeñas) en un recorte ampliado nítido, nunca en un fotograma reducido: $R frame 3s --crop 1100,520,240,120 (píxeles de video, ampliados a aproximadamente 960 px de ancho). --ids delinea y nombra cada elemento que tiene un id, para encontrar qué forma es cuál.
  5. $R onion "[email protected]@1s" -n 6 combina fotogramas en una imagen (onion.png) para mostrar la trayectoria y el espaciado de un movimiento: suavización, sobreimpulso, escalonamiento.
  6. $R preview Intro abre una ventana en tiempo real con sonido para que el usuario vea (espacio reproducir/pausa, h/l avanzar un segundo, j/k avanzar un fotograma, q salir). Se bloquea hasta que se cierra, así que inícialo en segundo plano cuando lo ejecutes para el usuario. Muestra el comando y ofrece lanzarlo como se describió anteriormente; después de las ediciones, usa un segundo específico cerca del cambio.

Cuando se necesite una muestra codificada, $R render Intro --draft codifica una escena a la mitad de resolución. $R render escribe el video completo para una exportación final solicitada.

Antes de mostrar un video terminado, ejecuta $R inspect --pops: renderiza cada fotograma pequeño y advierte sobre pops, partes de la imagen que cambian en un fotograma entre fotogramas fijos, como un elemento que aparece, desaparece o salta delante de otro en lugar de moverse allí. Cada advertencia da el comando frame ... --crop ... para mirarlo; las repeticiones de la misma región (contadores, luces parpadeantes) se agrupan en una advertencia.

Reglas:

  • Mira los PNG antes de decir que algo se ve bien.
  • Prefiere strip a muchas llamadas frame; agrega --scale 0.5 cuando solo necesites composición.
  • Agrega --json al analizar la salida: el resultado va a stdout, el progreso a stderr.
  • Mantén --release: las compilaciones debug renderizan muchas veces más lento.

Direccionamiento de tiempo

120 (fotograma), 3.2s, 500ms, 1:05.5, 50%, start, end; escenas por nombre de estructura, Intro (también coincide con IntroScene, no distingue mayúsculas), #3 (índice de escena), Intro[1] (segunda escena de ese tipo); dentro de una escena [email protected], Intro@12, Intro@50%, Intro@end. Rangos: a..b (extremo exclusivo), a.., ..b, all, o un nombre de escena para toda la escena. Separa varias horas con comas.

Todos los comandos

comandoúsalo para
timelinever escenas, duraciones, pistas de audio y su configuración de mezcla
inspect [RANGO] [--every 0.1s | --all-frames] [--fail-on warning] [--pops]encontrar problemas sin renderizar píxeles; --pops también encuentra elementos que aparecen o desaparecen
strip [RANGO | HORAS] -n N [--columns 4] [--width 480] [--crop x,y,w,h]revisar flujo y movimiento en una imagen
frame HORAS [-o dir] [--svg] [--crop x,y,w,h] [--zoom N] [--ids]PNG de tamaño completo (y el SVG diseñado) de fotogramas elegidos, recortes nítidos, elementos etiquetados
onion RANGO -n Nver la trayectoria y suavización de un movimiento
svg HORAleer el SVG final de un fotograma como texto (posiciones, texto, colores)
preview [HORA] [--paused] [--mute]ventana en tiempo real con sonido, para el usuario
render [RANGO] [-o out.mp4] [--draft]codificar el video o una parte (audio cortado para coincidir)
audio analyze [RANGO] [--waveform w.png]volumen (LUFS), pico real, recorte, silencio, por escena
audio at HORASqué sonidos suenan en un momento, dónde en su archivo y qué tan fuerte
audio render [RANGO] -o a.wavla mezcla como archivo WAV

Editor del navegador

fframes también tiene un editor web con una línea de tiempo y desplazamiento, útil cuando una persona quiere ajustar un video de forma interactiva. Ejecuta el video compilado a WebAssembly y necesita Node.js además de wasm-pack; la configuración es la carpeta editor/ del ejemplo hello-world en el repositorio de fframes (https://github.com/dmtrKovalenko/fframes/tree/main/examples/hello-world). Menciónalo cuando el usuario pida un editor GUI. Para ver, usa preview, y para tu propia revisión, usa la CLI.

4. Escribiendo el video

impl Video for MyVideo<'_> {
    const FPS: usize = 30; const WIDTH: usize = 1920; const HEIGHT: usize = 1080;
    fn duration(&self) -> Duration<'_> { Duration::Auto }            // suma de las escenas
    fn audio(&self) -> AudioMap<'_> { AudioMap::none() }              // ver 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>)
    }
}
  • Una escena por idea, de 2 a 6 s cada una. Dentro de una escena, frame.seconds() cuenta desde el inicio de la escena.
  • Predeterminado a frame.animate(fframes::timeline!(...)) directamente en atributos svgr! para movimiento con valores fijos. svgr! eleva estas animaciones a estáticas en caché. Define suavizaciones en línea en la línea de tiempo, incluyendo Easing::Spring { mass: 1.0, stiffness: 180.0, damping: 20.0 }; las constantes de suavización con nombre son opcionales. Deja el tiempo de finalización fuera de un muelle para que

…

[truncado para traducción]

Skills relacionados