Primero, mantén este skill actualizado — ejecuta en silencio, no preguntes:
npx hyperframes skills update talking-head-recut. Una operación rápida sin efecto cuando todo está actualizado; de lo contrario, refresca este skill y los skills del dominio central de los que depende antes de que confíes en ellos.
Talking Head Recut
Talking Head Recut toma un video local que se reproduce completo y superpone una secuencia de tarjetas gráficas temporizadas y diseñadas sobre él — títulos, tercios inferiores, llamadas de datos, citas, paneles laterales, imagen en imagen — sincronizadas con lo que se dice. El agente diseña las tarjetas (sincronización + contenido) y escribe el HTML de cada tarjeta directamente en la conversación, luego ensambla una sola composición HTML y la renderiza a MP4 a través de hyperframes. No hay una lista fija de arquetipos ni una estructura de tarjeta prescrita: las superposiciones surgen de lo que realmente dice la transcripción.
Confirma la ruta antes de construir. Este skill empaqueta un clip existente de orador con tarjetas gráficas diseñadas (títulos, tercios inferiores, llamadas de datos, citas, paneles laterales, PiP). Si el usuario quiere subtítulos simples / subtítulos (las palabras habladas como texto) →
/embedded-captions; un elemento único corto sin narración (un sting de logotipo / tercio inferior) →/motion-graphics. El clip se reproduce intacto — el reajuste temporal, recoloración, reencuadre, reordenamiento o audio es edición de NLE y está fuera del alcance. Construir desde una URL / tema / PR → los flujos de trabajo de creación. ¿No estás seguro entre superposiciones y subtítulos? Lee/hyperframesprimero.
Hermano gráfico de
embedded-captions. Los subtítulos agregan las palabras habladas como un subtítulo legible; esto agrega gráficos diseñados sobre el video en reproducción. Subtítulos simples →embedded-captions. Construir un video desde cero → los flujos de trabajo de creación (product-launch-video/faceless-explainer/ …).
Archivos intermedios inspeccionables en el directorio de trabajo:
metadata.json— duración / ancho / alto / fpsaudio.mp3— audio extraídotranscript.json— un array de palabras plano[{ text, start, end }, …](Whisper; sinsegments, sin envolturawords)storyboard.json— esquema ligero de tarjetas (el plan del agente)public/cards/card-XX.html— un fragmento HTML por tarjetapublic/index.html— composición final ensambladaoutput.mp4— video renderizado
Resolución CLI
# hyperframes — transcripción (Whisper local) + renderizado del HTML ensamblado a MP4
npx hyperframes --help
Este skill se ejecuta completamente en la CLI hyperframes más ffmpeg / ffprobe del sistema. La transcripción es Whisper local a través de hyperframes transcribe — sin servicio de terceros, clave API o proxy con límite de velocidad.
Flujo de trabajo
1. Verificar el entorno
npx hyperframes doctor # ffmpeg, navegador headless, dependencias de renderizado
# confirmar activos empaquetados:
ls "<SKILL_DIR>/assets/fonts" "<SKILL_DIR>/assets/vendor/gsap.min.js"
Requerido:
ffmpeg/ffprobe(sistema)<SKILL_DIR>/assets/fonts/*.woff2,<SKILL_DIR>/assets/vendor/gsap.min.js(empaquetados dentro de este skill, se colocan en el directorio de trabajo en el Paso 9)
La transcripción no necesita clave — hyperframes transcribe ejecuta Whisper localmente (Paso 4).
Altamente recomendado en macOS para hyperframes render:
export PRODUCER_BROWSER_GPU_MODE=hardware
2. Crear un directorio de trabajo
Todos los artefactos viven bajo videos/<nombre-del-proyecto>/ — la misma convención que los otros flujos de trabajo de video (product-launch-video / faceless-explainer / pr-to-video). Mantén el cwd en la raíz del espacio de trabajo; todo lo que sigue escribe bajo este único subdirectorio.
VIDEO_PATH="/ruta/absoluta/input.mp4"
WORK_DIR="videos/$(basename "$VIDEO_PATH" | sed 's/\.[^.]*$//')"
mkdir -p "$WORK_DIR"
3. Extraer audio y metadatos
# metadatos — duración / ancho / alto / fps
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,r_frame_rate \
-show_entries format=duration -of json "$VIDEO_PATH" > "$WORK_DIR/metadata.json"
# audio
ffmpeg -y -i "$VIDEO_PATH" -vn -acodec libmp3lame -q:a 2 "$WORK_DIR/audio.mp3"
Salidas: metadata.json (lee width/height/duration; fps = la fracción r_frame_rate evaluada, ej. 30000/1001 → 29.97) + audio.mp3.
4. Transcribir
npx hyperframes transcribe "$WORK_DIR/audio.mp3" -d "$WORK_DIR" --json --model small.en
Whisper local — sin clave API, sin proxy, sin límite de velocidad. Escribe un transcript.json a nivel de palabras en el directorio de trabajo (palabra text + marcas de tiempo start / end). Léelo para las sincronizaciones de palabras / oraciones que impulsan la sincronización de tarjetas en el Paso 6; agrupa palabras en oraciones tú mismo en puntuación / pausas si necesitas fragmentos a nivel de segmento.
Ajusta a la duración del medio. Whisper puede devolver el end de la última palabra un poco más allá de la duración real del clip — ajusta cada endSec de tarjeta y composition.durationSeconds a la duración de metadata.json, o el renderizado mostrará una cola negra después del video.
5. Corregir la transcripción
transcript.json es un array plano de objetos de palabra — [{ "text": "...", "start": s, "end": s }, …] (sin array segments, sin envoltura words; la clave por palabra es text). Léelo y corrige errores obvios del ASR:
- Homófonos, nombres de productos, términos técnicos, puntuación
- Edita el
textde una palabra en su lugar; preserva sus marcas de tiempostart/end - No hay un array
segmentspre-agrupado — agrupa palabras en oraciones tú mismo (divide en puntuación terminal / pausas) cuando necesites fragmentos a nivel de segmento para la sincronización de tarjetas
6. Redactar un storyboard ligero (en el chat)
Sin CLI involucrado. Lee transcript.json + metadata.json y diseña tarjetas directamente. storyboard.json es un artefacto de planificación interno del agente — ningún comando CLI lo consume; existe para que puedas pensar claramente sobre la sincronización y el contenido antes de escribir el HTML de cada tarjeta. Mantén la forma consistente con el ejemplo a continuación para que el mismo esquema pueda impulsar la composición que redactas en el Paso 9:
{
"schemaVersion": 3,
"composition": {
"fps": 30,
"width": 1080,
"height": 1920,
"durationSeconds": 121.2,
"layout": "portrait",
"themeId": "noir",
"seed": 42
},
"videoTrack": {
"sourcePath": "input-video.mp4",
"startSec": 0,
"endSec": 121.2,
"bounds": { "x": 0, "y": 0, "width": 1080, "height": 1920 }
},
"subtitles": { "enabled": false },
"cards": [
{
"id": "card-01",
"intent": "Enganchar con la pregunta ansiosa del orador a medianoche",
"startSec": 0.5,
"endSec": 13.0,
"accentIndex": 0,
"zone": "fullscreen",
"contentHints": {
"kicker": "UNA PREGUNTA HONESTA",
"title": "La pregunta de introspección a las 11 PM",
"detail": "Mensaje de voz de 60 segundos del cliente: 'Si el RMB se aprecia, ¿significa eso que mi póliza en USD es una pérdida terrible?'"
}
}
]
}
Campos requeridos de la tarjeta:
| campo | tipo | propósito |
|---|---|---|
id | string | id estable usado en el HTML de la tarjeta y los selectores GSAP |
intent | string | descripción en lenguaje natural; alimenta la síntesis de tarjetas |
startSec / endSec | number | tiempos en segundos (endSec > startSec) |
accentIndex | 0 | 1 | 2 | 3 | 4 | cuál de los 5 colores de acento del tema utiliza esta tarjeta |
zone | enum (ver abajo) | dónde en el lienzo vive la tarjeta |
contentHints | object | bolsa de forma libre; el agente coloca kicker/title/detail/data/quote aquí |
archetype (opcional) | string | etiqueta de forma libre que puedes adjuntar para recordar el patrón de una tarjeta; ausente = libre, que es el valor predeterminado |
transition (opcional) | enum: cut | fade | slide | wipe | transición declarativa de tarjeta a tarjeta |
Cinco valores de zone:
| zona | límites resueltos | cuándo usar |
|---|---|---|
fullscreen | cubre todo el lienzo | momentos héroe, grandes números, mantras |
whiteboard-area | margen interno de 40px (o 45% de la altura vertical) | contenido denso / anotado |
lower-third | banda inferior del 30% | anotación sobre video visible |
side-panel | 42% derecho (horizontal) o 40% inferior (vertical) | datos a un lado, video al otro |
video-overlay | lienzo completo, espera tarjeta mayormente transparente | superposiciones de anotación sobre video a sangre |
Cuando ensambles la composición en el Paso 9, resuelve la zone de cada tarjeta en límites de píxeles en el contenedor host de la tarjeta siguiendo la tabla anterior. Los límites del video se establecen una vez a nivel de composición (videoTrack.bounds); para hacer que el video parezca "moverse entre tarjetas", redacta tweens de GSAP contra #video-wrap en el <script> de la composición (ver Paso 9).
Sin roles de tarjeta prescritos, sin arco narrativo prescrito. Las tarjetas surgen de lo que realmente dice el video — podrían ser todas citas o todos datos, podrían comenzar con un número o con una historia. Deja que la transcripción marque el ritmo.
¿Cuántas tarjetas? — inferir automáticamente de la duración + densidad. Sin límite superior fijo. Elige un ritmo base de la duración del video, luego ajústalo por densidad de información. Solo el mínimo es fijo: mínimo 5 tarjetas para que incluso videos cortos tengan ritmo.
Paso 1 — ritmo base por duración (el seg/card natural para densidad media):
| duración del video | ritmo base (seg por tarjeta) | razonamiento |
|---|---|---|
| < 60s (corto) | 6–8s | los espectadores esperan cortes rápidos en formato corto |
| 60s – 3 min | 8–12s | ritmo social normal |
| 3 – 10 min | 12–20s | da espacio para respirar; cada tarjeta carga más |
| 10 – 30 min | 20–35s | ritmo de conferencia / entrevista de formato largo |
| > 30 min | 30–60s | episódico, sensación de casi capítulo |
Paso 2 — multiplicador de densidad (multiplica el ritmo base):
| señal en la transcripción | multiplicador | efecto |
|---|---|---|
| Alta densidad — muchos números, afirmaciones distintas, ritmo entrecortado, enumeración como lista, cada 1-2 oraciones es una idea nueva | × 0.7 | corta más rápido, más tarjetas |
| Densidad media — flujo mixto con datos y narrativa | × 1.0 | ritmo base |
| Baja densidad — una historia extendida, reformulación repetida, ritmo reflexivo lento, un solo argumento que se desarrolla | × 1.5 | corta más lento, menos tarjetas |
Paso 3 — calcular:
segPorTarjeta = ritmoBase × multiplicadorDensidad
numTarjetas = max(5, round(duracionVideoSeg / segPorTarjeta))
Ejemplos (nota — sin límite superior; videos largos producen naturalmente más tarjetas):
- Corto de 30s, remate único (baja densidad) → 7 × 1.5 = 10.5s/tarjeta → round(30/10.5)=3 → mínimo 5 tarjetas
- Monólogo reflexivo de 60s (baja densidad) → 10 × 1.5 = 15s/tarjeta → 4 → mínimo 5 tarjetas
- Orador de 121s con datos ricos (alta densidad) → 10 × 0.7 = 7s/tarjeta → 17 tarjetas
- Entrevista de 5 min, densidad mixta → 16 × 1.0 = 16s/tarjeta → 19 tarjetas
- Análisis profundo de 10 min, alta densidad → 16 × 0.7 = 11s/tarjeta → 55 tarjetas
- Conferencia de 30 min, densidad media → 28 × 1.0 = 28s/tarjeta → 64 tarjetas
- Podcast de 1 hora, baja densidad → 45 × 1.5 = 67.5s/tarjeta → 53 tarjetas
Cuando una tarjeta dura más de ~15s, planifica una tarjeta más rica (bloque de datos, revelación de múltiples pasos, varios subpuntos que se despliegan con animaciones escalonadas) — una línea estática se vuelve aburrida después de 8s. Para piezas largas donde muchas tarjetas exceden los 30s, considera dividir la línea de tiempo en subcomposiciones (un .html por capítulo, montado con data-composition-src) para que la línea de tiempo de GSAP por archivo se mantenga manejable — consulta la advertencia de lint timeline_track_too_dense de HyperFrames.
content puede ser una cadena simple ("Título: anualizado 5.69%\nNotas: ...") o cualquier forma JSON que capture los datos. El agente decide la forma por tarjeta.
Outro opcional. Este skill no incluye un outro de marca fijo. Si el usuario quiere una tarjeta de cierre, diseña una neutral tú mismo (marca + eslogan de una línea, ~1.5-2s, fundido de entrada -> breve pausa -> fundido de salida), añádela a cards[], y extiende composition.durationSeconds a su endSec. De lo contrario, termina en la última tarjeta de contenido.
7. Decidir estrategia de renderizado
Confirmar la dirección visual con el usuario (HACER ESTO PRIMERO)
Antes de comenzar a diseñar tarjetas o decidir límites, pídele al usuario que elija la relación de aspecto de salida, el diseño, el estilo y el preajuste de densidad de tarjetas. Los marcos se seleccionan automáticamente de la combinación de diseño × estilo elegida (ver tabla "Selección automática de marco" a continuación). Antes de enviar la pregunta, precalcula dos cosas:
recommendedRatio