Communitygithub.com

lian4211/video-flow

Convierte cualquier contenido (PDF, PPT, DOCX, Markdown, página web, video, un tema) en un video explicativo renderizado con código: estructura pedagógica, storyboard, narración, renderizado cuadro a cuadro con Canvas/HTML, codificación con FFmpeg, TTS opcional, música, subtítulos e informe de calidad.

¿Qué es video-flow?

Este skill transforma cualquier material de origen (PDF, PPT, DOCX, Markdown, URL, video o incluso un tema libre) en un video explicativo profesional generado mediante código. A diferencia de los modelos generativos de video (como Sora o Veo), aquí cada cuadro se renderiza con Canvas/HTML a través de una función `render(t)` pura, lo que garantiza control total, repetibilidad y la posibilidad de modificar un solo fotograma. El flujo de trabajo consta de 8 fases verificables: desde la lectura del material y la definición de la estructura pedagógica, hasta el renderizado con headless Chrome, la mezcla de audio (TTS, música, efectos), la generación de subtítulos y un informe de calidad (QA). Soporta múltiples formatos de pantalla (16:9, 9:16, 1:1, 4:5), 5 estilos visuales predefinidos y 8 tipos de escenas genéricas (título, concepto, proceso, comparación, fórmula, barras, cita, resumen), además de escenas personalizadas. Está diseñado para ser usado por agentes de IA como Claude Code, Cursor, Codex y otros, y requiere un entorno con Python 3.10+, FFmpeg, un navegador Chromium y las librerías necesarias.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add lian4211/video-flow

Preguntar en tu IA favorita

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

Documentación

video-flow: flujo de trabajo para videos explicativos renderizados con código

En una frase: primero piensa en "qué enseñar", luego convierte eso en una línea de tiempo computable y, finalmente, haz que el navegador dibuje cada fotograma. Resultado final = render(t) de Canvas/HTML + capturas de pantalla con headless Chrome + FFmpeg + TTS/música/subtítulos opcionales.

Este Skill divide un "video" en 8 fases comprobables. Cada fase tiene un producto entregable y puntos de verificación; si algún paso no es apto, no se debe pasar al siguiente.


0. Cuándo usar / No usar

Usar:

  • Convertir un PDF, PPT, DOCX, artículo, página web, video o un tema en un video explicativo de 1 a 5 minutos.
  • Necesitar un video con "texto claro, datos precisos, posibilidad de modificar un fotograma y reproducible" (ventaja estructural del renderizado con código frente a los modelos generativos).
  • Requerir múltiples versiones (vertical, cuadrado, panorámico) o versiones en varios idiomas.
  • Necesitar narración, subtítulos y música, y desear que todo el proceso sea repetible.

No usar:

  • Si se necesita un video con actores reales/escenas realistas -> usar modelos generativos de video o grabación real; este Skill solo maneja "la capa de código".
  • Si solo se trata de editar material existente -> usar herramientas de edición o un Agent.
  • Si solo se desea generar un MP4 sin definir el storyboard ni el guion -> el resultado parecerá una plantilla; se recomienda completar los pasos 1 y 2 primero.

1. Reglas estrictas (si se viola alguna, rehacer)

  1. La imagen es una función pura del tiempo: la página debe exponer window.render(t); dado t, la imagen es única.
    • Prohibido: Date.now(), aleatoriedad sin semilla, estado impulsado por requestAnimationFrame, transition/animation de CSS, caché entre fotogramas.
    • Las animaciones acumulativas (partículas, agua) deben simularse con un paso fijo desde 0 hasta t, o mediante una fórmula analítica.
  2. La línea de tiempo es la única fuente de verdad: el storyboard, la narración, la música, los efectos de sonido y los subtítulos se derivan del mismo timeline.json.
  3. Primero el storyboard, luego el código: sin storyboard.md y script.json, no se escribe código de escena.
  4. No inventar hechos: los números, años, nombres de personas y fórmulas deben provenir del material original; si hay incertidumbre, marcarlo con [pendiente de verificar] y listarlo por separado en la entrega.
  5. Sin marca de agua ni logotipo por defecto: a menos que el usuario proporcione un logotipo o nombre de marca; por defecto, el pie de página solo muestra información del curso/tema.
  6. Una sola codificación: el audio se mezcla y ecualiza en la fase WAV, y solo se codifica una vez a AAC; evitar recodificaciones.
  7. Pasar el QA antes de la entrega: verificar fotogramas perdidos, fotogramas negros, sonoridad, duración, subtítulos y sincronización audio-video; ver paso 8.

2. Entrada y productos

Entrada (cualquiera, se pueden combinar)

TipoProcesamiento
PDFscripts/ingest.py extrae texto; si es escaneo o tiene caracteres extraños, rasterizar automáticamente a PNG y "mostrar la página" al modelo
PPTXExtraer título, cuerpo y notas de cada diapositiva; opcionalmente exportar diapositivas clave como imágenes
DOCX / Markdown / TXTExtraer directamente a source/source.md
URL de página webExtraer el cuerpo del texto; conservar el enlace de origen
VideoMetadatos con ffprobe + captura de fotogramas en puntos específicos; si no hay ASR, que el humano complemente el contenido
Tema libreUna frase o esquema del usuario; primero pedir al usuario que confirme "los hechos que deben aparecer"

Estructura del proyecto

<project>/
  project.json          # Metadatos: título/audiencia/objetivo/formato/estilo/voz/música/marca
  source/               # Material fuente (source.md, pages/*.png, meta.json)
  storyboard.md         # Tabla de storyboard: qué se dice en cada escena, imagen, duración, narración, puntos clave
  script.json           # Legible por máquina: scenes[] (type/guion/visual/vo/duración)
  build/                # index.html + lib.js + theme.js + scenes.js + timeline.js
  audio/                # vo/*.wav, bgm, mix.wav
  frames/               # JPEG por fotograma
  out/                  # final.mp4 / final.srt / poster.png
  qa/                   # report.md + hojas de contacto + fotogramas extraídos

Usar scripts/init_project.py para generar la estructura de una vez.


3. Flujo de trabajo (8 pasos)

Paso 0: Verificar el entorno

python scripts/check_env.py

Requisitos: Python 3.10+, FFmpeg/ffprobe, un navegador con motor Chromium, numpy/scipy. Recomendado: edge-tts (voz neuronal en línea), pypdf, python-pptx, python-docx, Pillow. Instalar lo que falte según las indicaciones; si no se puede instalar, degradar (sin narración / voz del sistema / audio escrito a mano).

Paso 1: Leer el material fuente y extraer la "estructura pedagógica"

Responder primero 5 preguntas (escribirlas en brief de project.json):

  1. ¿Quién es la audiencia? ¿Qué saben ya?
  2. Después de verlo, deberían poder decir/hacer qué? (1–3 objetivos verificables)
  3. ¿Cuál es el punto más fácil de malinterpretar/difícil?
  4. ¿Qué hechos/fórmulas/datos deben aparecer? ¿Cuáles son las fuentes?
  5. ¿Duración y formato? ¿Plataforma (aula/móvil/redes sociales)?

No seguir el orden de las páginas del original. Reorganizar usando una de las 4 estructuras de references/storytelling.md:

  • Cadena causal (recomendada para ciencias/ingeniería);
  • Problema → solución → verificación;
  • Error → corrección → transferencia;
  • Línea de tiempo/proceso.

Paso 2: Elegir estilo y formato

Según references/styles.md, elegir 1 estilo (silicon / paper / blueprint / neon / swiss) y según references/formats.md elegir formato. Reglas:

  • Contenido "chips/ingeniería/datos" → silicon / blueprint;
  • "Humanidades/biología/historia" → paper;
  • "Lanzamiento/marketing/joven" → neon / swiss;
  • Una pantalla, un tema; en vertical, reorganizar la disposición, no recortar horizontal a vertical.

Paso 3: Escribir storyboard y guion

Generar storyboard.md (para humanos) y script.json (para máquinas). Cada escena debe incluir:

  • type (title/concept/process/compare/formula/bars/quote/recap/custom)
  • kicker (subtítulo), headline (conclusión en una frase), points (≤3 puntos)
  • vo (narración, 1–2 frases; si no hay voz en off, dejar vacío)
  • visual (datos concretos de gráficos/tablas/flujos/fórmulas)
  • duration (puede estar vacío; se determinará automáticamente por la duración de la narración)

5 reglas estrictas para escribir el guion:

  1. El texto en pantalla ≠ guion de narración: en pantalla solo palabras clave/conclusiones; la narración explica.
  2. Máximo 1 conclusión + 3 puntos de apoyo por pantalla; título ≤ 18 caracteres, línea de texto ≤ 22 caracteres.
  3. Cada 2–4 segundos debe haber un cambio (elemento, escena, énfasis), pero sin explosiones de partículas.
  4. Primero escribir una "lista prohibida": fondo degradado + letras grandes centradas, todas las elementos fundidos, texto pequeño llenando la pantalla, destellos sin sentido.
  5. Marcar las frases con hechos con su fuente; si hay incertidumbre, añadir [pendiente de verificar].

Paso 4: Generar narración y línea de tiempo

# Opcional: si no hay locución, saltar y asignar duration explícita a cada escena
python scripts/tts.py --project . --voice zh-CN-XiaoxiaoNeural --rate +3%
python scripts/timeline.py --project .
  • tts.py genera audio/vo/<id>.wav (48 kHz), aplica EQ/compresión ligera; soporta --from-dir para usar grabaciones humanas.
  • timeline.py genera build/timeline.js y timeline.json usando la duración real de la narración: scene.duration = head + voDuration + tail, para escenas sin narración usar duration explícita.
  • A partir de aquí, solo modificar script.json y volver a ejecutar estos dos pasos, no editar el timeline manualmente.

Paso 5: Construir la página e implementar las escenas

Usar la plantilla:

python scripts/init_project.py --dir my-video --title "..." --format 16:9 --style silicon
# Editar build/content generado por timeline.py; las escenas genéricas ya están implementadas, solo ajustar script.json
  • Las escenas genéricas (8 tipos) están en build/scenes.js, leen CONTENT para renderizar; suficientes para la mayoría de videos explicativos.
  • Para gráficos especializados (chips, circuitos, anatomía, mapas, moléculas), escribir build/custom.js:
    window.CUSTOM['s3'] = function(u, D, sc, ctx){ /* usar helpers de lib.js para dibujar */ };
    
    En script.json, asignar type: "custom" a esa escena.
  • Trabajar una escena a la vez: primero renderizar 3 fotogramas estáticos (scripts/render.py --still 1.2,2.4,3.6), verificar desbordamiento de texto, superposiciones, tamaño del objeto principal, luego continuar.

Paso 6: Renderizar

python scripts/render.py --project . --fps 30
# Renderizar solo un segmento: --start 8 --duration 4
# Reutilizar Chrome existente: --cdp http://127.0.0.1:9333
# Dejar que el script inicie Chrome: --launch-chrome

Salida: frames/f00000.jpg...; soporta reanudación (los fotogramas existentes de más de 2KB se saltan).

Chrome sin cabeza y sandbox: si el entorno prohíbe IPC/tuberías de Chrome, ejecutar en un entorno permitido, o usar --cdp para conectarse a un Chrome ya iniciado.

Paso 7: Música, efectos de sonido, mezcla y subtítulos

python scripts/audio.py --project .            # Sintetizar BGM + colocar narración + duck + master
python scripts/srt.py --project .              # Generar out/final.srt
  • Sin narración: audio.py --no-bgm o solo usar música proporcionada por el usuario.
  • Música del usuario: colocarla en audio/music.*, audio.py hará loop/corte y duck automáticamente.
  • Sonoridad objetivo por defecto: −14.2 LUFS, pico real ≤ −1.5 dBFS; el audio se codifica una sola vez.

Paso 8: Codificación + QA + Entrega

python scripts/encode.py --project .           # frames+mix+srt → out/final.mp4
python scripts/qa.py --project .               # qa/report.md + collage de fotogramas

El QA debe pasar todo (ver references/qa.md):

  • Duración/formato/fotogramas por segundo/pista de audio/pista de subtítulos correctos;
  • Sin fotogramas negros de ≥0.25 s; sin espacios en blanco, sin texto superpuesto, sin desbordamiento;
  • Sonoridad dentro de ±1 LU del objetivo, pico real ≤ −1.5 dBFS;
  • El primer fotograma no es negro; la última escena tiene cierre;
  • Lista de hechos coherente con el material fuente; [pendiente de verificar] listado por separado.

Entrega: out/final.mp4, out/final.srt, poster.png, storyboard.md, script.json, qa/report.md, tiempo de renderizado y deficiencias conocidas.


4. Tipos de escenas genéricas (plantilla ya implementada)

typeUsoCampos clave
titleApertura/capítulotitle/subtitle/kicker
conceptUn concepto + 3 puntos claveheadline/points/visual
processProceso/pasos (3–5)steps[]
compareComparación de dos partesleft/right
formulaFórmula + explicaciónformula/notes[]
barsComparación de datositems[{label,value}]
quoteCita/conclusiónquote/author
recapMapa de resumennodes[]/takeaway
customGráfico especializadoEscribir custom.js propio

Para añadir un nuevo tipo: agregar window.SCENES_IMPL['type'] en scenes.js y documentar el contrato de datos en references/pipeline.md.


5. Formatos y área segura

FormatoTamañoÁrea seguraTamaño de títuloTamaño de texto
16:91920×108096 izq/der / 64 sup/inf72–12028–40
9:161080×192064 izq/der / 160 sup/inf64–9632–44
1:11080×108072 en todos los lados56–8828–40
4:51080×135080 en todos los lados60–9230–42

En vertical, reorganizar: título arriba, gráfico en medio, conclusión abajo; no comprimir horizontalmente. La plantilla usa layout() para cambiar según el formato; consultar references/formats.md.


6. Fallos comunes → Soluciones

SíntomaCausa raízSolución
Pantalla negra/blancaError JS, render no definido, tamaño de canvas 0render.py --still, ver consola; asignar ancho/alto explícito al canvas
Fuente incorrecta/primer fotograma con fuente de respaldoFuente no cargadaEsperar document.fonts.ready antes de poner READY=true; para CJK usar cadena de respaldo del sistema
Mismo t produce dos imágenes diferentes / parpadeo en paraleloUso de rAF/timer/random/estado entre fotogramasConvertir a función pura; hash(seed); resorte cerrado
Texto superpuesto/desbordadoNo se verificaron fotogramas estáticos por escena3 fotogramas estáticos por escena + extraer fotogramas a 360px de ancho en vertical
Desincronización audio-videoAudio comienza en 0 vs video comienza en otro punto; TTS frase por fraseMisma línea de tiempo; TTS completo; -ss antes de -i
Sonoridad fluctuanteMúltiples loudnorm/codificacionesGanancia estática solo en fase WAV; una codificación AAC
Renderizado demasiado lento4K/subfotogramas/pincel/WebGLPrimero probar a 960×540; subfotogramas solo para movimientos rápidos; workers en paralelo
Chrome no arrancasandbox limita IPC/tuberíasEjecutar en entorno permitido, o --cdp conectar a Chrome ya iniciado

7. Puntos de extensión

  • Nuevo estilo: copiar templates/styles/*.json, modificar paleta/fuentes/tipo de fondo; añadir una fila en styles.md.
  • Nueva escena: registrar en build/scenes.js; o escribir gráfico especializado en build/custom.js.
  • Locución humana: colocar grabaciones como <scene-id>.wav en audio/vo_human/, usar tts.py --from-dir solo para remuestreo/tratamiento ligero.
  • Multilingüe: un script.<lang>.json + voz TTS correspondiente; la línea de tiempo puede reutilizar las mismas imágenes (tener en cuenta diferencias de longitud de texto).
  • Múltiples formatos: mismo script.json con diferentes project.format para reiniciar/renderizar; el diseño se adapta con layout().
  • Marca: project.json.brand proporciona texto de logotipo/color/pie de página; desactivado por defecto.

8. Documentos de referencia

  • references/pipeline.md: línea de tecnología completa, contrato de render(t), renderizado CDP, parámetros FFmpeg, modelo de datos de línea de tiempo.
  • references/inputs.md: extracción de PDF/PPT/DOCX/URL/video y OCR de respaldo.
  • references/storytelling.md: 4 estructuras pedagógicas, tabla de ritmo, reglas de guion.
  • references/styles.md: paletas/fuentes/animaciones/temas aplicables de los 5 estilos.
  • references/formats.md: formatos, área segura, reglas de reorganización vertical.
  • references/audio.md: opciones TTS, grabación humana, síntesis de música, ducking, sonoridad, codificación única.
  • references/qa.md: lista de verificación de aceptación y comandos automáticos.

Skills relacionados