A fábrica de vídeo com agentes|INEMA.CLUB-PRO

Aula 3 · 20 min

Demonstração de app, clique a clique

Para mostrar um app, a tela real convence mais que qualquer animação. O video-demonstrativo dirige um navegador pelo seu app, tira uma foto por passo com a posição do elemento clicado, narra com voz local e monta o vídeo com cursor e zoom. Nesta aula você faz isso inteiro, com um app de exemplo, sem crédito.

Começar a aula
Notebook numa mesa escura mostrando um app com um círculo destacando o cursor, e um segundo monitor com a mesma tela ampliada.

Nesta aula você vai

  1. 1O actions.json: URL, tamanho da tela e um passo por clique
  2. 2A captura com o agent-browser: foto e posição do alvo de cada passo
  3. 3Narração local por passo, com voz Kokoro, sem serviço externo
  4. 4A composição gerada e o render com a versão do HyperFrames fixa

Objetivo: capturar um app passo a passo com o agente e renderizar a demonstração narrada que passa no conferidor.

01Do app no ar ao MP4

Clique em cada etapa.

Clique em cada bloco do diagrama para ver o que ele faz.

Etapas da skill video-demonstrativo no commit a87b382 (05/10/2026). Captura antes de animar: o vídeo mostra a tela de verdade.

02O app e o roteiro de cliques

Um app de uma página no kit (quantas palavras cabem numa narração) e o actions.json com cinco passos.

Arquivo · kit/exemplos/a3-demo/actions.json
{
  "url": "http://127.0.0.1:18791/",
  "viewport": [1280, 800],
  "window": { "top": 96, "titleH": 52, "urlLabel": "127.0.0.1:18791" },
  "eyebrow": "DEMONSTRAÇÃO · MINUTOS DE VÍDEO",
  "ctaNarration": "Pronto: agora você sabe quantas palavras cabem no seu vídeo.",
  "ctaCaption": "Roteiro do tamanho certo",
  "steps": [
    { "id": "home", "intro": true, "caption": "Minutos de vídeo · do zero", "narration": "Este app diz quantas palavras cabem numa narração. Vamos usar em três cliques." },
    { "id": "minutos", "do": { "type": "setValue", "selector": "#min", "value": "3" }, "target": "#min", "caption": "1 · Duração: 3 minutos", "narration": "Primeiro, a duração do vídeo: três minutos." },
    { "id": "ritmo", "do": { "type": "setValue", "selector": "#ppm", "value": "140" }, "target": "#ppm", "caption": "2 · Ritmo: 140 palavras por minuto", "narration": "Depois, o ritmo da fala. Uma narração calma fica perto de cento e quarenta palavras por minuto." },
    { "id": "calcular", "do": { "type": "clickText", "tag": "button", "text": "Calcular" }, "target": { "tag": "button", "text": "Calcular" }, "click": true, "caption": "3 · Calcular", "narration": "Agora é só clicar em calcular." },
    { "id": "resultado", "target": "#res", "zoom": true, "caption": "Cabem 420 palavras", "narration": "Cabem quatrocentas e vinte palavras. Esse é o tamanho do seu roteiro." }
  ]
}

03Capturar o app

O bloco sobe o app numa porta local, roda a captura numa sessão própria do agent-browser e fecha tudo no fim.

Terminal · capturar o app
K=~/projetos/formacao-cinema-ia-fabrica-v72/kit
command -v agent-browser > /dev/null || { echo "FALTA agent-browser: npm i -g agent-browser@0.6.0 && agent-browser install"; exit 1; }
E=${TMPDIR:-/tmp}/ensaio-fabrica/a3; rm -rf "$E"; mkdir -p "$E"; cd "$E"
git clone -q https://github.com/inematds/video-demonstrativo.git && git -C video-demonstrativo checkout -q a87b382
cp video-demonstrativo/skills/video-demonstrativo/scripts/capture.mjs "$K/exemplos/a3-demo/actions.json" .
python3 -m http.server 18791 --bind 127.0.0.1 --directory "$K/exemplos/a3-demo" > servidor.log 2>&1 & S=$!
until curl -s -o /dev/null http://127.0.0.1:18791/; do sleep 0.3; done
export AGENT_BROWSER_SESSION=ensaio-fabrica
node capture.mjs actions.json > captura.log 2>&1; echo "captura: $?"
agent-browser close > /dev/null 2>&1; kill $S
ls assets/shots
python3 -c "import json; s=json.load(open('steps.json')); print('passos no steps.json:', len(s['steps']))"
Exemplo do repositório
captura: 0
00-home.png
01-minutos.png
02-ritmo.png
03-calcular.png
04-resultado.png
passos no steps.json: 5

Uma foto por passo e o steps.json com as caixas medidas. O until curl espera a porta responder antes de abrir o navegador; sleep fixo falha em máquina carregada.

04Narrar e montar

Cria o projeto HyperFrames, copia fotos, fontes e steps.json, gera uma fala por passo e escreve a composição.

Terminal · narrar e montar
export HYPERFRAMES_NO_TELEMETRY=1 NO_COLOR=1
E=${TMPDIR:-/tmp}/ensaio-fabrica/a3; S=$E/video-demonstrativo/skills/video-demonstrativo
cd "$E" && rm -rf demo
npx -y hyperframes@0.8.176 init demo --non-interactive > init.log 2>&1; echo "init: $?"
cd demo && mkdir -p assets/audio assets/txt
cp -r ../assets/shots assets/ && cp -r "$S/assets/fonts" assets/ && cp ../steps.json .
cp "$S/scripts/composition-template.mjs" build-demo.mjs
node -e 'const d=require("./steps.json"); const l=d.steps.map(s=>s.narration); l.push(d.ctaNarration);
l.forEach((t,i)=>require("fs").writeFileSync(`assets/txt/s${i+1}.txt`, t.trim()+"\n")); console.log("falas:", l.length)'
for f in assets/txt/s*.txt; do
  n=$(basename "$f" .txt)
  npx -y hyperframes@0.8.176 tts "$f" --voice pf_dora --lang pt-br --speed 0.98 --output "assets/audio/$n.wav" > /dev/null 2>&1 || echo "falhou $n"
done
ls assets/audio | wc -l
node build-demo.mjs | head -1
Exemplo do repositório
init: 0
falas: 6
6
index.html gerado · 1920x1080 · TOTAL=30.389s · 6 cenas (5 passos + CTA)

Seis falas (cinco passos e o fecho), seis WAVs. O TOTAL vem da soma das falas com uma folga antes e depois de cada uma: mude a fala, muda a duração.

05Render e conferência

Check, render em rascunho e o conferidor com a duração que a própria composição declara.

Terminal · render e conferir
export HYPERFRAMES_NO_TELEMETRY=1 NO_COLOR=1
K=~/projetos/formacao-cinema-ia-fabrica-v72/kit
cd ${TMPDIR:-/tmp}/ensaio-fabrica/a3/demo
npx -y hyperframes@0.8.176 check 2>&1 | grep -E "◇|✗" | head -3
npx -y hyperframes@0.8.176 render --quality draft --workers 2 --quiet --output renders/demo.mp4 > render.log 2>&1
echo "render: $?"
D=$(grep -o 'id="root"[^>]*data-duration="[0-9.]*"' index.html | grep -o "[0-9.]*\"$" | tr -d \")
echo "duração pedida: $D s"
python3 "$K/conferir.py" renders/demo.mp4 "$D" 1920x1080 --audio; echo "saída: $?"
Exemplo do repositório
  ◇ 0 errors, 0 warnings
  ◇ 0 issues across 9 sample(s)
  ◇ 0 errors, 0 warnings
render: 0
duração pedida: 30.389 s
OK: 30,4 s · 1920×1080 · 30 fps · com áudio
saída: 0

Nesta máquina o render de 30 s levou menos de um minuto (medido fora da captura; render por software, --workers 2). A duração pedida sai do data-duration da raiz, então o conferidor vale para qualquer roteiro seu.

06Prática

Do app de exemplo ao seu app.

E1 · Captura

5 min

Rode o bloco "capturar o app".

Pronto quando: captura: 0, as cinco fotos de 00-home.png a 04-resultado.png e passos no steps.json: 5.

E2 · Demonstração renderizada

10 min

Rode "narrar e montar" e depois "render e conferir".

Pronto quando: index.html gerado · 1920x1080, render: 0 e OK: … · 1920×1080 · 30 fps · com áudio com saída: 0.

E3 · O seu app

30 min

Peça ao seu agente um actions.json com 4 a 6 passos para um app seu que roda em localhost. Troque a URL, rode a captura com o seu arquivo e depois os dois blocos seguintes.

Pronto quando: Na pasta do ensaio, python3 -c "import json; print(len(json.load(open('steps.json'))['steps']))" → o número de passos do seu actions.json, e o render termina em OK: … · com áudio e saída: 0.

07Teste da aula

A explicação aparece depois da sua resposta.

Pergunta 1 de 3

Por que o viewport do actions.json é fixo?

08Em três frases

Captura antes de animaro agent-browser fotografa o app real e mede onde clicar.
Fala manda no tempocada passo dura a sua narração, feita com voz local.
Versão fixaHyperFrames 0.8.176 nos blocos, conferidor no MP4.

Para ir além

Aula anteriorPróxima aula