HyperFrames-Gradle: Converti l'AsciiDoc in video MP4
Publié le 31 May 2026
Due settimane fa, ho lanciato`capsule-gradle`— un plugin che trasforma un deck reveal.js in una capsula video WebM con TTS. Oggi, aggiungo un nuovo plugin: hyperframes-gradle. Fa qualcosa che capsule-gradle non fa : trasformare l’AsciiDoc direttamente in video MP4, senza passare da reveal.js.
Ecco perché questo plugin esiste, come si articola con l’esistente, e ciò che il motore HyperFrames di HeyGen apporta al pipeline di produzione del contenuto
il buco nel pipeline video
Il mio pipeline documentario produce due tipi di video:
-
Capsula di revisione (capsule-gradle) — un deck reveal.js catturato in WebM con
narrazione TTS. Perfetto per rivedere un modulo.
-
Slides d’animation (slider-gradle) — un deck reveal.js HTML interattivo per
Il formatore in presenza
Ma manca un terzo formato : il video standalone
caso d’uso |
Soluzione attuale |
Mancanza |
Slides formatore |
slider-gradle → reveal.js |
(No output) |
Capsula revisione |
capsule-gradle → WebM |
�✅ |
Video teaser |
nessuna |
❌ |
Demo tecnica animata |
nessuna |
�❌ |
Da documento a video |
Nessuna |
❌ |
Il primo use case è critico: come generare automaticamente un video di 60 secondi che presenta un progetto o un modulo, con animazioni GSAP, narration TTS, e sottofondo musicale — il tutto dallo stesso file AsciiDoc cosa le slide ?
Capsule-gradle non può rispondere: gli serve già un deck reveal.js. slider-gradle produce bene questo deck, ma non è progettato per il rendering video. Era necessario avere un pipeline direct : AsciiDoc → video.
HyperFrames : Il Motore
Ho scopertohttps://github.com/heygen-com/hyperframes[HyperFrames] il y a alcuni giorni. È un framework open-source (Apache 2.0) creato da HeyGen, l’unicorno del video IA. 22 700 stelle su GitHub. Il pitch contiene in una frase :
Scrivi HTML. Renderizza video. Realizzato per gli agenti.
Il principio: voi scrivete HTML con dei`data-*`attributi, fate riferimento un’animazione GSAP (o CSS, Lottie, Three.js…), e il motore rende tutto in MP4 via Puppeteer (Chrome headless) + FFmpeg. Risultato deterministico: stesso input, stessi frame, stesso 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>
Che cosa rende HyperFrames diverso da Remotion? Nessun React, nessun bundler, senza JSX. HTML grezzo che gli agenti IA sanno scrivere nativamente. È tagliato esattamente per il mio pipeline : planner-gradle con deepseek può generare questo HTML a partire da un piano SPG/SPD, e un plugin Gradle può convertirlo in MP4.
L’architettura del plugin
hyperframes-gradle segue lo stesso pattern di tutti i miei plugin : il pattern « Plugin Indipendente + Radice Consumatore ».
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
Il pipeline in quattro fasi
Failed to generate image: PlantUML preprocessing failed: [From <input> (line 9) ] @startuml skinparam backgroundColor #FEFEFE skinparam defaultFontSize 11 title condotta hyperframes-gradle rectangle "AsciiDoc\nsorgente" as adoc #LightYellow rectangle "AsciidoctorJ" as asciidoctorj #LightBlue rectangle "HTML HyperFrames (data-* attributi)" as html #LightGreen ^^^^^ Syntax Error? (Assumed diagram type: activity) @startuml skinparam backgroundColor #FEFEFE skinparam defaultFontSize 11 title condotta hyperframes-gradle rectangle "AsciiDoc\nsorgente" as adoc #LightYellow rectangle "AsciidoctorJ" as asciidoctorj #LightBlue rectangle "HTML HyperFrames (data-* attributi)" 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 analizza il sorgente AsciiDoc e estrae i blocchi personalizzati
[hyperframes-composition], [hyperframes-track], [hyperframes-animation].
-
GenerateHyperframesHtmlTask genera l’HTML HyperFrames con le
`data-*`attributi corrispondenti.
-
RenderHyperframesTask appelle la CLI HyperFrames via
ProcessBuilder:
npx hyperframes render --input index.html --output video.mp4.
-
Il MP4 è distribuito in`output/`con un`metadata.json`per l’orchestrazione.
Il DSL AsciiDoc
Il vero valore aggiunto del plugin è il DSL AsciiDoc. L’utente Non scrive mai HTML. Annota il suo documento AsciiDoc esistente:
= 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;
Gli attributi docinfo`:hyperframes-width:`) configurano le dimensioni. I blocchi personalizzati definiscono le composizioni e le tracce. `[hyperframes-animation]`contiene il codice GSAP grezzo — che l’agente IA può generare a partire da una descrizione in linguaggio naturale.
Il Bridge Node.js
L’unico punto di attrito tecnico: HyperFrames è in Node.js/TypeScript, e i miei plugin sono in Kotlin/JVM. La soluzione è 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"
}
}
}
Zero accoppiamento tra il codice JVM e Node.js. Il contratto è via riga di comando. e file su disco. È lo stesso modello che`plantuml-gradle` # Gradle Integration JBake can be integrated into Gradle builds using the JBake Gradle plugin or by calling the JBake CLI directly:
----
tasks.register<JavaExec>("bake") {
mainClass.set("org.jbake.launcher.Main")
classpath = configurations["jbake"]
args = listOf(projectDir.absolutePath, "$buildDir/jbake")
}`slider-gradle`(chi chiama AsciidoctorJ). Niente di nuovo sotto il sole — semplicemente applicato a uno strumento più recente.
== Due Plugins Video, Due Usi
|===
| |capsula-gradle |hyperframes-gradle |Source |Deck reveal.js (HTML esistante) |AsciiDoc → HyperFrames HTML |Caso d'uso |Capsula di revisione |Video standalone esplicativa |Natura |Diapositive → video |Documento → video |reso |Playwright Java → WebM |HyperFrames CLI → MP4 |Animazione |Transizioni reveal.js nativi |GSAP/CSS attributi data |pila |100% JVM (Kotlin) |### Integrazione Gradle
JBake può essere integrato nelle build Gradle utilizzando il plugin JBake per Gradle oppure richiamando direttamente la CLI di JBake:
----
tasks.register<JavaExec>("bake") { mainClass.set("org.jbake.launcher.Main") classpath = configurations["jbake"] args = listOf(projectDir.absolutePath, "$buildDir/jbake") }
|===
|===
|EPIC |Description |Priorità |HF-0 |Bootstrap governance + inquadramento architettura |TERMINATO |HF-1 |Plugin Gradle stub + integrazione AsciidoctorJ |P0 |HF-2 |### Integrazione Gradle JBake può essere integrato nelle build Gradle utilizzando il plugin JBake Gradle oppure chiamando direttamente la CLI di JBake:
```kotlin
----
tasks.register<JavaExec>("bake") {
mainClass.set("org.jbake.launcher.Main")
classpath = configurations["jbake"]
args = listOf(projectDir.absolutePath, "$buildDir/jbake")
} |P1 |HF-3 |DSL AsciiDoc abitudini (blocchi, docinfo, template) |P1 |HF-4 |Integrazione runner-gradle (metadata.json) |P2 |HF-5 |Template pronti all'uso (title-card, code-diff, captions) |P3 |HF-6 |CI + pubblicazione Maven Central / Gradle Portal |P3
|===
La session 000 (bootstrap) è già terminata. La session 001 attaccherà HF-1 : lo stub del plugin Gradle e l'integrazione AsciidoctorJ.
== Perché funziona
Tre ragioni:
1. *HyperFrames è "built for agents*". Il mio pipeline si basa su agenti IA
(planner-gradle + deepseek) che generano contenuto. HyperFrames accetta HTML grezzo — il formato che i LLM padroneggiano meglio. Niente React, niente di JSX, nessuna curva di apprendimento per l'agente.
1. *Il DSL AsciiDoc è naturale*. Tutto il mio ecosistema parla AsciiDoc.
slider-gradle, codex-gradle, training-gradle — tutti consumano del`.adoc`. Aggiungere blocchi personalizzati`[hyperframes-composition]`è un'estensione logico, non una rottura.
1. *Il bridge Node.js è un pattern collaudato*. ProcessBuilder fuori dalla JVM,
Questo è quello che faccio già per PlantUML, Graphviz, Piper. Aggiungi HyperFrames non cambia nulla all'architettura — è uno strumento esterno in più, pilotato da Gradle
[NOTE]
====
La vera forza del pattern è che non c'è *nessuna* dipendenza npm in la build Gradle. Il plugin non importa alcun codice Node.js. Esegue una comando shell. Se HyperFrames evolve o si rompe, il plugin non è accoppiato. — basta aggiornare il comando.
====
== Conclusion: L'anello mancante
Con hyperframes-gradle, il mio pipeline video è completo. Ho:
* Le *slide interattive* (slider-gradle)
* Le *capsule di revisione* (capsule-gradle)
* Le *video standalone* (hyperframes-gradle)
Tre formati. Un unico file sorgente: l'AsciiDoc.
L'obiettivo successivo è HF-1 : fare compilare il plugin e generare un primo HTML HyperFrames a partire da un documento AsciiDoc annotato. La sessione 001 è già inquadrata.
hyperframes-gradle esiste. La governance è in atto. Il backlog è scritto. L'architettura è documentata. Il plugin è nato.
== Riferimenti
* ### Integrazione Gradle
JBake può essere integrato nelle build Gradle utilizzando il plugin Gradle JBake o chiamando direttamente la CLI JBake:
----
tasks.register<JavaExec>("bake") { mainClass.set("org.jbake.launcher.Main") classpath = configurations["jbake"] args = listOf(projectDir.absolutePath, "$buildDir/jbake") } ```
xref:0124_architecture_plugin_gradle_racine_consommateur_independant_post.adoc[Articolo 0124 — L'Architettura Plugin Indipendente + Radice Consumatore]
* https://github.com/heygen-com/hyperframes[HyperFrames — GitHub]
* https://hyperframes.heygen.com/introduction[HyperFrames — Documentazione]
* `foundry/public/hyperframes-gradle/hyperframes-plugin/doc/HYPERFRAMES_ARCHITECTURE.adoc`— Architettura dettagliata
Articoli correlati
14 May 2026