mkt-hyperframe-talking-head-video-16-9
Editor paisaje 16:9 (1920×1080) dedicado — la entrada es una carpeta de trabajo que ya contiene voiceover.mp3 + source.mp4 + script.txt, y la salida es esa misma carpeta con un proyecto HyperFrames completo listo para previsualizar con npx hyperframes preview.
Esta es una capa operacional bajo el orquestador mkt-full-video-with-11-hyperframe-heygen-16-9. El orquestador maneja la Fase 1 (TTS) + Fase 2 (Avatar de HeyGen) → luego pasa la carpeta a esta habilidad para que se encargue de la Fase 3 (transcripción + scaffold + lint + preview).
Qué produce esta habilidad
<carpeta_de_trabajo>/
├── voiceover.mp3 # entrada (sin modificar)
├── source.mp4 # entrada (avatar HeyGen sincronizado, sin modificar)
├── script.txt # entrada (sin modificar)
├── transcript.json # generado — salida de Whisper a nivel de palabra
├── transcript-cleaned.json # generado — corregido de errores tipográficos en VN
├── scenes-outline.json # generado — esquema previo al punto de control (5 escenas)
├── scenes.json # generado — metadatos finales por escena
├── index.html # generado — composición raíz 1920×1080
├── compositions/
│ ├── scene-1.html # 1 archivo por escena, independientemente de N
│ ├── scene-2.html # creado por subagentes LLM paralelos (Fase 3d)
│ ├── scene-3.html # NO generado por plantillas Python (obsoleto)
│ ├── ...
│ └── scene-N.html
├── sfx/ # 6 SFX enlaces simbólicos/copias desde los assets de la habilidad
│ ├── camera-flash.mp3
│ ├── Whoosh sound effect (1).mp3
│ ├── búng tay.mp3
│ ├── Laser.mp3
│ ├── ting.mp3
│ └── Discord Notification - Sound Effect.mp3
└── (opcional) infographics/
├── 1.png 2.png 3.png # si se usa --with-infographics
└── prompts.md # indicaciones editoriales en papel crema por escena
Lienzo:
- Raíz:
data-width="1920" data-height="1080". - Marco de avatar por defecto SPLIT:
top:100, left:1290, width:540, height:880, borderRadius:32. - Marco de avatar en PIP (esquina):
top:600, left:1540, width:320, height:420, borderRadius:20. - Montaje de diapositivas:
1200×1080SPLIT, animable a1920×1080durante PIP. - Tamaño intrínseco de cada composición:
data-width="1200" data-height="1080"(llena el 100% del montaje, se expande cuando el montaje se ensancha).
Entradas necesarias (convención de carpeta de trabajo)
| Archivo | Requerido | Nota |
|---|---|---|
voiceover.mp3 | Sí | Salida de TTS de ElevenLabs (voz de Hoàng). |
source.mp4 | Sí | Avatar HeyGen sincronizado. Actualmente en retrato 9:16 — el marco paisaje usa object-fit: cover; object-position: center 25% para recortar de manera óptima. Ver references/source-mp4-cropping.md. |
script.txt | Sí | Guion en vietnamita que produjo voiceover.mp3. Se usa para corregir errores tipográficos y derivar títulos de escenas. |
scenes-outline.json | No | Si el usuario predefinió 5 escenas, se salta la detección automática. Esquema: ver Paso 3. |
Slug = nombre base de la carpeta de trabajo (no se necesita derivación). Todos los scripts leen/escriben dentro de esa carpeta. Los scripts aceptan la bandera --workspace <ruta> y por defecto usan el directorio de trabajo actual.
El pipeline (invocación secuencial de scripts)
voiceover.mp3 + source.mp4 + script.txt
│
▼
1. transcribe_audio.py ── Whisper VN → transcript.json (nivel de palabra)
│
▼
2. clean_transcript.py ── elimina artefactos de Whisper, aplica diccionario VN
│
▼
3. detect_scenes.py ── transcript + script.txt → scenes-outline.json (5 escenas)
│
▼
4. [PUNTO DE CONTROL opcional] ── el usuario revisa el esquema / edita kicker, título
│
▼
5. scaffold_project.py ── escribe scenes.json (esquema completo), crea sfx/ + logos/ + avatar.jpg + yt-lower-third.html
│
▼
6. 🔥 FANOUT DE SUBAGENTES LLM 🔥 ── el orquestador lanza N agentes de propósito general
paralelos (1 por escena) en un solo mensaje, cada uno
creando compositions/scene-{num}.html a partir de
visual-plan.json + references/composition-patterns.md.
NO usar generate_compositions.py (generador Jinja2
OBSOLETO — colapsa a 5 arquetipos fijos, no puede adaptar
metáforas específicas de escena, rompe listicles de 6+ escenas).
│
▼
7. generate_root_index.py ── escribe index.html con montaje de diapositivas (monta scene-{num}.html
para TODAS las escenas, sin mapeo kind→fs-lesson) +
marco de avatar (borde de marca claude-orange #d97757) +
timeline GSAP (SPLIT↔PIP, respiración, golpes,
PIP_EVENTS, zoom híbrido de gancho) + 6 SFX conectados +
capa de imagen b-roll en papel crema en la raíz (completo 1920×1080)
│
▼
8. [opcional] scaffold_infographic_slots.py
── añade marcadores de posición <img onerror> + escribe prompts.md
(indicaciones editoriales en papel crema por metáfora de escena)
│
▼
9. lint_and_preview.py ── npx hyperframes lint → 0 errores, luego preview
│
▼
ENTREGA — Se imprime la URL del Studio; el usuario revisa; el orquestador decide el render.
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 después de la confirmación explícita del usuario — ese paso pertenece al orquestador o al usuario manualmente.
Paso 1: transcribe_audio.py
python3 scripts/transcribe_audio.py --workspace <carpeta>
Envuelve la habilidad existente mkt-ai-video-extract-srt-segment si está disponible localmente; de lo contrario, recurre directamente al CLI de whisper:
whisper voiceover.mp3 --model medium --language vi --word_timestamps True \
--output_format json --output_dir .
NUNCA uses --model medium.en para audio vietnamita — .en traduce en lugar de transcribir. Siempre --language vi.
Salida: transcript.json — arreglo de entradas a nivel de palabra {text, start, end}.
Paso 2: clean_transcript.py
Reutiliza la lógica del editor 9:16 hermano (mkt-hyperframe-talking-head-video/scripts/clean_transcript.py). Elimina U+FFFD, aplica un diccionario a nivel de palabra y frase en VN (alphabit→Alphabet, Cod→Code, etc.), agrupa en frases de 3 a 5 palabras. Salida: transcript-cleaned.json. (No hay caption-groups.json — los subtítulos están DESACTIVADOS en 16:9.)
Paso 3: detect_scenes.py
Lee transcript-cleaned.json + script.txt → infiere 5 límites de escena usando el esqueleto estándar de video de conocimiento:
| # | Tipo | Pista de kicker por defecto | Variante |
|---|---|---|---|
| 1 | gancho | Primera oración del guion | tier-row (sensación de pila de publicaciones vía kind=hook) |
| 2 | problema | Donde el guion transiciona a "ChatGPT/AI cũ", "khó", "đứt mạch", "vấn đề"… | chats-stack |
| 3 | solución | Donde el guion introduce la herramienta/método | hero-orb |
| 4 | resumen | Donde el guion muestra un resultado numérico ("X horas", "Y clientes") | counter-row |
| 5 | cta | Última oración con comentario/guardar/seguir | terminal-row |
Si el guion no tiene 5 partes claras, genera menos (mínimo 3) y advierte al usuario. Heurística: dividir el transcript por límites de oraciones en ~5 fragmentos ponderados 1.5x para la escena 3 (la solución suele ser la más larga).
Salida scenes-outline.json:
[
{ "num": 1, "kind": "hook", "start": 0.07, "end": 13.73, "kicker": "...", "heading": "...", "variant": "tier-row" },
{ "num": 2, "kind": "problem", "start": 13.73, "end": 27.37, "kicker": "...", "heading": "...", "variant": "chats-stack" },
{ "num": 3, "kind": "solution", "start": 27.37, "end": 47.75, "kicker": "...", "heading": "...", "variant": "hero-orb" },
{ "num": 4, "kind": "recap", "start": 47.75, "end": 53.80, "kicker": "...", "heading": "...", "variant": "counter-row" },
{ "num": 5, "kind": "cta", "start": 53.80, "end": 60.68, "kicker": "...", "heading": "...", "variant": "terminal-row" }
]
PUNTO DE CONTROL — imprime el esquema para que el usuario lo revise. El usuario puede editar kicker/título/variante en línea y luego continuar. Saltar el punto de control si la habilidad se invoca con --auto (modo orquestador).
Paso 4: scaffold_project.py
Lee scenes-outline.json → enriquece cada escena con:
accent_words— derivadas del título (extraer números + últimos 2-3 sustantivos)content— esquema específico del patrón (verassets/templates/)badges— 1-3 badges flotantes por escenabrollEnd,hasBreath— para la programación SPLIT↔PIPpip_events— derivadas de la sincronización deaccent_wordsdentro de la escena
Escribe scenes.json. También copia automáticamente estos assets autocontenidos del paquete de la habilidad assets/ a la carpeta de trabajo:
| Asset | Origen | Destino | Propósito |
|---|---|---|---|
| 6 archivos SFX | assets/sfx/ | <workspace>/sfx/ | Sonidos de ritmo (camera-flash, whoosh, búng-tay, Laser, ting, Discord-notification) |
| Logos de marca | assets/logos/{chatgpt,gemini,claude,claude-code}.{png,jpg} | <workspace>/assets/logos/ | Adjuntados automáticamente a las composiciones (avatares de chats-stack, hero-orb, badge de herramienta de tier-row) |
| Avatar | assets/avatar.jpg | <workspace>/assets/avatar.jpg | Miniatura del canal para el banner de suscripción yt-lower-third |
| YT lower-third | assets/compositions/yt-lower-third.html | <workspace>/compositions/yt-lower-third.html | Montaje del banner de suscripción, últimos 3s del video |
Si un asset de origen falta en el paquete de la habilidad, recurre silenciosamente a la ruta heredada de la carpeta de trabajo (workspace/assets/...). Si no se encuentra ninguno, ese asset se omite (las composiciones se degradan elegantemente — avatares de texto en lugar de logos, sin lower-third).
Paso 5: 🔥 FANOUT DE SUBAGENTES LLM (creación de composiciones) 🔥
generate_compositions.py está OBSOLETO. No lo llames. El generador Jinja2 de Python colapsa cada escena en 1 de 5 arquetipos fijos (hook → tier-row, problem → chats-stack, solution → hero-orb, recap → counter-row, cta → terminal-row), no puede adaptarse a metáforas específicas de escena (por ejemplo, "scroll-tape-wasted", "two-clock-comparison", "right-tool-vehicles"), y se rompe en listicles de 6+ escenas (múltiples tip-N colapsan al mismo nombre de archivo → sobrescritura).
Método canónico: el orquestador (o el usuario) lanza N agentes de propósito general paralelos (1 por escena) en un solo mensaje para que se ejecuten concurrentemente. Cada subagente:
- Lee su bloque de escena de
visual-plan.json(ruta:<workspace>/visual-plan.json, índice de escenanum-1) - Lee las referencias de la habilidad del orquestador:
references/composition-patterns.md(8 patrones probados en producción),references/slide-design-tokens.md(paleta + tipografía) - Elige el patrón correcto para la metáfora de su escena — se adapta libremente (hero-orb puede convertirse en vault+spokes, stats-3card puede convertirse en two-clock-comparison)
- Crea
compositions/scene-{num}.htmldesde cero con: viewport 1200×1080, CSS con ámbito mediante[data-composition-id="scene-{num}"], timeline GSAP registrado enwindow.__timelines["scene-{num}"], sin!important, sinimage-slotincrustado (la imagen de papel crema vive solo en la capa raíz)
El resultado: cada escena obtiene un archivo de composición único y ajustado a su metáfora. Sin colisiones, sin aburrido bloqueo de 5 arquetipos.
Ver el Paso 4d del orquestador en mkt-full-video-with-11-hyperframe-heygen-16-9/SKILL.md para la plantilla completa del prompt del subagente.
Logos de marca en las composiciones (los subagentes los referencian)
Los subagentes incrustan logos de marca cuando su patrón los necesita. Los logos residen en <workspace>/assets/logos/:
| Uso del patrón | Elemento de marca |
|---|---|
| Hook tier-row "después" | Píldora tool-badge (arriba a la derecha) — logo de Claude + nombre. |
| Filas de fallo de Problem chats-stack | Logos de ChatGPT/Gemini adjuntos automáticamente cuando name coincide con la palabra clave (chatgpt/gpt → chatgpt.png; gemini/google → gemini.jpg). |
| Solution hero-orb / vault | Logo de marca dentro del brillo del orbe (por defecto Claude). |
| CTA terminal-row | Sin logos por defecto. |
Los subagentes recurren a avatar de texto si assets/logos/ no existe (sin parpadeo).
Referencia de patrones (8 arquetipos, los subagentes eligen y adaptan)
El references/composition-patterns.md del orquestador incluye 8 patrones probados en producción:
| Patrón | Mejor para | Motivo interno |
|---|---|---|
tier-row before-after | Contraste de gancho | 2 filas de niveles (antes rosa/rojo + después lima/verde) con letra + elementos |
chats-stack | Problema / fallo / demo de Edit-Regen | Fila de usuario + 2-3 filas de fallo de IA + sello de cadena rota |
hero-orb + spec-trio | Solución / mecanismo / bóveda central | Orbe brillante + iconos de tarea + 3 filas de niveles de especificaciones |
counter-row | Resumen / prueba numérica | Contador grande (DESDE → HASTA) + clientes + etiqueta delta |
comment-terminal | CTA / "comenta X" | Letra de nivel + terminal mock de macOS + 2 tarjetas de regalo |
stats-3card | Introducción de conocimiento / revelación de 3 hechos | 3 columnas estilo landing con // LBL + número degradado |
comparison-2col | "Cuándo usar cuál" | 2 columnas Sí/Sí con chips |
image-slot | (OBSOLETO — imagen en capa raíz) | — |
Los subagentes se adaptan libremente: ej., hero-orb → "bóveda + 5 radios de chat", stats-3card → "comparación de dos relojes", comparison-2col → "3 tarjetas de vehículo de nivel". El documento del patrón da el esqueleto (HTML + CSS + GSAP), el LLM hace la personalización creativa.
Paso 6: generate_root_index.py
Lee scenes.json + total_duration del transcript → renderiza assets/templates/index.html.j2:
- Raíz 1920×1080 con
#slide-bg,#heygen-bg,#avatar-frame > .avatar-breathing > .avatar-punch > #v-source <audio id="a-source">rastrea el audio original de source.mp4 (pista 1)- 6
<audio>SFX conectados condata-startabsoluto (límites de escena) - Marca de marca arriba a la izquierda
- Bloque GSAP:
- Entrada inicial (aparición del avatar, aparición de la marca)
- Constantes SPLIT/PIP + ayudantes
goPIP(t)/goSplit(t) - Arreglo
PIP_EVENTSimpulsado porpip_eventspor escena desde scenes.json - Estrategia de zoom visual "Hybrid Hook" en
.avatar-breathing:- Escena HOOK: rampa lenta 1.0 → 1.10 durante la duración de la escena (construcción dramática,
power2.in) - Transición HOOK→BODY: restablecimiento brusco 1.10 → 1.0 (liberación de tensión, 0.5s
power3.in) - Escenas BODY (2..N-1) en eventos PIP-IN: golpes de pulso 1.06 (ritmo,
power2.out→power3.out) - Escena CTA: empuje suave 1.0 → 1.04 (cierre,
sine.inOut)
- Escena HOOK: rampa lenta 1.0 → 1.10 durante la duración de la escena (construcción dramática,
- Pequeño golpe (1.06) al inicio de cada escena en
.avatar-punchpara la transición be
…
[truncado para la traducción]