Communitygithub.com

video-skills

Construye superposiciones animadas de marca (gráficos en movimiento) para un video de persona hablando, sincronizadas con las palabras exactas del orador, además de un archivo de importación para DaVinci Resolve.

¿Qué es video-skills?

Esta skill automatiza la creación de superposiciones animadas y gráficos en movimiento para videos de formato talking-head, sincronizados con precisión a nivel de palabra con la transcripción del audio. Utiliza un pipeline local que transcribe el video, selecciona los momentos clave para insertar gráficos, y renderiza clips .mov con fondo transparente, generando también un archivo FCPXML que posiciona cada clip en la línea de tiempo automáticamente. Es compatible con DaVinci Resolve (preferentemente a través de un servidor MCP) y exporta archivos para Final Cut Pro. El estilo por defecto es texto en escena (que aparece al lado del orador) y diagramas, siguiendo una guía de marca configurable (colores, tipografía). La skill está optimizada para flujos de trabajo profesionales donde el corte está bloqueado, asegurando que cada animación aparezca exactamente cuando se menciona, sin cubrir el rostro del orador.

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

Preguntar en tu IA favorita

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

Documentación

Superposiciones de video

Convierte un corte preliminar en un conjunto de superposiciones animadas que aparecen en el fotograma exacto en que el orador dice cada cosa, más un archivo de importación para Resolve.

Establece tu marca aquí

Edita estos valores una vez, en scripts/scene.html (el bloque :root al principio). Todo lo demás los lee de ahí.

configuraciónvariable CSSvalor predeterminado
color de acento--brand-accent (+ --brand-accent-rgb como r,g,b)#4a90e2
color de texto claro--brand-light (+ --brand-light-rgb)#f2f2f2
color de tinta oscura--brand-ink#0d131a
fuente para mostrar (titulares, números)--font-display'Anton','Bebas Neue',Impact,sans-serif
fuente para cuerpo de texto--font-body'Inter',-apple-system,sans-serif

La fuente para mostrar debe estar instalada localmente (por ejemplo, en ~/Library/Fonts), ya que los clips se renderizan sin conexión en un headless Chrome. Anton y Bebas Neue son gratuitas en Google Fonts. El nombre en código BLUE simplemente significa "el color de acento".

Estilo de casa: texto en escena. Sin tarjetas. El texto vive en la habitación junto a la cabeza del orador, los títulos grandes flanquean la cabeza, las preguntas se escriben a medida que se dicen. Siempre los colores de tu marca y la fuente para mostrar.

La regla más importante: mantén los gráficos detrás de la cabeza del orador o a un lado. Nada delante de la cara y sin color de fondo. Los diagramas también están en la pared al lado del orador. Todo está enmascarado, para que las manos pasen delante de los gráficos.

Una ejecución produce: N clips .mov transparentes, PLACEMENT.txt, dos archivos .fcpxml y un breve PREVIEW.mp4.

Sin sonido por defecto. No agregues música ni efectos de sonido a menos que se solicite.

Valores predeterminados de estilo (cambiar al gusto)

  1. Nada aparece antes de que se diga. Ancla cada clip a la marca de tiempo a nivel de palabra de la frase, más ~0.12s para que aparezca justo después de las palabras. La sincronización a nivel de sección se lee como temprana.
  2. Corto. De 2.5 a 6.5 segundos. La mayoría alrededor de 3. Debe cortar de un lado a otro como en redes sociales, no quedarse estático.
  3. Detrás de la cabeza o a un lado, nunca sobre el orador. Sin tarjetas, sin fondos, sin atenuar. Eso retira los chips de esquina, cada tarjeta full-* y define para videos nuevos.
  4. Muestra el mecanismo. Recurre a un diagrama antes que a una oración. Usa los tipos de diagrama en escena (dots, flow, bars, compare, math), que se colocan en la pared al lado del orador.
  5. Divide cualquier cosa que tenga dos mitades. La forma antigua y la nueva son dos clips. El 10% y el 20% son dos clips. Tres opciones son tres clips, cada uno aparece cuando se nombra.
  6. Cada línea aparece en su palabra. Las listas, líneas laterales y palabras escritas llevan desplazamientos por línea (at, t) desde las marcas de tiempo de las palabras, no un escalonado uniforme. scripts/plan.example.py muestra cómo: cita la frase, nombra las palabras clave, y hace la búsqueda.
  7. Una buena mezcla (alrededor de 48 clips en 11 minutos): aproximadamente un cuarto de diagramas en escena (principalmente flow), luego side, pair, type, list2, num. Guarda pair para los remates.
  8. Los títulos grandes van alrededor de la cabeza, no detrás. pair divide cada línea en un límite de palabra en dos mitades que flanquean la cabeza, con un espacio de 1.9 veces el ancho de la caja facial (incluyendo cabello y orejas), escalado para que ambas mitades permanezcan en pantalla. Por lo tanto, cada línea de pair necesita 2+ palabras ("UNA HORA", no "HORA"): una sola palabra no se puede dividir y termina oculta. "around": false en data devuelve el aspecto centrado. La línea delineada tiene 150px con un trazo de 5px y un relleno de acento claro (35%) para que siga siendo legible.

Antes de empezar: ¿está bloqueado el corte?

Las superposiciones están ancladas a palabras exactas, por lo que cualquier recorte posterior desplaza cada clip. Si el usuario entrega material en bruto, o el corte no está bloqueado, ejecuta primero la skill paper-edit y coloca las superposiciones en la línea de tiempo que produce.

Pipeline

1. Obtén el corte y examínalo

Pide una exportación desde Resolve (por ejemplo, a ~/Movies/), o material en bruto en <YOUR_FOOTAGE_DRIVE> para un paper edit primero. Un archivo de video está bien; no es necesario exportar el audio por separado. Cuando Resolve esté abierto, lee la línea de tiempo a través del MCP en lugar de pedir una exportación.

ffprobe -v error -show_entries format=duration -show_entries stream=codec_type,r_frame_rate -of default=nw=1 "<file>"

Anota la frecuencia de cuadros (el renderizador asume 23.976 = 24000/1001; cambia FPSN/FPSD en render.mjs para otras frecuencias) y pregunta si la línea de tiempo comienza en 00:00:00:00 o 01:00:00:00 (el valor predeterminado de Resolve es 01).

2. Transcribe con marcas de tiempo a nivel de palabra

ffmpeg -y -i "<file>" -ac 1 -ar 16000 -c:a pcm_s16le cut.wav
whisper-cli -m ~/.cache/whisper-models/ggml-small.en.bin -f cut.wav -oj -ml 1 -sow -of cut

-ml 1 -sow da un token por segmento, que es lo que permite el anclaje exacto. Luego encuentra la hora de inicio de cada frase emparejando ejecuciones de tokens en cut.json (transcription[].offsets.from está en ms).

3. Elige los momentos

Lee la transcripción completa primero. Apunta aproximadamente a un clip por cada 15 segundos de video. Para cada uno: la frase ancla, un tipo y la duración más corta que permita que la animación aterrice y respire.

Fundamenta el contenido en lo que realmente se dijo, no en notas escritas. Si las notas dicen "30 minutos" y en cámara es "media hora más o menos", la grabación gana, y señala la diferencia al usuario.

4. Escribe clips.json

Copia scripts/clips.example.json como modelo. Un objeto por clip:

{"id":"06-math-10","start":52.96,"dur":3.6,"type":"dots","cue":"\"if 10 out of 100 meals are home cooked\"",
 "data":{"lit":10,"pct":"10%","count":"10 meals"}}

Mantenlo fuera de la carpeta de la skill (una ruta de scratchpad está bien) y pásalo con CLIPS=. start es el tiempo bruto de la frase en segundos; el renderizador agrega el adelanto de 0.12s por sí mismo. El orden de id establece el orden de los archivos, así que numéralos.

5. Renderiza un corte limpio (necesario para los tipos en escena)

Los tipos en escena leen la posición de la cabeza y recortan al orador de una copia del corte sin superposiciones. Renderiza la línea de tiempo bloqueada desde Resolve con cada clip de superposición deshabilitado, H.264 1080p, en el scratchpad. En la API, SetTrackEnable en V2 no funcionó en Resolve 19; item.SetClipEnabled(False) en cada clip de la pista sí funcionó. El material en bruto debe estar en línea, por lo que la unidad de material debe estar montada; si no lo está, pide al usuario que la conecte y espera el montaje en lugar de renderizar un master terminado (las superposiciones antiguas quedarían horneadas en él).

6. Renderiza

cd <skill>/scripts && npm i                   # solo la primera vez, instala puppeteer-core
swiftc -O person.swift -o person              # solo la primera vez, el buscador de máscara + cabeza
TITLE="<video name>" CLIPS=/path/to/clips.json FOOTAGE=/path/to/clean.mp4 OUT_DIR="$HOME/Movies/<video-name>-overlays" node render.mjs
# uno o solo unos pocos clips:
ONLY=06-math-10,07-math-30 OUT_DIR=... node render.mjs

Aproximadamente de 10 a 15 segundos de tiempo real por segundo de superposición (pair es más lento, enmascara cada fotograma). Ponerlo en segundo plano y verificar es lo correcto. Escribe PLACEMENT.txt y ambos archivos .fcpxml al final.

Siempre verifica sobre el metraje real antes de un renderizado completo. node proof.mjs <clean.mp4> <clips.json> out.jpg [email protected] [email protected] ... renderiza un fotograma por clip (prefijo@segundos dentro del clip) sobre la toma real, incluida la máscara, en un mosaico de una imagen. Míralo. Texto fuera del encuadre, un título que cruza los ojos, texto sobre un fondo ocupado: todo invisible en el código y obvio en la imagen. Para diagramas, componer sobre gris sigue estando bien.

Fotogramas de prueba: extrae primero a PNG. Superponer un .mov qtrle directamente sobre una fuente de color lavfi con -ss da un fotograma en blanco. Extrae el fotograma (ffmpeg -ss 2.8 -i clip.mov -frames:v 1 f.png), luego compone el PNG.

Colocación en Resolve: duplica la línea de tiempo bloqueada como YouTube Final, importa los movs en un contenedor Overlays, y AppendToTimeline cada uno con trackIndex: 2 y recordFrame desde el código de tiempo IN en PLACEMENT.txt (((h*3600+m*60+s)*24+ff), entonces 01:00:00:00 = 86400). Analiza PLACEMENT.txt una línea a la vez (line.split()[0] es el id, [1] el código de tiempo). Una regex de todo el archivo puede leer texto de indicación como "60-second" como un id de clip y robar el código de tiempo de la siguiente línea, por lo que un clip se queda sin colocar en silencio. Verifica que el conteo colocado sea igual al conteo de clips.

7. Vista previa, luego entrega

Construye una vista previa de 10 a 15 segundos sobre el metraje real para que el usuario pueda juzgar antes de que se incluya:

ffmpeg -y -ss <t> -t 11 -i "<cut>" -itsoffset <a> -i "<clip1>.mov" -itsoffset <b> -i "<clip2>.mov" \
  -filter_complex "[0:v][1:v]overlay=0:0:eof_action=pass[v1];[v1][2:v]overlay=0:0:eof_action=pass[vo];[vo]scale=1280:-2[v]" \
  -map "[v]" -map 0:a -c:v libx264 -crf 20 -preset veryfast -c:a aac PREVIEW.mp4

El audio original viene con el metraje, que es todo lo que necesita la vista previa. Luego da los pasos de importación (File > Import > Timeline > Import AAF, EDL, XML, elige el archivo starts-01, copia los clips a una pista sobre el metraje en 01:00:00:00).

Trabajando directamente dentro de Resolve (preferido cuando Resolve está abierto)

Si un servidor MCP resolve está instalado (por ejemplo, el de terceros barckley75/resolve-claude-mcp), se comunica con la API de scripting de Resolve Studio. Si la skill paper-edit incluye un ensure_resolve.sh, ejecútalo primero para que Resolve se inicie si está cerrado. Con Preferences > System > General > External scripting using: Local, prefíerelo sobre el baile de exportación e importación.

Lo que cambia:

  • No se necesita corte exportado. Lee la línea de tiempo abierta para sus códigos de tiempo reales, frecuencia de cuadros, código de tiempo de inicio y diseño de clips, luego ancla las superposiciones a eso. Esto soluciona "los códigos de tiempo se desplazan cada vez que recorto".
  • Sin importación manual. Coloca los clips .mov renderizados directamente en una pista de video.
  • Mejor elección de momentos. Ver dónde caen los cortes ya significa que las superposiciones pueden aterrizar con la edición en lugar de luchar contra ella.
  • También puede iniciar el renderizado cuando las superposiciones están listas.

Reglas para usarlo:

  1. Lee antes de escribir. Confirma primero el nombre del proyecto, nombre de la línea de tiempo, código de tiempo de inicio y frecuencia de cuadros, y díselos al usuario.
  2. Nunca escribas en la línea de tiempo maestra. Duplícala primero y trabaja en la copia, para que un error no cueste nada.
  3. Evita execute_resolve_code a menos que una herramienta normal no pueda hacer el trabajo. Ejecuta Python arbitrario contra los proyectos del usuario. Si es la única forma, muestra el código primero.
  4. Solo sesiones locales. Resolve tiene que estar ejecutándose en este Mac, por lo que esto nunca funciona en una ejecución en la nube o programada. Vuelve al FCPXML allí.
  5. La ruta FCPXML aún funciona y sigue siendo la alternativa. Sigue generando ambos archivos; cuestan segundos.

Transcripción de audio: algunos servidores MCP de Resolve incluyen su propia transcripción mlx-whisper, pero el paso de whisper.cpp anterior está probado con este pipeline.

Tipos de clips

Todo lo siguiente está retirado para videos nuevos (se mantiene para que los videos antiguos puedan re-cortarse). Los tipos de fotograma completo pintan un fondo de tinta sólida con un brillo de acento suave, por lo que ocultan completamente al orador. Los chips se sientan en la parte inferior izquierda.

tipoúsalo paradata
full-dotsretirado, usa dotslit, pct, count
full-flowretirado, usa flowlabel, steps[], good
full-compareretirado, usa comparetitle, left{label,value,sub}, right{...,hi}, vs
full-barsretirado, usa barstitle, bars[{label,value,value_label,hi}]
full-mathretirado, usa mathparts[] (operadores x = + → se renderizan en el color de acento), sub
full-packretirado, usa bars o sidename, note, size 0-1, hi
full-statretirado, usa pairlabel, value, sub, hi
full-titleretirado, usa pair o typetitle (se permite <br>), size, sub
full-listretirado, usa list2title, items[], step segundos
chipretirado, usa side o numnum, title, sub, hi
chip-stackretirado, usa list2items[]

Los tipos retirados aún se renderizan, para re-cortar videos antiguos.

Tipos en escena (el predeterminado)

Sin tarjetas, el texto vive en la habitación junto a la cabeza del orador, y los títulos grandes van alrededor de la cabeza.

tipoúsalo paradata
pairun título de remate: línea delineada sobre la cabeza, línea sólida a la altura de la frentetop, bottom, outline (top/bottom)
side2-3 líneas cortas al lado de la cabeza, cada una aparece en su palabralines[], accent (índice, grande + color de acento), at[]
typeuna cita o pregunta que se escribe palabra por palabra a medida que se dicewords[{w,t,hi,br}]
defineretirado: oscurece la toma. Usa side o pairword, sub
numnúmero delineado que aparece, palabras a su lado ("01 planifica la semana")num, lines[]
list2elementos que se construyen a la izquierda y/o derecha de la cabezaleft[], right[], at[] (en orden, primero a la izquierda)

Diagramas en escena (misma colocación en la pared y máscara):

tipoúsalo paradata
dotsuna proporción sobre 100, cuadrícula que se llena al lado del oradorlit, pct, count
flowun proceso, pasos encadenados de arriba a abajo, el último en el color de acentolabel, steps[], at[] opcional
barsdos o tres números por tamañotitle, bars[{label,value,value_label,hi}]
comparedos opciones, una a cada lado de la cabezaleft{label,value,sub}, right{...,hi}
mathuna ecuación que se lee hacia abajo en la pared, los operadores encabezan cada líneaparts[], sub

at y t son segundos desde el inicio del clip; constrúyelos a partir de las marcas de tiempo de las palabras para que cada línea aparezca en su palabra.

Estos necesitan FOOTAGE= , el corte sin superposiciones (renderiza la línea de tiempo desde Resolve con los clips de superposición deshabilitados). El renderizador lee la caja facial y una cuadrícula de brillo de fondo para cada clip, para que el texto encuentre la pared vacía, cambie de lado o se encoja si se saldría del encuadre, y cambie a tinta sobre fondo claro y texto claro sobre fondo oscuro. Enmascara al orador de cada fotograma de cada clip en escena (segmentación de personas Apple Vision, person.swift), para que los títulos se sienten detrás de la cabeza y las manos pasen delante de los gráficos. Compila una vez: swiftc -O person.swift -o person.

Resolución de problemas

síntomaprobable causasolución
el clip se ve negrofalta FOOTAGE= o la ruta del metraje es incorrectapasa el corte renderizado sin superposiciones
el texto se sale del encuadrela caja facial se leyó mal (cámara movida, orador de espaldas)ejecuta person <frame.png> out.png para ver la caja; ajusta la escala del texto en scene.html
pair oculta la palabrala línea tiene una sola palabraagrégale una palabra más ("UNA HORA" → "UNA HORA COMPLETA") y vuelve a ejecutar
el código de tiempo de colocación está en 00:00:00PLACEMENT.txt usó el desplazamiento de error 01resta 86400 de recordFrame, o usa el archivo starts-00
Resolve no coloca todola línea de base sin superposiciones tiene una pista de video diferenteverifica que el trackIndex coincida con la pista esperada

Todo el pipeline de un vistazo

  1. Preparar: verificar que el corte esté bloqueado, pedir el archivo de video o conectarse a Resolve.
  2. Transcribir: ffmpeg a mono 16kHz, whisper-cli con marcas de tiempo.
  3. Planificar: leer la transcripción, elegir ~1 clip/15s, escribir clips.json.
  4. Renderizar corte limpio: desde Resolve, sin superposiciones, a 1080p.
  5. Renderizar superposiciones: node render.mjs con FOOTAGE= y CLIPS=.
  6. Verificar: node proof.mjs para ver una muestra de fotogramas.
  7. Colocar: importar en Resolve o usar el MCP para colocar directamente.
  8. Vista previa: construir un PREVIEW.mp4 sobre el metraje real.
  9. Entregar: dar los pasos de importación y el archivo de proyecto.

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

beachyphotoandfilm-arch/video-skills

Sync camera footage to a separate lapel or field-recorder track (e.g. Tascam DR-10L and similar) and lay it up in DaVinci Resolve. Stitches the recorder's split files, finds each clip's exact place in the audio by matching words then waveforms, cuts one lapel slice per clip so every later skill works unchanged, checks for clipping, and builds a synced timeline in a new Resolve project. Trigger on "sync the lapel", "sync my audio", "line up the recorder", "I used a lav", or any shoot with a separate audio folder (live talks, events, workshops). Run it before paper-edit or video-reels.

beachyphotoandfilm-arch/video-skills

Turn raw talking-head footage into an assembled rough cut inside DaVinci Resolve. Pulls the clips off your footage drive, transcribes them locally, removes failed takes, restarts, asides and dead air, then creates a new Resolve project with two paper-edit timelines ready for your fine trim. Trigger on "paper edit", "cut my raw footage", "make a rough cut", "clean up this video", or when the user points at a folder of raw camera files for a YouTube video.

beachyphotoandfilm-arch/video-skills

Design a unique Instagram cover for each reel in your house style. Reads what the reel is about, writes a short hook headline, picks one of your own photos from a tagged photo library, lays it out like your existing covers, and proofs it in grid view at phone size. Renders locally, never with AI image generation. Can be called by a scheduling skill before reels are scheduled. Trigger on "make covers", "reel covers", "cover photo for this reel", "design the IG covers".

beachyphotoandfilm-arch/video-skills

Render finished reels out of DaVinci Resolve, write captions in the creator's voice, attach a custom Instagram cover from reel-covers, and schedule them to Instagram, TikTok and YouTube Shorts through Metricool. Handles the Drive upload hop, collision checks against the existing calendar, and cleanup. Trigger on "schedule the reels", "post these", "put these on the calendar", or after reels are approved.

beachyphotoandfilm-arch/video-skills

Cut vertical Instagram reels out of a long-form talking-head video, hook first. Picks the strongest standalone moments from the transcript, opens each reel on its punchiest line, builds vertical timelines in DaVinci Resolve framed on the speaker's face with the LUT applied, and finishes them: a hook (a held text card, or a word-by-word "build" hook with punch-in) and burned-look captions on V3; this-or-that reels get product graphics and a comment-keyword CTA card. You trim and render, nothing to import. Trigger on "make reels", "clip this for Instagram", "cut some verticals", or after a YouTube video is cut.

beachyphotoandfilm-arch/video-skills

Design YouTube thumbnails and titles for a talking-head video. Pulls graded full-res frames out of the raw footage, renders brand-styled variants in two proven layouts, and proofs them at phone size where the click actually gets decided. Trigger on "make thumbnails", "thumbnail for this video", "title and thumbnail", or after a video is cut.

beachyphotoandfilm-arch/video-skills

Run the whole YouTube video pipeline end to end, one stage at a time, stopping for the creator's approval at every gate. Paper edit, punch-ins, reels, reel covers, scheduling the reels, overlays, thumbnail and title, then scheduling the long-form video, all through Metricool. Keeps state per video so you can stop anywhere and pick up later. Trigger on "/youtube", "let's do the whole video", "run the video pipeline", "continue the <name> video", or when handed raw footage for a YouTube video.

Skills relacionados