HeyGen MP3 → MP4 (Propósito Único)
Toma un solo MP3 de voz y devuelve un único MP4 de avatar de HeyGen con sincronización de labios. Nada más.
Esta skill existe porque la skill existente heygen-short-video requiere un plan de producción completo + SRT + segmentos fragmentados, lo cual es excesivo cuando el usuario solo tiene un audio terminado y desea un video de un avatar parlante.
Por qué híbrido REST + MCP (no solo MCP)
Versiones anteriores de esta skill imponían "solo MCP — nunca llames a REST". Esa regla ya no es factible a partir de la reorganización del MCP de HeyGen en 2026: el servidor MCP solo expone create_video_from_avatar, get_video, create_lipsync, list_avatar_looks, etc. — ya no existe una herramienta de carga de activos. Para sincronizar labios desde un MP3 local, la API aún requiere un audioAssetId (activo subido) o un audioUrl (URL HTTPS pública). Alojar una URL pública es frágil (enlaces rotos, fugas), por lo que utilizamos el endpoint REST de carga documentado a través de un script auxiliar, y luego continuamos con MCP para la creación del video, sondeo y descarga.
Restricciones estrictas
| Restricción | Valores permitidos |
|---|---|
| Carga de activos | REST POST https://upload.heygen.com/v1/asset mediante scripts/upload_asset.py (usa HEYGEN_API_KEY) |
| Creación / estado / lista de videos | Solo MCP de HeyGen (mcp__heygen__create_video_from_avatar, mcp__heygen__get_video) |
| ID de avatar | Uno de los IDs en la variable de entorno HEYGEN_AVATAR_LOOKS (lista blanca separada por comas) |
| ID de voz (solo si la ruta MCP fuerza TTS) | HEYGEN_VOICE_ID del archivo .env (no se permite otro ID de voz) |
| Duración del MP3 | ≤ 300 segundos (5 minutos). Falla rápido si es más largo; no dividas automáticamente |
| Relación de aspecto (enum MCP) | 9:16 por defecto (TikTok / Reels). 16:9 solo cuando el orquestador principal lo anula |
| Resolución (enum MCP) | 720p por defecto (produce 720×1280 para 9:16, 1280×720 para 16:9) |
Para la sincronización de labios con MP3, el tipo de voz es audio y se proporciona audioAssetId — no se envía voiceId. La lista blanca de ID de voz anterior solo importa si una firma futura del MCP requiere uno.
Entradas
- Ruta del MP3 (obligatorio) — ruta absoluta al archivo de voz.
- ID de avatar (opcional) — uno de los IDs permitidos. Si se omite, elige aleatoriamente del conjunto permitido para generar variedad visual entre ejecuciones.
- Ruta de salida (opcional) — por defecto,
workspace/heygen-clips/<nombre-mp3>/<nombre-mp3>_<YYYYMMDD-HHMMSS>.mp4relativo a la raíz del proyecto. - Relación de aspecto (opcional) —
9:16(por defecto) o16:9.
Flujo de trabajo
Sigue estos pasos en orden. Cada paso tiene una condición de parada; no continúes después de un paso fallido.
0. Verificación de autenticación (solo en la primera llamada)
El servidor MCP de HeyGen usa OAuth. En una sesión nueva, solo mcp__heygen__authenticate y mcp__heygen__complete_authentication están expuestos; las herramientas reales (create_video_from_avatar, get_video, …) aparecen después de que la autenticación se completa. Si la sesión no tiene ninguna de esas herramientas cargadas, llama a mcp__heygen__authenticate y muestra la URL de autorización al usuario. El usuario hace clic → el navegador puede mostrar un "error de conexión" en la devolución de llamada de localhost (esto es esperado) → el usuario pega la URL de devolución de llamada completa, y tú llamas a mcp__heygen__complete_authentication. Una vez que las herramientas posteriores a la autenticación aparecen en la lista de herramientas diferidas, continúa.
1. Validar el MP3
uv run .claude/skills/heygen-mp3-to-mp4/scripts/check_duration.py "<ruta_mp3>"
Imprime OK <segundos> / TOO_LONG <segundos> / MISSING. Código de salida 0 = OK, distinto de cero = detener.
Si es TOO_LONG: informa al usuario la duración y que HeyGen limita un solo video a ~5 minutos, y sugiere la skill existente heygen-short-video (que fragmenta). No continúes.
2. Elegir el avatar
Lee HEYGEN_AVATAR_LOOKS (lista blanca separada por comas):
HEYGEN_AVATAR_LOOKS=$(
grep -h '^HEYGEN_AVATAR_LOOKS=' .env.local .env 2>/dev/null \
| head -1 | cut -d'=' -f2- | tr -d '"' | tr -d "'"
)
echo "$HEYGEN_AVATAR_LOOKS" | tr ',' '\n' | awk 'BEGIN{srand()} {a[NR]=$0} END{print a[int(rand()*NR)+1]}'
Posible problema de marcadores de posición — claudeclaw-os/.env.local viene con marcadores de posición (avatar_look_id_1,avatar_look_id_2). Los valores reales suelen estar en ~/Documents/GitHub/hoang-ai-marketing/.env:
grep '^HEYGEN_AVATAR_LOOKS=' ~/Documents/GitHub/hoang-ai-marketing/.env
Si el valor coincide con ^(your_|avatar_look_id_|placeholder), trátalo como faltante y recurre al archivo .env del repositorio de marketing. Si ambos son marcadores de posición/faltan, detente y pide al usuario que ingrese IDs reales.
Informa al usuario qué avatar elegiste antes de continuar — es posible que desee cambiarlo.
3. Subir el MP3 como un activo de HeyGen (REST)
uv run .claude/skills/heygen-mp3-to-mp4/scripts/upload_asset.py "<ruta_mp3>"
# → imprime "OK <id_activo>" en caso de éxito
El script auxiliar maneja el encabezado X-Api-Key, selecciona el Content-Type correcto para la extensión del audio y resuelve HEYGEN_API_KEY en este orden: bandera --key-file → variable de entorno HEYGEN_API_KEY → .env.local → .env → ~/Documents/GitHub/hoang-ai-marketing/.env. Los marcadores de posición (your_*) se omiten automáticamente.
Captura el id_activo impreso en la salida estándar.
4. Generar el video del avatar (MCP)
Llama a mcp__heygen__create_video_from_avatar con el nuevo esquema (la forma antigua dimension: {width, height} ya no existe — la herramienta ahora toma los enumerados aspectRatio + resolution):
avatarId: <elegido de la lista blanca>
audioAssetId: <del paso 3>
aspectRatio: "9:16" # o "16:9" cuando el orquestador principal lo anula
resolution: "720p" # 720p · 1080p · 4k
title: "<nombre-mp3>-<marca-de-tiempo>"
Captura el video_id devuelto (el estado será waiting inicialmente).
Por qué audio (no texto): la sincronización de labios desde un MP3 existente requiere que HeyGen consuma el audio directamente. Enviar un script + voiceId aquí cambiaría HeyGen al modo TTS e ignoraría el MP3 subido por completo.
5. Sondeo hasta completar
Llama a mcp__heygen__get_video con el video_id cada ~10–15 segundos. Estados:
waiting/processing/pending→ sigue sondeandocompleted→ tomavideo_urlde la respuesta y continúafailed→ detente, muestrafailure_messageal usuario
Limita la espera a ~10 minutos; si aún está procesando, informa al usuario y permite que decida.
Problema particular de zsh para bucles de sondeo — el nombre de variable status es de solo lectura en zsh. Si escribes status=$(…) en un bucle de sondeo, el script falla con read-only variable: status. Usa un nombre diferente (vstate, phase, ready).
6. Descargar el MP4
uv run .claude/skills/heygen-mp3-to-mp4/scripts/download_video.py "<url_video>" "<ruta_salida>"
Descarga HTTPS simple de la URL devuelta por HeyGen — no es una llamada API para crear o modificar un video.
7. Informar
Informa al usuario tres cosas en una sola respuesta breve:
- ruta de salida del MP4
- qué avatar se usó
- duración y tamaño del archivo resultante
Ejemplo
Usuario: tạo video heygen từ mp3 workspace/audio/episode-3.mp3
Tú:
- Verificación de autenticación → si las herramientas de HeyGen están presentes, saltar; de lo contrario,
mcp__heygen__authenticate+ completar flujo OAuth. check_duration.py workspace/audio/episode-3.mp3→OK 87.4- Elección aleatoria de
HEYGEN_AVATAR_LOOKS(ej.66e75e22e6584bbdaa56a19088286dc8). Dilo. upload_asset.py workspace/audio/episode-3.mp3→OK 36922ca92326480f8dbb0f57fae1a144mcp__heygen__create_video_from_avatar(avatarId=…, audioAssetId=…, aspectRatio="9:16", resolution="720p", title="episode-3-…")→video_id: 874793a8…- Sonde
mcp__heygen__get_videocada ~15s hastacompleted→ tomavideo_url download_video.py <url> workspace/heygen-clips/episode-3/episode-3_20260510-143022.mp4- Informa ruta, ID de avatar, duración.
Lo que esta skill deliberadamente NO hace
- No escribe/transcribe SRT (eso es
mkt-ai-video-extract-srt-segment). - No planifica imágenes, material de archivo, segmentos (eso es
mkt-plan-short-video-edit-16-9). - No fragmenta el MP3 (eso es
heygen-short-videoconsplit_audio.py). - No compone con Remotion o HyperFrames (eso es el orquestador principal).
Si el usuario desea algo de lo anterior, dirígelo a la skill correcta en lugar de expandir esta.
Modos de fallo y mensajes
| Síntoma | Qué decir al usuario |
|---|---|
| Archivo MP3 faltante | MP3 không tìm thấy ở <ruta>. Kiểm tra lại đường dẫn. |
| MP3 > 300s | MP3 dài <X>s, vượt giới hạn 5 phút của HeyGen. Dùng skill heygen-short-video (có chunking) thay thế. |
| MCP de HeyGen no autenticado | Muestra la URL mcp__heygen__authenticate, pide al usuario que autorice, luego mcp__heygen__complete_authentication. |
HEYGEN_API_KEY no encontrada / marcador de posición | Không tìm thấy HEYGEN_API_KEY. Helper đã thử .env.local, .env, và ~/Documents/GitHub/hoang-ai-marketing/.env. Bạn cần thêm key thật (không phải stub your_*) vào 1 trong các file đó. |
HEYGEN_AVATAR_LOOKS es marcador de posición (avatar_look_id_1,…) | Misma recurrencia que la clave API: leer del repositorio de marketing, o pedir al usuario que ingrese IDs de avatar reales. |
| HeyGen devuelve fallo | HeyGen render failed: <mensaje_fallo>. Có thể avatar look bị xoá hoặc audio asset không hợp lệ. |
| Sin créditos | Muestra el error de HeyGen — no hay get_remaining_credits expuesto en esta versión del servidor. Dirige al usuario a https://app.heygen.com/billing. |
Nombre de herramienta no encontrado (upload_asset / generate_avatar_video / get_avatar_video_status) | Nombres MCP antiguos — reemplazados por carga REST + create_video_from_avatar + get_video. Actualiza cualquier llamante que aún use los nombres antiguos. |