Communitygithub.com

liangruibupt/explainer-video-pipeline

Crea un video explicativo narrado (storyboard de Opus, fotogramas dibujados con código, voz Polly, subtítulos, música y efectos de sonido) con renderizadores intercambiables.

¿Qué es explainer-video-pipeline?

Esta habilidad permite generar automáticamente videos explicativos narrados de 1 a 3 minutos sobre cualquier tema (ciencia, producto, tecnología). El proceso completo es gestionado por el pipeline: desde la escritura del guion y storyboard (usando modelos como Claude Opus), pasando por la generación de código para cada fotograma (con renderizadores como Remotion, HTML/Canvas o Manim), hasta la composición final con voz (Amazon Polly o gTTS), subtítulos sincronizados palabra por palabra, música y efectos de sonido. Soporta múltiples plataformas: Claude Code, Cursor y Codex. El usuario solo necesita proporcionar el tema; el pipeline usa valores predeterminados inteligentes y ofrece parámetros intercambiables para el modelo de storyboard, motor de video, renderizador, TTS, idioma, etc. La habilidad incluye pasos para verificar la calidad visual antes del renderizado completo y maneja gotchas comunes como la sincronización de audio y código. Está diseñada para ser altamente configurable y producir resultados profesionales con mínimo esfuerzo del usuario.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/liangruibupt/explainer_video_platform/tree/HEAD/skills/explainer-video-pipeline

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

explainer-video-pipeline (generado automáticamente)

Cuándo usar

El usuario quiere un video explicativo narrado de 1 a 3 minutos sobre un tema (ciencia, un producto, una tecnología), entregado como un MP4 con voz en off, subtítulos, música y efectos de sonido.

Parámetros y valores predeterminados

Pregunta solo por el tema; toma todos los demás valores predeterminados a menos que el usuario especifique un valor. Indica en una línea qué valores usaste.

ParámetroValor predeterminadoOtros valores
topicrequerido—
storyboard_modelclaude-opus-5.5 escribe el guion, la narración y el storyboardcualquier ID de modelo de kiro-cli chat --list-models
video_engineopus-5.5: claude-opus-5.5 escribe cada escena como código que dibuja cada fotogramaotro modelo de código, p. ej. claude-sonnet-5.5; seedance (API de BytePlus ModelArk, necesita ARK_API_KEY); hybrid (clips de Seedance dentro de escenas dibujadas con código)
rendererremotion (React/SVG; Remotion maneja Chromium sin interfaz gráfica fotograma a fotograma)html (Canvas 2D / SVG / GSAP / página p5.js, capturada con Playwright); manim (escenas de Manim Community; ideal para geometría, gráficos, vectores y derivaciones paso a paso)
seedance_modelseedance-1-5-pro-251215cualquier modelo Seedance habilitado en la cuenta de ModelArk del usuario
ttspolly, voz neural Zhiyu, cmn-CN, us-east-1gtts (gratuito, sin clave, voz más plana); cualquier otra voz/idioma de Polly
captionsactivado: temporización de palabras Whisper, incrustadas como subtítulos resaltados palabra por palabradesactivado
whisper_modelsmall (CPU, int8; aproximadamente 5 s para 10 s de habla)base (más rápido), medium (temporización más precisa)
musicsynth (base de oscilador libre de regalías hecha con ffmpeg)none; una ruta a un archivo de música que el usuario posee
sfxactivado: los eventos listados en scenes.json se sintetizan y colocan en sus fotogramasdesactivado: omitir sfx en cada escena
languageNarración en mandaríncualquier idioma que admitan Polly y Whisper
size, fps1920×1080, 30 fps1080×1920 para vertical

"Hecho con Opus 5.5" significa que Opus 5.5 es el autor: escribe el guion y el código de dibujo, y un renderizador convierte ese código en píxeles. Ningún modelo de texto genera video directamente; solo Seedance lo hace. Di esto una vez en la primera respuesta. Si la sesión ya se ejecuta en claude-opus-5.5, haz la escritura tú mismo. De lo contrario, genera una tarea con model="claude-opus-5.5" y keep=true para el storyboard (paso 2) y continúa la misma ejecución con spawn_continue para el código de escena (paso 5), luego revisa su salida tú mismo.

Configuración (una vez por máquina)

Mantén las herramientas en un directorio de caché estable (p. ej. ~/.cache/explainer-video/), nunca en $KIROCREW_SCRATCH, que se recupera entre sesiones.

  • ffmpeg: una compilación estática completa con aevalsrc, anoisesrc, tremolo, sidechaincompress y ass/libass. El ffmpeg incluido de Remotion carece de ellos. Apunta FFMPEG / FFPROBE a él.
  • Entorno virtual Python (boto3 gTTS playwright faster-whisper pillow numpy), luego python -m playwright install chromium-headless-shell desde ese entorno virtual. faster-whisper 1.2.x falla con PyAV 19 (unexpected keyword argument 'metadata_errors'): fija av==16.1.0. Establece HF_HOME en el directorio de caché para que el modelo Whisper se descargue una sola vez.
  • Manim (solo para renderer=manim): pip no puede compilarlo en aarch64 (no hay ruedas para pycairo, manimpango, moderngl). Sin root, usa micromamba: micromamba create -p <cache>/manim-env -c conda-forge python=3.12 manim. Text() con una fuente CJK funciona. MathTex/Tex necesitan una distribución LaTeX más dvisvgm; texlive-core de conda-forge en aarch64 no tiene latex.fmt, por lo que las fórmulas fallan allí. Escribe fórmulas con Text() (Unicode: F = m·a, x², √, →), o instala un TeX Live del sistema donde el usuario pueda.

Pasos

Los helpers están en la carpeta scripts/ de esta habilidad.

  1. Proyecto. Crea una carpeta de proyecto en un repositorio git dentro del espacio de trabajo del usuario. Para renderer=remotion, crea manualmente package.json, tsconfig.json (resolveJsonModule: true), src/index.ts, src/Root.tsx y ejecuta npm i remotion @remotion/cli react react-dom.
  2. Guion y storyboard (por storyboard_model). Escribe scenes.json: un objeto por escena con id, narration (la línea hablada), visual (lo que se ve en pantalla), opcionalmente manim (nombre de la clase Scene) y opcionalmente sfx: [{"at": FOTOGRAMA_EN_ESCENA, "kind": "whoosh|hiss|pop|rise|thud|PATH"}]. Usa 6–10 escenas, una idea cada una, con una escena de título y una tarjeta final. Verifica los hechos con búsqueda web y cita las fuentes en el README.
  3. Imágenes de referencia. Cuando el video muestre un objeto real, pide o busca una foto clara y guárdala en ref/. Nunca dibujes la forma de un objeto real de memoria: ejecuta detección de bordes en la foto, mide puntos clave y genera las formas a partir de esos puntos con un pequeño script guardado en el repositorio.
  4. La narración marca el tiempo. Ejecuta narrate.py scenes.json . --tts polly. Escribe durations.json (fotogramas por escena, calculados a partir de la longitud real de la voz más relleno), narration.wav y audio/sNN.mp3. El código de la escena lee durations.json, por lo que cada escena dura exactamente lo que dura su línea.
  5. Código de escena (por video_engine).
    • remotion: un componente React por escena, animado con useCurrentFrame e interpolate/spring relativas al inicio de la escena.
    • html: un index.html con window.seek = async (frame) => {...} que dibuja exactamente ese fotograma a partir del número de fotograma y el array de durations.json. Sin requestAnimationFrame, sin reloj de pared, sin Math.random sin semilla. Pega el array de durations.json en la página como una constante: una página abierta como file:// no puede fetch() un archivo local, y el fallo es silencioso. GSAP: línea de tiempo pausada + tl.seek(frame / fps). p5.js: noLoop() + redraw() en seek.
    • manim: un scenes.py con una clase Scene por escena. Lee la longitud objetivo de os.environ["SCENE_SECONDS"] y termina con self.wait(max(0.04, secs - self.renderer.time)); dimensiona las animaciones largas desde secs también. Mantén el 15% inferior del fotograma libre para subtítulos.
    • seedance: seedance_clips.py scenes.json . con ARK_API_KEY configurada; descarga clips/<id>.mp4 (las URL caducan después de 24 h).
  6. Verifica fotogramas congelados antes de la renderización completa. Renderiza 4–6 fotogramas, uno por escena clave, combínalos en una hoja de contacto reducida y mira esa sola imagen. Para una verificación independiente, genera un revisor nuevo con solo la hoja y scenes.json.
  7. Sonido. Si alguna escena tiene sfx, ejecuta sfx.py scenes.json .. Luego mix_bgm.py . --music <music>: atenúa la música debajo de la voz, añade sfx.wav, escribe narration_bgm.wav y muestra los niveles RMS. La introducción solo con música debe estar entre −20 y −30 dB; −55 dB o menos significa que es inaudible.
  8. Subtítulos. captions.py scenes.json . --size <WxH> transcribe cada línea con marcas de tiempo de palabras de faster-whisper y las asigna a los caracteres del propio guion, porque Whisper malinterpreta homófonos (oyó 气体 como 漆体). Escribe captions.ass (cada carácter se resalta cuando se habla) y words.json (tiempos por carácter, utilizables para énfasis en pantalla en el paso 5).
  9. Renderizar (imagen silenciosa).
    • remotion: npx remotion render src/index.ts <Comp> out/silent.mp4.
    • html: capture_html.py index.html out/silent.mp4 --frames <suma de durations.json>.
    • manim: manim_scenes.py scenes.py . --manim <manim-env>/bin/manim --quality h. Renderiza cada clase y la rellena o recorta exactamente a su recuento de fotogramas.
  10. Componer con FFmpeg. Con subtítulos: ffmpeg -i silent.mp4 -i narration_bgm.wav -vf "ass=captions.ass" -c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac -b:a 192k -shortest final.mp4. (Sin subtítulos, usa -c:v copy y omite -vf). Verifica que las duraciones de video y audio coincidan dentro de aproximadamente 0.1 s, luego extrae 4–5 fotogramas del MP4 final y revísalos, incluyendo uno a mitad de frase para ver el resaltado del subtítulo.
  11. Entregar. Confirma en una rama de características, abre un PR y, después de fusionar, confirma con gh api repos/<o>/<r>/git/trees/<base>?recursive=1 que los archivos llegaron.

Gotchas

  • Nunca pongas comentarios /* */ dentro de una cadena de atributo d= de una ruta SVG; Chromium deja de analizar en la /. Usa colores hexadecimales de 6 dígitos.
  • El código con números de fotograma absolutos codificados puede colocar un clímax después de que termine su escena.
  • En Manim, posiciona las etiquetas y flechas después de que el objeto se haya movido (o fíjalas con always_redraw / add_updater), de lo contrario se quedan en el lugar antiguo. DashedVMobject no tiene puntos propios: toma posiciones de una forma simple.
  • Un Playwright instalado con pip puede querer una compilación de Chromium más reciente que la almacenada en caché.
  • No edites un archivo con varias llamadas strReplace paralelas; las ediciones se pierden. No escribas código a través de heredocs de shell; las protecciones pueden bloquearlos.
  • Los modelos Seedance 2.x necesitan activación de cuenta y rechazan imágenes de referencia con rostros humanos reales. Los clips de Seedance 1.5 pro son de 4 a 12 s.
  • Licencia de Remotion: gratuita para individuos y empresas de hasta 3 personas; las empresas más grandes necesitan una Licencia de empresa paga. html y manim lo evitan.

Skills relacionados