Communitygithub.com

video-skill

Crear, editar, verificar y comprender videos desde un terminal, para un agente que no puede verlos. Utilízalo cuando alguien quiera un video creado, editado, verificado o renderizado – un video de lanzamiento o demo, explicativo, cartel promocional, gráficos animados, pase de diapositivas de fotos, montaje de un viaje o evento, GIF, clip para redes sociales, o un corte de metraje y sonido existente – o quiera saber qué hay en un video («qué sucede en este clip», «encuentra el momento en que», «transcribe esto»), o tenga metraje de teléfono que se ve desteñido, girado o desincronizado. También para OpenFilm, su editor Studio, film.html o páginas con window.film, y para normalización de sonoridad, compatibilidad H.264, conversión HDR a SDR, y exportación GIF y WebP.

¿Qué es video-skill?

Este skill permite a un agente de IA que no puede ver video trabajar con material audiovisual de principio a fin: desde la creación de películas completas en formato OpenFilm (HTML plano + editor Studio local) hasta la ingestión, análisis y entrega de metraje. Convierte cada paso en algo que el agente sí puede leer: fotogramas, hojas de contacto, transcripciones con marcas de tiempo, y valores numéricos como la sonoridad (LUFS). El flujo de trabajo recomendado es: escribe → renderiza fotogramas → lee la hoja de contacto → corrige. Para metraje recibido (como grabaciones de teléfono), primero se debe sondear con `footage.py probe` para detectar problemas comunes (HDR, rotación, frecuencia de cuadros variable, dimensiones impares), luego generar un proxy corregido con `footage.py proxy`. El análisis se realiza con muestreo de fotogramas (`footage.py frames`) y transcripción automática local con `parakeet-mlx`. La entrega incluye verificación automática de compatibilidad (`footage.py check`) y optimización para web (`footage.py share`, `footage.py gif`). El skill está optimizado para sistemas macOS con `ffmpeg` instalado (idealmente via Homebrew), `Python 3`, `uv`, y el entorno `mise`. Funciona con Claude Code, Cursor y otros agentes que ejecutan comandos Bash.

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

Preguntar en tu IA favorita

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

Documentación

¿Qué hace video-skill?

Los scripts viven en scripts/ junto a este archivo; escríbelo como $S abajo, pero escribe la ruta absoluta completa en cada comando, porque las variables de shell no se transfieren entre llamadas Bash.

No puedes ver videos, así que cada paso lo convierte en algo que sí puedes leer: fotogramas que observas y números que verificas. Hacer una película es escribir → renderizar fotogramas → leer la hoja de contacto → corregir. Entender metraje es sondear → proxy → hojas con marcas de tiempo + transcripción → juzgar. Entregar es un script que verifica códec, frecuencia de cuadros, faststart y sonoridad, para que «se reproduce en todas partes» sea un hecho.

Primera vez en un Mac

Ejecuta sh $S/setup.sh tú mismo. Verifica mise y ffmpeg (instalando ffmpeg con Homebrew cuando puede), instala la versión fijada de OpenFilm en el primer uso y ejecuta openfilm doctor. Arregla cada TODO que imprima, o explícalo claramente a la persona. Es seguro volver a ejecutarlo.

Haciendo una película: OpenFilm

OpenFilm (MIT) es el formato de autoría: una película es una carpeta con un film.html que corta páginas HTML, metraje, imágenes y sonido, y cada página dibuja cualquier momento t que se le pida. Studio es su editor local en navegador.

  1. Imprime el manual y léelo completo (es corto y cambia entre versiones): $S/openfilm. Síguelo, con este archivo teniendo prioridad donde difieran.
  2. $S/openfilm es la única forma de ejecutar OpenFilm aquí: fija la versión, lo instala a través de mise en el primer uso, y evita que Studio abra una ventana del navegador. No uses npx openfilm (salta la fijación) ni npx skills add openfilm/openfilm (un skill externo que compite con este).
  3. FILM es siempre una ruta absoluta, $HOME/Movies/OpenFilm/Projects/<film-name>. Un nombre relativo cae en la carpeta actual, como el repositorio git de alguien. Las películas nunca van en un repositorio.
PasoComando
Crear o abrir$S/openfilm open FILM
Verificar toda la película$S/openfilm -C FILM look
Verificar un momento, un tramo, un archivo… look 4.5, look 3-6, look assets/bed.wav
Verificar una entrada rápida… look 0-2 --count 24
Renderizar el MP4$S/openfilm -C FILM render
Qué servicios multimedia están conectados$S/openfilm get
Diagnosticar la instalación$S/openfilm doctor

look y render se ejecutan sin Studio abierto e imprimen rutas relativas a FILM. La dirección de Studio contiene una clave de acceso: entrégala solo a la persona con la que estás trabajando (es 127.0.0.1, Chrome o Edge, no desde un teléfono).

Lee cada hoja de look antes de mostrar nada, y corrige lo que veas. Sus comprobaciones (el mismo t dibuja la misma imagen, fuentes cargadas, texto recortado, sonoridad) no dicen nada sobre el gusto o el diseño. Un ! sobre texto cortado durante una entrada está bien; cortado en reposo es un error. Luego mira algunos momentos a tamaño completo (look 12.5): un mosaico de 300 px oculta cosas pequeñas, incluídas personas.

Cómo se construye una película, aprendido al hacer una:

  • Una página por toma; lo que las páginas comparten (un movimiento Ken Burns, fuentes, colores) va en un módulo que importan. Cada valor es una función solo de t: sin temporizadores, sin bucle de animación, sin estado.
  • Las páginas se desvanecen a sí mismas (opacidad desde t); un fundido a negro entre tomas en una pista es la transición más simple. Una encadenado necesita la toma entrante en una pista encima de la saliente.
  • El texto sobre fotos necesita una sombra detrás (un degradado inferior), o desaparece en escenas recargadas.
  • Las fuentes van en FILM/fonts/ con @font-face, esperadas a través de window.film.ready (document.fonts.ready). Para fotos, ready: img.decode().
  • Recorta con #t=inicio,fin, nunca cortando archivos nuevos; un sonido más largo que la película extiende la película.

Sonido

$S/openfilm get muestra lo que está conectado; la voz generada, la música y los efectos necesitan las propias claves del proveedor de la persona (Studio: logo de OpenFilm → Configuración → Proveedores). Sin ellas, haz sonido con ffmpeg, guárdalo en FILM/assets/, anota el comando en FILM/sound-notes.txt para que pueda rehacerse, y di qué servicio lo haría mejor. No puedes oírlo, así que juzga por números:

  • -16 LUFS integrado para una mezcla final (podcasts, la mayoría de video web); las plataformas de streaming normalizan cerca de -14. Mantén el pico verdadero en o bajo -1 dBTP. Una cama bajo una voz está ~-22.
  • Mide: ffmpeg -i X -af ebur128=peak=true -f null -. Normaliza una cama generada con loudnorm=I=-16:TP=-1.5:LRA=7; para una masterización final, ejecuta loudnorm dos veces (mide, luego retroalimenta los valores measured_*) para que la ganancia sea lineal.
  • look imprime la sonoridad de la mezcla, y footage.py check falla en un renderizado que no alcanza el objetivo.

Metraje recibido: ingesta

El video de teléfono rara vez es lo que parece. Ejecuta esto sobre cualquier cosa antes de mirarlo o cortarlo:

uv run --no-project --with pillow python -I $S/footage.py probe CLIP.mov ...
uv run --no-project --with pillow python -I $S/footage.py proxy CLIP.mov <scratch>/clip.mp4

probe advierte sobre cada uno de estos, y proxy los corrige todos en una sola pasada (SDR BT.709, rotación incrustada, 30 fps constante, tamaño par, H.264 yuv420p, AAC 48 kHz, faststart):

  • HDR (los iPhones graban HLG por defecto: color_transfer=arib-std-b67, BT.2020). Leído como SDR, se ve desteñido y cambia los colores: el bermellón se vuelve naranja. proxy mapea el tono con el avconvert integrado de macOS, o si no con zscale de ffmpeg (ausente en muchas compilaciones de Homebrew), o si no advierte.
  • Rotación: los teléfonos almacenan video vertical de lado con un indicador de rotación; algunas herramientas lo ignoran.
  • Frecuencia de cuadros variable: nominal 24, promedio 23.997. Los tiempos de los fotogramas se desvían y el audio se desincroniza después de cortes. probe marca cualquier diferencia superior a 0.001 fps.
  • Dimensiones impares: H.264 yuv420p necesita ancho y alto pares.

Mira y corta desde el proxy; conserva el original para cualquier cosa que deba permanecer en calidad completa.

Entendiendo metraje

uv run --no-project --with pillow python -I $S/footage.py frames <scratch>/clip.mp4 <scratch>/sheets --every 4

Esto toma un fotograma en cada cambio de escena (--scene 0.3) y al menos uno cada --every segundos, con un máximo de --max 60, en hojas de 5×6 mosaicos etiquetados como 0007 · 1:23.4, con manifest.json mapeando cada id a su tiempo. Lee las hojas y responde con ids y tiempos. Práctica, no doctrina:

  • Películas creadas: muestreo uniforme a la duración del plano. Metraje encontrado: cambios de escena más un mínimo de un fotograma cada 2-5 s. Acción rápida: un tramo corto con --every 0.5.
  • Mantén una hoja por debajo de ~2500 px en su lado largo y lee unas pocas a la vez; para metraje largo, distribuye a subagentes sobre hojas, cada uno escribiendo un veredicto JSONL por id de mosaico, luego python3 -I $S/check_verdicts.py manifest.json out/*.jsonl (ids faltantes, duplicados o inventados fallan; una hoja donde cada mosaico recibió la misma respuesta probablemente fue hojeada).
  • La mayor parte de un video con diálogo está en su audio. Transcribe en el dispositivo con tiempos de palabras: uvx parakeet-mlx AUDIO.wav --output-format json --output-dir <scratch> (extrae audio primero: ffmpeg -i clip.mp4 -ar 16000 -ac 1 audio.wav). Une palabras a fotogramas por tiempo. Los nombres propios salen mal («torii» → «Torrey»), así que verifica los nombres contra lo que ves antes de citarlo.

Entregando

uv run --no-project --with pillow python -I $S/footage.py check FILM/<nombre>.mp4 --duration 30
uv run --no-project --with pillow python -I $S/footage.py share FILM/<nombre>.mp4 <scratch>/<nombre>-share.mp4
uv run --no-project --with pillow python -I $S/footage.py gif FILM/<nombre>.mp4 <scratch>/loop.webp --start 2.5 --duration 6 --width 480
  • check debe pasar antes de que entregues un archivo: H.264, yuv420p, tamaño par, frecuencia de cuadros constante, moov antes de mdat (faststart: se reproduce mientras se descarga), duración, sonoridad ±1.5 LU, pico verdadero.
  • Renderiza cuando la persona pida el archivo o no pueda estar en este Mac; ejecuta look sobre el MP4 mismo como última verificación. share hace una copia pequeña (1280 de ancho, CRF 28: un renderizado de 30 s a 1080p pasó de 34 MB a 3.8 MB) para una página web o chat; el MP4 original de la película queda intacto.
  • Bucles: WebP animado sobre GIF. Un bucle de fotos de 5.6 s con un zoom lento pesaba 6.7 MB como GIF y 1.6 MB como WebP: GIF no puede reutilizar píxeles cuando cada píxel se mueve. GIF solo cuando el destino no puede mostrar WebP; entonces footage.py gif X.gif usa una paleta generada (palettegen/paletteuse).
  • Elimina lo que no debe viajar: el video de iPhone lleva GPS, el modelo del teléfono y la hora en sus metadatos. proxy y share eliminan todo (-map_metadata -1). El archivo original, o una copia hecha por AirDrop o una exportación de Fotos, lo conserva. Verifica con exiftool -GPSCoordinates ARCHIVO.

Fotos en una película

Usa el skill photo-skill (github.com/kylefritz/photo-skill; si no está instalado, ofrece clonarlo en ~/.claude/skills/photo-skill) para encontrarlas (busca en la biblioteca por descripción, luego juzga hojas de contacto) y descargar originales en resolución completa: las vistas previas son demasiado pequeñas para 1080p. Copia lo que la película usa en FILM/assets/, reguardado sin EXIF. Antes de que una película con las fotos de alguien vaya a algún lado, mira cada toma a tamaño completo: la detección de rostros falla en multitudes, y un mosaico de 300 px oculta personas que un fotograma de 1080p muestra.

Otras herramientas

OpenFilm se adapta mejor a un agente porque una película es HTML plano y look devuelve exactamente lo que necesitas ver. Alternativas, a finales de 2026:

HerramientaAutoríaNotas
HyperFrames (HeyGen, Apache-2.0)HTML/CSS + GSAP, renderizado por headless Chromeel análogo más cercano; compuerta check --json lint/diseño/contraste, instantáneas, un plugin de Claude Code
RemotionComponentes Reactmaduro, skills oficiales para agentes; licencia de código disponible, empresas por encima de un tamaño pequeño necesitan una
Manim (MIT)Escenas Pythonexplicaciones matemáticas y de diagramas
MoviePy (MIT) / ffmpeg puroPython / gráficos de filtrocortes y superposiciones simples; ffmpeg se mantiene mejor como la capa de E/S

Actualizando OpenFilm

El repositorio upstream publica a menudo. Lee las notas de lanzamiento y ejecuta npm view openfilm scripts primero (una entrada preinstall o postinstall merece un vistazo), luego cambia OPENFILM_VERSION en scripts/openfilm y vuelve a ejecutar setup.sh. Después ls ~/Library/Caches/ms-playwright: la primera ejecución de OpenFilm elimina los navegadores Playwright que no tienen un marcador de enlace; setup.sh informa sobre los que eliminó, y npx playwright install chromium en el proyecto que lo necesite lo restablece.

Errores comunes

ErrorCorrección
npx openfilm …$S/openfilm …: npx salta la fijación
look o render en la carpeta incorrecta$S/openfilm -C FILM …
Confiar en las comprobaciones de look sin abrir su PNGLee la hoja; una comprobación exitosa no dice nada sobre el diseño
Cortar o mirar metraje de iPhone directamenteprobe, luego proxy: HDR, rotación y VFR afectan
Enviar el MP4 maestro a un chatsharelo, luego check la copia
Un GIF para un README o una páginaWebP, ~4× más pequeño
Studio desactualizado después de una actualizaciónDetén los procesos viejos de studio/server/main.mjs (pgrep -fl openfilm); un Studio son dos procesos

Skills relacionados