Motion por código com agente|INEMA.CLUB-PRO

Aula 1 · 15 min

Vídeo é código: composição com tempo e render determinístico

No motion por código, o vídeo é uma página que sabe desenhar qualquer instante. Um navegador sem tela pede o quadro 0, o 1, o 2, e o FFmpeg junta tudo num MP4. Se a mesma entrada der sempre os mesmos quadros, você pode refazer, corrigir e versionar o vídeo como código. Nesta aula você prova isso na sua máquina.

Começar a aula
Tira de película sobre uma mesa de luz fria, com um círculo branco que cresce de quadro em quadro.

Nesta aula você vai

  1. 1As quatro peças: composição, relógio, navegador sem tela e codificador
  2. 2Comparar dois renders quadro a quadro com um comando
  3. 3Por que Math.random e Date.now quebram o vídeo
  4. 4Sorteio com semente: variedade sem perder a repetição

Objetivo: provar na sua máquina que a mesma composição dá os mesmos quadros e achar o que quebra isso.

01Do código ao MP4

Clique em cada peça. HyperFrames (HTML) e Remotion (React) seguem o mesmo desenho.

Entre máquinas diferentes, GPU e fontes podem mudar alguns pixels; para repetir em outra máquina, o render do 0.8.176 tem --docker ("deterministic render") e --no-browser-gpu.

Determinístico = rodar duas vezes no mesmo ambiente e ter os mesmos quadros. É o que permite corrigir um detalhe sem refazer o resto.

02O que quebra a repetição

Três fontes de acaso que o lint do HyperFrames procura.

1. Sorteio

Cada render sorteia de novo: os mesmos 12 pontos nascem em lugares diferentes.

A troca é um sorteio com semente (mulberry32): a mesma semente dá os mesmos números, sempre.

Trocaconst sorteio = mulberry32(42); depois sorteio() no lugar de Math.random().

03O ensaio: dois renders, comparados quadro a quadro

Duas composições quase iguais: uma usa Math.random, a outra um sorteio com semente. Cada uma é renderizada duas vezes e comparada pelo hash de cada quadro.

Git · clonar o curso (uma vez)
git clone https://github.com/inematds/formacao-cinema-ia-motion-v72 ~/projetos/formacao-cinema-ia-motion-v72
Terminal · dois renders de cada e a comparação
K=~/projetos/formacao-cinema-ia-motion-v72/kit
export HYPERFRAMES_NO_TELEMETRY=1
E=${TMPDIR:-/tmp}/ensaio-motion/a1; rm -rf "$E"; mkdir -p "$E"
for ex in a1-sorteio a1-semente; do
  cp -r "$K/exemplos/$ex" "$E/$ex"; cd "$E/$ex"
  for n in 1 2; do
    npx -y hyperframes@0.8.176 render --quality draft --workers 1 --quiet --output "render-$n.mp4" > /dev/null 2>&1
  done
  echo "## $ex"; bash "$K/comparar-quadros.sh" render-1.mp4 render-2.mp4; echo "saída: $?"
done
Exemplo do repositório
## a1-sorteio
DIFEREM: 89 de 90 quadros
saída: 1
## a1-semente
IGUAIS: 90/90 quadros
saída: 0

São 90 quadros (3 s a 30 fps). Com Math.random só o primeiro coincide; com a semente, os 90. O primeiro render baixa o hyperframes@0.8.176 e o navegador, por isso demora mais.

04O lint acha o acaso antes do render

O mesmo par de composições passado pelo lint do HyperFrames. Ele aponta a linha e sugere a semente.

Terminal · lint das duas composições
K=~/projetos/formacao-cinema-ia-motion-v72/kit
export HYPERFRAMES_NO_TELEMETRY=1 NO_COLOR=1
for ex in a1-sorteio a1-semente; do
  cd "$K/exemplos/$ex"
  npx -y hyperframes@0.8.176 lint; echo "saída: $?"
done
Exemplo do repositório
◆  Linting a1-sorteio/index.html

  ✗ [~/projetos/formacao-cinema-ia-motion-v72/kit/exemplos/a1-sorteio/index.html:24:24] non_deterministic_code: Script contains `Math.random()` which produces non-deterministic output. Renders may differ between frames or runs.
    Fix: Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic across frames.

◇  1 error(s), 0 warning(s)
saída: 1
◆  Linting a1-semente/index.html

◇  0 errors, 0 warnings
saída: 0

O lint sai com código 1 quando acha erro: dá para usar como portão antes de qualquer render.

05Prática

Ensaio, lint e a sua semente.

E1 · Ver o acaso e a semente

10 min

Clone o curso em ~/projetos e rode o bloco "dois renders de cada e a comparação".

Pronto quando: a1-sorteio termina em DIFEREM: 89 de 90 quadros e saída: 1; a1-semente em IGUAIS: 90/90 quadros e saída: 0. (No seu computador o número de quadros diferentes pode variar; o que não pode é a semente dar diferente.)

E2 · O lint como portão

5 min

Rode o bloco do lint.

Pronto quando: a1-sorteio mostra non_deterministic_code e saída: 1; a1-semente mostra 0 errors, 0 warnings e saída: 0.

E3 · Outra semente, mesma garantia

10 min

Em /tmp/ensaio-motion/a1/a1-semente, troque mulberry32(42) por mulberry32(7), renderize duas vezes (render-3.mp4 e render-4.mp4, com o mesmo comando do bloco) e compare: 3 com 4, depois 1 com 3.

Pronto quando: bash ~/projetos/formacao-cinema-ia-motion-v72/kit/comparar-quadros.sh render-3.mp4 render-4.mp4 → IGUAIS: 90/90 quadros; o mesmo com render-1.mp4 render-3.mp4 → começa com DIFEREM:.

06Teste da aula

A explicação aparece depois da sua resposta.

Pergunta 1 de 4

Quem decide qual instante a composição desenha?

07Em três frases

Composição + relógioO vídeo é uma página que desenha qualquer instante que o motor pedir.
DeterminismoMesma entrada, mesmos quadros: é o que deixa corrigir um detalhe sem refazer o resto.
Acaso controladoSorteio com semente, tempo do motor e dados gravados na pasta; o lint vigia.

Para ir além

Próxima aula