tiempo de lectura : 8 minutes

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 :

  1. Cápsula de revisión (capsule-gradle) — un deck reveal.js capturado en WebM con

narración TTS. Perfecto para revisar un módulo.

  1. 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
  1. AsciidoctorJ analiza la fuente AsciiDoc y extrae los bloques customs

[hyperframes-composition], [hyperframes-track], [hyperframes-animation].

  1. GenerateHyperframesHtmlTask genera el HTML HyperFrames con los

`data-*`atributos correspondientes.

  1. RenderHyperframesTask llama a la CLI de HyperFrames mediante`ProcessBuilder`:

npx hyperframes render --input index.html --output video.mp4.

  1. 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:

  1. 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.

  1. 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.

  1. 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

Articles connexes