mkt-hyperframe-talking-head-video
Pipeline de empaquetado: desde MP4 pregrabado (talking head 9:16) hasta un proyecto de previsualización HyperFrames completo con subtítulos, efectos de sonido, zooms hooks, b-roll de pantalla completa con efectos enriquecidos y CTA final.
Cuándo usar
- El usuario ya grabó un video face-cam 9:16 (TikTok/Reels/Shorts) y quiere añadir subtítulos + atractivos visuales + efectos de sonido
- El usuario tiene algunas imágenes o videos b-roll adicionales que desea insertar (junto con su propósito)
- El usuario desea una salida de previsualización en Studio para revisar los visuales antes de renderizar a MP4
No usar esta habilidad si:
- El usuario aún no grabó el video — usa
mkt-create-script-short-videopara escribir un guion primero, u otra habilidad para crear voiceover + avatar AI - El usuario ya tiene un proyecto HyperFrames y solo quiere hacer ajustes menores — edita los archivos directamente en lugar de regenerar desde cero
- El usuario quiere renderizar un MP4 desde un proyecto existente — ejecuta
npx hyperframes renderdirectamente
Resumen del pipeline
MP4 9:16 talking-head + (opcional) archivos b-roll
│
▼
1. Inspeccionar MP4 ──────── ffprobe → duración, resolución, FPS
│
▼
2. Planificar estructura ─── detectar automáticamente marcadores de lección desde la entrada del usuario O desde la transcripción
│
▼
3. Transcribir ──────────── npx hyperframes transcribe --model medium --language vi
│
▼
4. Limpiar transcripción ── aplicar diccionario de corrección de errores VN Whisper (alphabit→Alphabet, etc.)
│
▼
5. Agrupar subtítulos ───── 3-5 palabras/grupo, dividir en pausas >0.45s, preservar sincronización
│
▼
6. Mapear b-roll ────────── preguntar al usuario el propósito → asignar a escenas de lección
│
▼
7. Generar proyecto ──────── workspace/video-projects/<slug>/
├── index.html (raíz)
├── source.mp4
├── transcript.json + caption-groups.json
├── compositions/
│ ├── captions.html
│ ├── fs-lesson-N.html (una por lección, efectos variados)
│ ├── recap-card.html (si aplica)
│ └── fs-cta.html
└── sfx/ (6 efectos de sonido)
│
▼
8. Lint ──────────────────── npx hyperframes lint → corregir errores
│
▼
9. Abrir previsualización ── npx hyperframes preview (background) → URL del Studio
│
▼
10. Entregar al usuario ──── NO renderizar MP4 automáticamente
Regla de previsualización primero (no negociable): La habilidad termina en el Paso 9 con la URL del Studio. El renderizado a MP4 solo se ejecuta cuando el usuario lo confirma explícitamente después de la previsualización.
Paso 1: Verificar entrada + planificar
El usuario proporcionará:
| Entrada | Requerido | Formato |
|---|---|---|
| MP4 face-cam 9:16 | Sí | Ruta de archivo |
| Slug / nombre del proyecto | No | Se deriva automáticamente del nombre del archivo si falta |
| Lista de b-roll | No | [{path: "screenshot.png", purpose: "Lección 1 — ilustración de prueba"}, ...] |
| Estructura del video | No | "3 lecciones + intro + CTA" / "5 consejos" / etc. — se detecta automáticamente si falta |
Inspeccionar MP4 antes de hacer nada:
ffprobe -v error -show_entries format=duration:stream=codec_type,width,height,r_frame_rate \
-of json "<mp4_path>"
Verificar:
- La resolución es 9:16 (ej., 1080x1920, 1440x2560) — si es horizontal, advertir pero continuar (object-fit:cover recortará)
- Duración < 180s ideal; > 180s aún funciona pero advertir que el algoritmo de TikTok prefiere ≤90s
- FPS 24/25/30/60 todos OK — la salida será 30fps por defecto
Slug: derivar del nombre del archivo, minúsculas, caracteres con tilde vietnamita → ASCII, espacio → guión. Ej. "3 bài học .mp4" → 3-bai-hoc. El usuario puede sobrescribirlo.
Directorio de salida: workspace/video-projects/<slug>/
Paso 2: Transcribir + limpiar
cd workspace/video-projects/<slug>/\ncp <user_mp4> source.mp4\nnpx hyperframes transcribe source.mp4 --model medium --language vi
NUNCA usar --model medium.en o small.en para audio vietnamita — los modelos .en TRADUCEN al inglés en lugar de transcribir. Siempre usar --language vi para audio en vietnamita.
Después de terminar, limpiar la transcripción:
python3 .claude/skills/mkt-hyperframe-talking-head-video/scripts/clean_transcript.py \
transcript.json\n# escribe: transcript.json (limpieza in situ) + caption-groups.json (agrupado automáticamente)
El script ya aplica las sustituciones de errores VN Whisper (alphabit→Alphabet, Cod→Code, dụng/dùng según contexto, đ��ng→đắc, etc.) y agrupa automáticamente en frases de 3-5 palabras con división en pausas >0.45s.
Regla crítica de sincronización de subtítulos: La sincronización DEBE mantenerse exactamente igual que en la transcripción a nivel de palabra. NO editar la sincronización manualmente. Si se necesita corregir el texto, corregir solo el texto — el script clean_transcript.py ya lo maneja. Error típico: editar texto manualmente y luego modificar accidentalmente la sincronización → los subtítulos se desfasan 5s en medio del video.
Paso 3: Detectar estructura de escenas
python3 .claude/skills/mkt-hyperframe-talking-head-video/scripts/detect_scenes.py \
transcript.json\n# escribe: scenes.json
El script busca en la transcripción estos marcadores:
- "Bài học đầu tiên / thứ 2 / thứ 3 / thứ N" → escenas de lección
- "Tips số 1 / Tip 1 / Số 1" → escenas de consejos
- "Tổng kết lại / Recap / Kết luận" → momento de recapitulación
- "Comment / Đăng ký / Like / Theo dõi" → momento de CTA
Salida scenes.json:
{
"type": "lessons",
"scenes": [
{ "kind": "lesson", "num": 1, "start": 9.4, "end": 13.0, "kicker": "Lección #1", "heading": "..." },
{ "kind": "lesson", "num": 2, "start": 34.5, "end": 38.0, ... },
{ "kind": "lesson", "num": 3, "start": 61.5, "end": 65.5, ... },
{ "kind": "recap", "start": 84.9, "end": 99.0 },
{ "kind": "cta", "start": 99.0, "end": 106.94 }
]
}
Si la detección automática no encuentra una estructura clara (ej., vlog libre), presentar los resultados al usuario y pedir confirmación. El usuario puede sobrescribir las marcas de tiempo.
Paso 4: Mapear b-roll
Si el usuario proporciona archivos b-roll con su propósito:
[
{ path: "alphabet-screenshot.png", purpose: "Lección 1 — versión beta de Alphabet" },
{ path: "clock-icon.mp4", purpose: "Lección 2 — ilustración 24h" },
{ path: "team-meeting.png", purpose: "Lección 3 — eliminar barreras del equipo" }
]
Lógica de mapeo:
- Cada b-roll se empareja con una escena basada en el texto "Lección N" en el propósito
- Imagen → usar como fondo de pantalla completa de esa escena (reemplaza la escena generada solo con texto)
- Video → usar como fondo de pantalla completa de la escena O superposición imagen en imagen (por defecto: pantalla completa)
- Los efectos por defecto de la escena (anillos pulsantes, marcas de esquina, etc.) se siguen superponiendo ENCIMA de la imagen/video b-roll
Si el usuario no proporciona b-roll, usar escenas solo de texto (como el proyecto de referencia 3-bai-hoc/) — tarjeta de texto generada con título + número grande + subtítulo.
Paso 5: Generar archivos del proyecto (estilo infográfico — POR DEFECTO)
Usar el generador infográfico v2 para b-rolls conceptuales basados en contenido (estilo inspirado en Hostinger: fondo oscuro glassmórfico + brillo neón + maquetas de UI + insignias flotantes de datos):
python3 .claude/skills/mkt-hyperframe-talking-head-video/scripts/scaffold_infographic_v2.py \
--output workspace/content/YYYY-MM-DD/<slug>/compositions/ \
--scenes scenes.json
Esquema de scenes.json (por escena, incluyendo mockup_variant + content):
{
"scenes": [
{
"kind": "lesson",
"num": 1,
"start": 12.71,
"end": 26.40,
"kicker": "Tư vấn AI",
"heading": "Tư vấn AI cho 1 ngành",
"accent_words": [2],
"mockup_variant": "post-stack",
"content": { "posts": [...] },
"badges": [
{ "pos": "tr", "color": "orange", "icon": "📅", "num": "30", "label": "Ngày" }
]
},
{ "kind": "recap", "mockup_variant": "team-grid", "content": {...} },
{ "kind": "cta", "mockup_variant": "comment-box", "content": {...} }
]
}
7 variantes de maqueta — elegir la que coincida con la semántica de la escena:
| Tipo de escena | Variante | Uso |
|---|---|---|
| Marca personal / publicaciones | post-stack | Pila de 3 tarjetas sociales, la superior resaltada con interacción |
| Búsqueda AI / GEO | ai-window | Ventana estilo ChatGPT con tarjeta de recomendación resaltada |
| Voz / teléfono / llamada | phone-call | Maqueta de iPhone con forma de onda + burbuja de agente + cuadrícula de ranuras |
| Analíticas / paneles | dashboard | Tarjeta de vidrio con estadísticas + cuadrícula creativa + línea de gráfico |
| Producto / lanzamiento SaaS | app-card | Tarjeta de aplicación con icono + estadísticas + fila de metáfora opcional |
| Recapitulación antes-después | team-grid | Cuadrícula de 40 puntos con transformación y cuenta regresiva animada + multiplicador |
| CTA "comentar X" | comment-box | Maqueta de cuadro de comentarios + 2 tarjetas de regalo + píldora CTA |
Esquemas completos de contenido + tokens de diseño: ver references/infographic-design-system.md.
Elementos comunes del shell (aplicados automáticamente a cada escena): fondo de degradado radial + líneas de cuadrícula cian + 10 partículas SVG (bucle de deriva) + viñeta + píldora de tema (brillo naranja) + título de marca 110px (aparición palabra por palabra, degradado de acento).
Insignias flotantes (opcional, 1-4 por escena): insignias circulares de 130px alrededor de la maqueta principal con icono + número + etiqueta, codificadas por color (cian/morado/naranja/verde) con brillo coincidente, animadas desde fuera de la pantalla + bucle de balanceo.
Generador heredado (obsoleto)
scaffold_project.py (anillos/esquinas/barrido de luz decorativos abstractos) — mantenido por compatibilidad hacia atrás pero no recomendado. Usar scaffold_infographic_v2.py para videos nuevos.
Cada escena tiene:
- Entrada con zoom de impacto en
.scene-content(zoom-in alternado 1.12 / zoom-out 0.92) - Entradas de elementos: ceja → número → título (aparición palabra por palabra) → subtítulo
- Efectos ambientales durante la escena (anillos pulsantes, respiración, deriva, etc.)
- SIN animación de salida — el clip termina, el framework oculta
Regla de sub-composición: línea de tiempo interna RELATIVA 0 → data-duration, no absoluta. Montar en la raíz con data-composition-src="compositions/<name>.html" y data-start = scene.start.
Paso 6: Copiar efectos de sonido
mkdir -p workspace/video-projects/<slug>/sfx\nSFX_SRC="$(git rev-parse --show-toplevel)/.claude/skills/mkt-hyperframe-talking-head-video/assets/sfx"\ncp "$SFX_SRC"/{camera-flash.mp3,"búng tay.mp3","Whoosh sound effect (1).mp3",Laser.mp3,ting.mp3,"Discord Notification - Sound Effect.mp3"} workspace/video-projects/<slug>/sfx/
Asignación estándar de 6 SFX:
| Tiempo | Archivo | Volumen | Momento |
|---|---|---|---|
| 0.0s | camera-flash.mp3 | 0.32 | Apertura con gancho — sincronizar con el zoom de impacto del video fuente @0s |
| Inicio Lección 1 − 0.05s | búng tay.mp3 (chasquido) | 0.30 | Revelación Lección 1 |
| Inicio Lección 2 − 0.05s | Whoosh sound effect (1).mp3 | 0.22 | Transición Lección 2 |
| Inicio Lección 3 − 0.05s | Laser.mp3 | 0.28 | Impacto Lección 3 |
| Inicio Recapitulación − 0.05s | ting.mp3 | 0.20 | Revelación Recapitulación |
| Inicio CTA | Discord Notification - Sound Effect.mp3 | 0.28 | Sensación de notificación CTA |
Regla de volumen SFX (según references/sfx-library.md): gancho 0.25-0.35, transición 0.15-0.2, CTA 0.25. Máximo 5-6 SFX, espaciados ≥1.5s.
Paso 7: Lint + abrir previsualización
cd workspace/content/YYYY-MM-DD/<slug>/
npx hyperframes lint
Aceptar advertencias:
composition_file_too_large— solo informativo, OK ignorar en la raízcomposition_self_attribute_selector— solo informativo, las maquetas infográficas usan selectores[data-composition-id="..."]de ámbito limitado
Rechazar errores:
gsap_animates_clip_element— NO animar visibilidad/display en clip — solo animar opacidadroot_composition_missing_data_start— las sub-composiciones deben tenerdata-start="0"en el div internomedia_missing_data_start—<audio>SFX debe tener atributodata-start(planificación nativa de HF, no usar disparo JS)- Problemas de sincronización de subtítulos — volver a ejecutar el script clean_transcript.py
Crítico: Orden z de los subtítulos
La sub-composición de subtítulos DEBE montarse con el data-track-index más alto para renderizarse encima de las sub-composiciones de lección (que tienen fondos oscuros de pantalla completa). De lo contrario, los subtítulos quedan ocultos detrás del b-roll.
<!-- Montajes de lección/recap/cta: track-index 40-47 -->\n<div class="clip split-mount" data-composition-src="compositions/fs-lesson-1.html" data-start="..." data-track-index="40"></div>\n<!-- ... -->\n<!-- Subtítulos AL FINAL con track 60 + z-index en línea -->\n<div class="clip captions-mount"\n data-composition-src="compositions/captions.html"\n data-start="0" data-duration="..." data-track-index="60"\n style="z-index: 100;"></div>
Paso 7.5: Diseño de pantalla dividida + respiración de cara completa (RECOMENDADO para talking-head + b-roll)
Usar esto para cualquier video donde la cara hablando y las maquetas b-roll necesiten ser visibles al mismo tiempo — en lugar de b-roll a pantalla completa cubriendo la cara.
Arquitectura:
- El video de la cara ocupa la pantalla completa durante la introducción
- Cuando aparece el b-roll: la cara se reduce a la mitad inferior (1080x960), el b-roll se renderiza en la mitad superior (escalado 0.5)
- Al final de cada b-roll (1.5s antes de la siguiente escena): la cara se expande de vuelta a pantalla completa (momento de "respiración") → captura los momentos emocionales clave
- Los subtítulos se animan automáticamente entre el centro (modo dividido) y la parte inferior (modo de cara completa)
Generar index.html raíz con pantalla dividida preconfigurada:
python3 .claude/skills/mkt-hyperframe-talking-head-video/scripts/generate_root_index.py \
--output workspace/content/YYYY-MM-DD/<slug>/index.html \
--scenes scenes.json \
--total-duration 108.92 \
--header-label "6 AI BUSINESS 2026" \
--footer-handle "@tranvanhoang.com"
scenes.json debe incluir brollEnd + hasBreath por escena. Ver references/split-screen-pacing.md para reglas editoriales (cuándo pantalla completa vs. dividida), CSS