HyperFrames-Gradle : Convertir el AsciiDoc a vídeo MP4
Publié le 31 May 2026
Hace dos semanas, he lanzado`capsule-gradle`— un plugin que transforma un deck reveal.js en cápsula de video WebM con TTS. Hoy, añado un nuevo plugin : hyperframes-gradle. Hace algo que capsule-gradle no hace: transformar el AsciiDoc directamente en video MP4, sin pasar por reveal.js.
Aquí está por qué existe este plugin, cómo se articula con lo existente, y lo que el motor HyperFrames de HeyGen aporta al pipeline de producción de contenido.
El Agujero en el Pipeline de Video
Mi pipeline documental produce dos tipos de videos :
-
Cápsula de revisión (capsule-gradle) — un deck reveal.js capturado en WebM con
narración TTS. Perfecto para revisar un módulo.
-
Diapositivas de animación (slider-gradle) — una presentación reveal.js HTML interactiva para
el formador presencial.
Pero falta un tercer formato: el video independiente.
caso de uso |
Solución actual |
Falta |
Slides formador |
slider-gradle → reveal.js |
�✅ |
Cápsula de revisión |
capsule-gradle → WebM |
�✅ |
Vídeo avance |
Ninguna |
❌ |
Demo técnica animada |
Ninguna |
❌ |
De documento a video |
Ninguna |
❌ |
El primer caso de uso es crítico: ¿cómo generar automáticamente? un video de 60 segundos que presenta un proyecto o un módulo, con animaciones GSAP, narración TTS, y música de fondo—todo desde el mismo archivo AsciiDoc ¿qué tal las diapositivas?
Capsule-gradle no puede responder: ya necesita un deck reveal.js. slider-gradle produce bien este deck, pero no está diseñado para el renderizado de video. Era necesario un pipeline direct : AsciiDoc → video.
HyperFrames : El Motor
He descubiertohttps://github.com/heygen-com/hyperframes[HyperFrames] il y a unos días. Es un framework de código abierto (Apache 2.0) creado por HeyGen, el unicornio del video IA. 22 700 estrellas en GitHub. El pitch mantiene en una frase:
Escribe HTML. Renderiza video. Construido para agentes.
El principio: escribes HTML con`data-*`atributos, usted referencia una animación GSAP (o CSS, Lottie, Three.js…), y el motor renderiza todo en MP4 via Puppeteer (headless Chrome) + FFmpeg. Resultado determinista: misma entrada, mismos frames, mismo video.
<div id="stage" data-composition-id="intro" data-start="0" data-width="1920" data-height="1080">
<video class="clip" data-start="0" data-duration="6" data-track-index="0"
src="background.mp4" muted playsinline></video>
<h1 id="title" class="clip" data-start="1" data-duration="4" data-track-index="1">
Formation Docker & Kubernetes
</h1>
<audio data-start="0" data-duration="6" data-track-index="2"
data-volume="0.3" src="music.wav"></audio>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script>
const tl = gsap.timeline({ paused: true });
tl.from("#title", { opacity: 0, y: 40, duration: 0.8 }, 1);
window.__timelines = window.__timelines || {};
window.__timelines.intro = tl;
</script>
</div>
¿Qué hace que HyperFrames sea diferente de Remotion? Nada de React, nada de bundler, sin JSX. HTML sin formato que los agentes IA pueden escribir de forma nativa. Está diseñado exactamente para mi pipeline: planner-gradle con deepseek puede generar este HTML a partir de un plan SPG/SPD, y un plugin Gradle puede convertirlo a MP4.
La Arquitectura del Plugin
hyperframes-gradle sigue el mismo patrón que todos mis plugins: el pattern « Plugin Independiente + Raíz Consumidor »
hyperframes-gradle/
├── settings.gradle.kts ← racine consommateur (dogfood)
├── build.gradle.kts ← 3 lignes : apply plugin hyperframes
├── hyperframes-plugin/ ← BUILD INDÉPENDANT
│ ├── gradlew ← son propre wrapper
│ ├── build.gradle.kts ← java-gradle-plugin
│ ├── src/main/kotlin/education/cccp/hyperframes/
│ │ ├── HyperframesPlugin.kt
│ │ ├── GenerateHyperframesHtmlTask.kt
│ │ ├── RenderHyperframesTask.kt
│ │ └── HyperframesExtension.kt
│ ├── .agents/ ← gouvernance agent
│ └── doc/
│ └── HYPERFRAMES_ARCHITECTURE.adoc
└── video.yml ← configuration dogfood
El Pipeline En Cuatro Pasos
Failed to generate image: PlantUML preprocessing failed: [From <input> (line 8) ] @startuml skinparam backgroundColor #FEFEFE skinparam defaultFontSize 11 title Pipeline hyperframes-gradle rectangle "AsciiDoc fuente" as adoc #LightYellow ^^^^^ Syntax Error? (Assumed diagram type: activity) @startuml skinparam backgroundColor #FEFEFE skinparam defaultFontSize 11 title Pipeline hyperframes-gradle rectangle "AsciiDoc fuente" as adoc #LightYellow rectangle "AsciidoctorJ" as asciidoctorj #LightBlue rectangle "HTML HyperFrames (data-* atributos)" as html #LightGreen rectangle "HyperFrames CLI (Node.js 22+)" as cli #Lavender rectangle "video.mp4" as mp4 #Gold adoc -right-> asciidoctorj : parse blocs customs asciidoctorj -right-> html : génère HTML html -right-> cli : ProcessBuilder\nnpx hyperframes render cli -right-> mp4 : Puppeteer + FFmpeg @enduml
-
AsciidoctorJ analiza la fuente AsciiDoc y extrae los bloques customs
[hyperframes-composition], [hyperframes-track], [hyperframes-animation].
-
GenerateHyperframesHtmlTask genera el HTML HyperFrames con los
`data-*`atributos correspondientes.
-
RenderHyperframesTask llama a la CLI de HyperFrames mediante`ProcessBuilder`:
npx hyperframes render --input index.html --output video.mp4.
-
El MP4 se despliega en`output/`con un`metadata.json`para la orquestación.
El DSL AsciiDoc
El verdadero valor añadido del plugin, es el DSL AsciiDoc. El usuario Nunca escribe HTML. Annota su documento AsciiDoc existente:
= Formation Docker & Kubernetes
:hyperframes-width: 1920
:hyperframes-height: 1080
:hyperframes-fps: 30
[hyperframes-composition, id="intro"]
== Introduction
Le titre apparaît avec un fondu GSAP sur fond vidéo.
[hyperframes-track, index=0, start=0, duration=6]
video::assets/background.mp4[muted, playsinline]
[hyperframes-track, index=1, start=1, duration=4]
Formation Docker & Kubernetes
[hyperframes-animation, type=gsap]
const tl = gsap.timeline({ paused: true }); tl.from("#title", { opacity: 0, y: 40, duration: 0.8 }, 1); window.timelines = window.timelines || {}; window.__timelines.intro = tl;
Los atributos docinfo (:hyperframes-width:) configuran las dimensiones. Los bloques custom definen las composiciones y los tracks. El bloque `[hyperframes-animation]`contiene el código GSAP bruto — que el agente IA puede generar a partir de una descripción en lenguaje natural.
El Puente Node.js
El único punto de fricción técnica: HyperFrames está desarrollado con Node.js/TypeScript, y mis plugins están en Kotlin/JVM. La solución es un`ProcessBuilder`:
class RenderHyperframesTask : DefaultTask() {
@TaskAction
fun render() {
val process = ProcessBuilder(
"npx", "hyperframes", "render",
"--input", inputHtml.absolutePath,
"--output", outputMp4.absolutePath
)
.inheritIO()
.start()
val exitCode = process.waitFor()
require(exitCode == 0) {
"HyperFrames render failed with exit code $exitCode"
}
}
}
Cero acoplamiento código JVM ↔ Node.js. El contrato es por línea de comandos. y archivos en disco. Es el mismo patrón que`plantuml-gradle` (que llama a la CLI PlantUML) o`slider-gradle`(que llama a AsciidoctorJ). Nada nuevo bajo el sol — solo aplicado a una herramienta más reciente.
Dos plugins de video, dos usos
capsule-gradle |
hyperframes-gradle |
Fuente |
Deck reveal.js (HTML existente) |
AsciiDoc → HTML HyperFrames |
Use case |
Cápsula de revisión |
Vídeo explicativo independiente |
naturaleza |
Slides → vídeo |
Documento → video |
Entregado |
Playwright Java → WebM |
HyperFrames CLI → MP4 |
Animación |
Transiciones nativas de reveal.js |
GSAP/CSS atributos de datos |
Stack |
100% JVM (Kotlin) |
JVM + CLI externa de Node.js |
No se reemplazan. Se complementan. La cadena de valor completa:
AsciiDoc ──→ slider-gradle ──→ deck reveal.js ──→ capsule-gradle ──→ WebM (cápsula de revisión)
AsciiDoc ──→ hyperframes-gradle ──→ MP4 (vídeo autónomo)
El usuario escribe un solo archivo AsciiDoc. slider-gradle produce las diapositivas. capsule-gradle produce la cápsula de revisión. hyperframes-gradle produce el vídeo teaser y las demostraciones técnicas.
Los 6 EPICs de la hoja de ruta
El plugin está estructurado en 6 EPICs :
ÉPICO |
Descripción |
Prioridad |
HF-0 |
Bootstrap gobernanza + alcance arquitectura |
�✅ TERMINADO |
HF-1 |
Plugin Gradle stub + integración AsciidoctorJ |
P0 |
HF-2 |
Puente CLI HyperFrames (ProcessBuilder → npx → MP4) |
P1 |
HF-3 |
DSL AsciiDoc costumbres (bloques, docinfo, plantillas) |
P1 |
HF-4 |
Integración de runner-gradle (metadata.json) |
P2 |
HF-5 |
Listos para usar (title-card, code-diff, captions) |
P3 |
HF-6 |
CI + publicación Maven Central / Portal de Gradle |
P3 |
La sesión 000 (bootstrap) ya ha finalizado. La sesión 001 atacará HF-1 : el stub del plugin Gradle y la integración AsciidoctorJ
¿Por qué funciona?
Tres razones:
-
HyperFrames está "built for agents". Mi pipeline se basa en agentes IA
(planner-gradle + deepseek) que generan contenido. HyperFrames acepta HTML crudo — el formato que los LLM dominan mejor. Sin React, sin de JSX, no hay curva de aprendizaje para el agente.
-
El DSL AsciiDoc es natural. Todo mi ecosistema habla AsciiDoc.
slider-gradle, codex-gradle, training-gradle — todos consumen de`.adoc`. Agregar bloques personalizados`[hyperframes-composition]`es una extensión lógico, no una ruptura.
-
El puente Node.js es un patrón probado. ProcessBuilder fuera de la JVM
Esto es lo que ya hago para PlantUML, Graphviz, Piper. Agregar HyperFrames No cambia la arquitectura — es simplemente otra herramienta externa, Controlado desde Gradle.
|
La verdadera fuerza del patrón es que no hay ninguna dependencia npm en el build Gradle. El plugin no importa código Node.js. Ejecuta una comando de shell. Si HyperFrames evoluciona o se rompe, el plugin no está acoplado — basta con actualizar el comando |
Conclusión : El eslabón faltante
Con hyperframes-gradle, mi pipeline de vídeo está completo. Tengo :
-
Las slides interactivas (slider-gradle)
-
Los cápsulas de revisión (capsule-gradle)
-
Los videos standalone (hyperframes-gradle)
Tres formatos. Un único archivo fuente: AsciiDoc.
El próximo objetivo es HF-1: compilar el plugin y generar un primer HTML HyperFrames a partir de un documento AsciiDoc anotado. La sesión 001 ya está encuadrada.
hyperframes-gradle existe. La gobernanza está establecida. El backlog está escrito. La arquitectura está documentada. El plugin nació.
Referencias
-
Artículo 0124 — La Arquitectura del Plugin Independiente + Raíz Consumidor
-
foundry/public/hyperframes-gradle/hyperframes-plugin/doc/HYPERFRAMES_ARCHITECTURE.adoc— Arquitectura detallada