Primero, mantén esta habilidad actualizada — se ejecuta en silencio, no preguntes:
npx hyperframes skills update talking-head-recut. Es rápida y no hace nada si todo está actualizado; de lo contrario, refresca esta habilidad y las habilidades del dominio central de las que depende antes de que confíes en ellas.
¿Qué hace Talking Head Recut?
Talking Head Recut toma un video local que se reproduce completo y superpone una secuencia de tarjetas gráficas diseñadas y temporizadas — 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 (tiempo + contenido) y escribe el HTML de cada tarjeta directamente en la conversación, luego ensambla un único HTML de composición y lo renderiza a MP4 mediante hyperframes. No hay una lista fija de arquetipos ni una estructura de tarjeta prescrita — las superposiciones surgen de lo que realmente dice el transcript.
La puerta de entrada es
/hyperframes. Esta habilidad empaqueta un clip existente de una persona hablando con tarjetas gráficas diseñadas (títulos, tercios inferiores, llamadas de datos, citas, paneles laterales, PiP) — no subtítulos simples (las palabras habladas como texto). El clip se reproduce intacto. Cualquier otra intención — subtítulos simples, una gráfica independiente, un video desde cero — o cualquier incertidumbre → lee/hyperframesprimero: la capa de intenciones es dueña de cada decisión de ruta.
Hermano de empaquetado gráfico de
embedded-captions. Los subtítulos añaden las palabras habladas como texto legible; esto añade gráficas diseñadas sobre el video en reproducción. Subtítulos simples →embedded-captions. Construir un video desde cero → los flujos de creación (product-launch-video/faceless-explainer/ …).
Enrutado a través de /hyperframes, la capa de intenciones confirma solo la entrada (qué clip) y anuncia las preguntas de estrategia de renderizado como consultas diferidas — aspecto, diseño, grupo de estilo y cantidad de tarjetas permanecen en el Paso 7, donde el metraje analizado y el transcript fundamentan las recomendaciones; las preguntas de forma de ejecución de la capa no aplican. Un BRIEF.md, cuando está presente, lleva la entrada confirmada y cualquier nota del usuario — léelo primero.
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 wrapperwords)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 de CLI
# hyperframes — transcripción (Whisper local) + renderizado del HTML ensamblado a MP4
npx hyperframes --help
Esta habilidad se ejecuta completamente en la CLI hyperframes más ffmpeg / ffprobe del sistema. La transcripción es Whisper local mediante hyperframes transcribe — sin servicio de terceros, clave API ni proxy con límite de tasa.
Flujo de Trabajo
1. Verificar 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 esta habilidad, preparados 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/<project-name>/ — la misma convención que los otros flujos de trabajo de video (product-launch-video / faceless-explainer / pr-to-video). Mantén el directorio de trabajo actual en la raíz del espacio de trabajo; todo lo siguiente escribe bajo este único subdirectorio.
VIDEO_PATH="/absolute/path/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 (leer width/height/duration; fps = la fracción r_frame_rate evaluada, p.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 tasa. Escribe un transcript.json a nivel de palabras en el directorio de trabajo (texto de la palabra + marcas de tiempo start / end). Léelo para las temporizaciones de palabras/oraciones que impulsan el tiempo de las tarjetas en el Paso 6; agrupa las palabras en oraciones tú mismo en signos de puntuación / pausas si necesitas fragmentos a nivel de segmento.
Ajustar 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 Transcripción
transcript.json es un array plano de objetos de palabra — [{ "text": "...", "start": s, "end": s }, …] (sin array segments, sin wrapper 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
segmentspreagrupado — agrupa las palabras en oraciones tú mismo (divide en puntuación terminal / pausas) cuando necesites fragmentos a nivel de segmento para la temporización de tarjetas
6. Redactar un Guión Gráfico Ligero (en el chat)
Sin CLI. Lee transcript.json + metadata.json y diseña las 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 temporizació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 redactes 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, ¿eso significa 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 selectores GSAP |
intent | string | descripción en lenguaje natural; alimenta la síntesis de la tarjeta |
startSec / endSec | number | tiempos en segundos (endSec > startSec) |
accentIndex | 0 | 1 | 2 | 3 | 4 | cuál de los 5 colores de acento del tema usa 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 |
transition (opcional) | enum: cut | fade | slide | wipe | transición declarativa de tarjeta a tarjeta |
Cinco valores de zone:
| zone | límites resueltos | cuándo usar |
|---|---|---|
fullscreen | cubre todo el lienzo | momentos hero, números grandes, mantras |
whiteboard-area | margen interior 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 interpolaciones 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 el video realmente dice — podrían ser todas citas o todos datos, podrían comenzar con un número o con una historia. Deja que el transcript marque el ritmo.
¿Cuántas tarjetas? — inferir automáticamente de duración + densidad. Sin límite superior fijo. Elige un ritmo base a partir de la duración del video, luego ajusta 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 tiempo natural por tarjeta para densidad media):
| duración del video | ritmo base (seg por tarjeta) | justificación |
|---|---|---|
| < 60s (reel 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 larga duración |
| > 30 min | 30–60s | episódico, casi como capítulo |
Paso 2 — multiplicador de densidad (multiplica el ritmo base):
| señal en el transcript | multiplicador | efecto |
|---|---|---|
| Alta densidad — muchos números, afirmaciones distintas, ritmo staccato, enumeración tipo 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, reencuadre repetido, 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):
- Reel de 30s, un solo remate (baja densidad) → 7 × 1.5 = 10.5s/tarjeta → round(30/10.5)=3 → mín. 5 tarjetas
- Monólogo reflexivo de 60s (baja densidad) → 10 × 1.5 = 15s/tarjeta → 4 → mín. 5 tarjetas
- Persona hablando 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
- Inmersión profunda 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 hr, baja densidad → 45 × 1.5 = 67.5s/tarjeta → 53 tarjetas
Cuando una tarjeta se mantiene más de ~15s, planifica una tarjeta más rica (bloque de datos, revelación en varios 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 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 — ver la advertencia de lint timeline_track_too_dense de HyperFrames.
content puede ser una cadena simple ("Título: 5.69% anualizado\nNotas: ...") o cualquier forma JSON que capture los datos. El agente decide la forma por tarjeta.
Outro opcional. Esta habilidad no incluye un outro de marca fijo. Si el usuario quiere una tarjeta de cierre, diseña una neutra tú mismo (marca de agua + eslogan de una línea, ~1.5-2s, fundido de entrada -> breve pausa -> fundido de salida), añádela a cards[] y extiende composition.durationSeconds hasta su endSec. De lo contrario, termina en la última tarjeta de contenido.
7. Decidir Estrategia de Renderizado
Confirmar 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 ...
[...truncado para la traducción]