tempo de leitura : 8 minutes

Há duas semanas, eu lancei`capsule-gradle`— um plugin que transforma um deck reveal.js em cápsula de vídeo WebM com TTS. Hoje, estou adicionando um novo plugin : hyperframes-gradle. Ele faz algo que o capsule-gradle não faz : transformar o AsciiDoc diretamente em vídeo MP4, sem passar por reveal.js.

Aqui está por que esse plugin existe, como ele se articula com o existente, e o que o motor HyperFrames da HeyGen traz para o pipeline de produção de conteúdo.

O Buraco no Pipeline de Vídeo

Meu pipeline documental produz dois tipos de vídeos :

  1. Cápsula de revisão (capsule-gradle) — um deck reveal.js capturado em WebM com

narration TTS. Perfeito para rever um módulo.

  1. Slides de animação (slider-gradle) — um deck reveal.js HTML interativo para

o formador presencial

Mas falta um terceiro formato: o vídeo standalone.

Caso de uso

solução atual

Falta

Slides do formador

slider-gradle → reveal.js

✅

Cápsula de revisão

capsule-gradle → WebM

✅

vídeo teaser

Nenhuma

�❌

Demo técnica animada

Nenhuma

❌

Doc-para-vídeo

Nenhuma

�❌

O primeiro caso de uso é crítico: como gerar automaticamente um vídeo de 60 segundos que apresenta um projeto ou um módulo, com animações GSAP, narration TTS, música de fundo — tudo desde o mesmo arquivo AsciiDoc os slides ?

Capsule-gradle não pode responder: ele já precisa de um deck reveal.js. slider-gradle produz bem esse deck, mas não foi projetado para a renderização de vídeo. Precisava de um pipeline direto: AsciiDoc → vídeo.

HyperFrames : O Motor

Descobrihttps://github.com/heygen-com/hyperframes[HyperFrames] il y a alguns dias. É um framework open-source (Apache 2.0) criado pelo HeyGen, o unicórnio do vídeo IA. 22 700 estrelas no GitHub. O pitch se encaixa em uma frase :

Escreva HTML. Renderize vídeo. Construído para agentes.

O princípio: você escreve HTML com`data-*`attributes, você referencia uma animação GSAP (ou CSS, Lottie, Three.js…), e o motor renderiza tudo em MP4 via Puppeteer (headless Chrome) + FFmpeg. Resultado determinístico: mesmo input, mesmas frames, mesmo vídeo.

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

O que torna o HyperFrames diferente do Remotion? Sem React, sem bundler, sem JSX. HTML simples que os agentes de IA sabem escrever nativamente. É exatamente ajustado para o meu pipeline: planner-gradle com deepseek pode gerar esse HTML a partir de um plano SPG/SPD, e um plugin Gradle pode convertê-lo para MP4.

A Arquitetura do Plugin

hyperframes-gradle segue o mesmo padrão que todos os meus plugins: o padrão « Plugin Indépendant + Racine Consommateur ».

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

O Pipeline em Quatro Etapas

Failed to generate image: PlantUML preprocessing failed: [From <input> (line 8) ]

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontSize 11

title Pipeline hyperframes-gradle

rectangle "AsciiDoc
fonte" as adoc #LightYellow
^^^^^
 Syntax Error? (Assumed diagram type: activity)

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontSize 11

title Pipeline hyperframes-gradle

rectangle "AsciiDoc
fonte" as adoc #LightYellow
rectangle "AsciidoctorJ" as asciidoctorj #LightBlue
rectangle "HTML HyperFrames
(data-* attrs)" as html #LightGreen
rectangle "HyperFrames CLI\n(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 analisa o fonte AsciiDoc e extrai os blocos personalizados

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

  1. GenerateHyperframesHtmlTask gera o HTML HyperFrames com as

`data-*`atributos correspondentes.

  1. RenderHyperframesTask chama a CLI HyperFrames via`ProcessBuilder`:

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

  1. O MP4 é implantado em`output/`com um`metadata.json`para a orquestração.

O DSL AsciiDoc

O verdadeiro valor agregado do plugin é o DSL AsciiDoc. O usuário nunca escreve HTML. Ele anota seu 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;

Os atributos docinfo (:hyperframes-width:) configuram as dimensões. Os blocos personalizados definem as composições e as faixas. O bloco `[hyperframes-animation]`contém o código GSAP bruto — que o agente IA pode gerar a partir de uma descrição em linguagem natural

O Bridge Node.js

O único ponto de atrito técnico: HyperFrames está em Node.js/TypeScript, e meus plugins são em Kotlin/JVM. A solução é um`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 acoplamento código JVM ↔ Node.js. O contrato é por linha de comando e arquivos no disco. É o mesmo padrão que`plantuml-gradle` (que chama a CLI PlantUML) ou`slider-gradle`(que chama AsciidoctorJ). Nada de novo sob o sol — apenas aplicado a uma ferramenta mais recente.

Dois plugins de vídeo, dois usos

cápsula-gradle

hyperframes-gradle

Source

Deck reveal.js (HTML existente)

AsciiDoc → HTML HyperFrames

caso de uso

Cápsula de revisão

vídeo explicativo standalone

natureza

slides → vídeo

Documento → vídeo

entregue

Playwright Java → WebM

HyperFrames CLI → MP4

Animação

Transições reveal.js nativas

atributos de dados GSAP/CSS

Pilha

100% JVM (Kotlin)

JVM + Node.js CLI externo

Eles não se substituem. Eles se complementam. A cadeia de valor completa:

AsciiDoc ──→ slider-gradle ──→ deck reveal.js ──→ capsule-gradle ──→ WebM (cápsula de revisão)

AsciiDoc ──→ hyperframes-gradle ──→ MP4 (vídeo autônomo)

O utilizador escreve um único ficheiro AsciiDoc. slider-gradle produz os slides. capsule-gradle produz a cápsula de revisão. hyperframes-gradle produz o vídeo teaser e as demonstrações técnicas

Os 6 EPICs da Roadmap

O plugin é estruturado em 6 EPICs :

EPIC

Descrição

Prioridade

HF-0

Bootstrap governança + enquadramento da arquitetura

✅ CONCLUÍDO

HF-1

Plugin Gradle stub + Integração AsciidoctorJ

P0

HF-2

Bridge CLI HyperFrames (ProcessBuilder → npx → MP4)

P1

HF-3

Costumes do DSL AsciiDoc (blocos, docinfo, modelos)

P1

HF-4

Integração runner-gradle (metadata.json)

P2

HF-5

Modelos prontos para uso (title-card, code-diff, captions)

P3

HF-6

CI + publicação Maven Central / Gradle Portal

P3

A sessão 000 (bootstrap) já terminou. A sessão 001 atacará HF-1 : o stub do plugin Gradle e a integração AsciidoctorJ.

Por que funciona

Três razões :

  1. HyperFrames é "built for agents". Meu pipeline depende de agentes de IA

(planner-gradle + deepseek) que geram conteúdo. HyperFrames aceita de HTML bruto — o formato que os LLMs dominam melhor. Sem React, não de JSX, sem curva de aprendizagem para o agente.

  1. O DSL AsciiDoc é natural. Todo o meu ecossistema fala AsciiDoc.

slider-gradle, codex-gradle, training-gradle — todos consomem do`.adoc`. Adicionar blocos personalizados`[hyperframes-composition]`é uma extensão lógico, não uma ruptura.

  1. O bridge Node.js é um padrão comprovado. ProcessBuilder fora da JVM,

isso é o que eu já faço para PlantUML, Graphviz, Piper. Adicionar HyperFrames não muda nada na arquitetura — é mais uma ferramenta externa, pilotado a partir do Gradle.

A verdadeira força do padrão é que não há nenhuma dependência npm em o build Gradle. O plugin não importa código Node.js. Ele executa uma comando shell. Se HyperFrames evolui ou quebra, o plugin não está acoplado — basta atualizar o comando.

Conclusão: O elo faltante

Com hyperframes-gradle, meu pipeline de vídeo está completo. Eu tenho :

  • As slides interativas (slider-gradle)

  • As capsules de revisão (capsule-gradle)

  • vídeos standalone (hyperframes-gradle)

Três formatos. Um único arquivo fonte: o AsciiDoc.

O próximo objetivo é HF-1 : compilar o plugin e gerar um primeiro HTML HyperFrames a partir de um documento AsciiDoc anotado. A sessão 001 já está enquadrada.

hyperframes-gradle existe. A governança está instalada. O backlog est escrito. A arquitetura está documentada. O plugin nasceu.

Referências

Articles connexes