E1 · Clipe de ensaio
5 minRode o bloco "fazer o clipe de ensaio".
Pronto quando: clipe.mp4: 6,0 s · 24 fps · 1920×1080.
Aula 2 · 15 min
A qualidade do movimento na rolagem se decide aqui. Quadros de menos e o filme vira apresentação de slides; quadros grandes demais e a página não abre no celular; nome sem zeros e o filme pula. Você faz um clipe de ensaio com ffmpeg a partir de uma foto, extrai todos os quadros e confere contagem, ordem e peso com um script.
Começar a aula
Objetivo: transformar um clipe em quadros na taxa nativa, com nome em ordem e peso conferido, prontos para a rolagem.
Clique em cada etapa.
Regra das duas skills do INEMA: extrair na taxa nativa. Um filme de 72 s em 24 quadros por segundo tem 1.728 quadros; tirar "uns 300" vira 4 quadros por segundo na rolagem (scroll-film-studio, references/engine.md).
6 s, 24 quadros por segundo, a câmera indo de 1,0 a 1,35 de zoom sobre a foto da lente do kit.
K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a2; rm -rf "$E"; mkdir -p "$E"
bash "$K/scripts/clipe.sh" "$K/exemplos/lente.jpg" "$E/clipe.mp4" 6 1.0 1.35clipe.mp4: 6,0 s · 24 fps · 1920×1080
Troque a foto pela do seu produto e você tem um clipe para treinar o caminho inteiro sem gastar nada.
O quadros.sh extrai; o conferir-quadros.py compara a pasta com o clipe.
K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a2
bash "$K/scripts/quadros.sh" "$E/clipe.mp4" "$E/quadros" 1024 6
ls "$E/quadros" | head -3
python3 "$K/scripts/conferir-quadros.py" "$E/quadros" "$E/clipe.mp4"; echo "saída: $?"#!/usr/bin/env bash
# quadros.sh — extrai TODOS os quadros de um clipe, na taxa nativa dele, para o site rolar.
# Uso: bash quadros.sh <clipe.mp4> <pasta> [largura=1024] [qualidade=6]
# largura: 1024–1280 px no computador, 720 px no filme vertical do celular.
# qualidade: -q:v do JPEG (2 = melhor e mais pesado, 31 = pior); 5–6 é o ponto do curso.
# Grava <pasta>/f_0001.jpg, f_0002.jpg… (zeros à esquerda: a ordem alfabética é a ordem do filme)
# e <pasta>/manifest.json {count, fps, largura}, que a página lê para saber quantos quadros pedir.
set -euo pipefail
CLIPE=$1; PASTA=$2; LARG=${3:-1024}; Q=${4:-6}
FPS=$(ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of csv=p=0 "$CLIPE" | python3 -c "import sys; n,d=sys.stdin.read().strip().split('/'); print(round(int(n)/int(d)))")
mkdir -p "$PASTA"; rm -f "$PASTA"/f_*.jpg
# -fps_mode passthrough: um JPEG por quadro do clipe, sem duplicar nem pular.
ffmpeg -v error -i "$CLIPE" -vf "scale=${LARG}:-2" -fps_mode passthrough -q:v "$Q" "$PASTA/f_%04d.jpg"
python3 - "$PASTA" "$FPS" "$LARG" <<'PY'
import glob, json, os, sys
from PIL import Image
pasta, fps, larg = sys.argv[1], int(sys.argv[2]), int(sys.argv[3])
q = sorted(glob.glob(os.path.join(pasta, 'f_*.jpg')))
json.dump({'count': len(q), 'fps': fps, 'largura': larg}, open(os.path.join(pasta, 'manifest.json'), 'w'))
w, h = Image.open(q[0]).size
mb = f"{sum(os.path.getsize(f) for f in q) / 1e6:.1f}".replace('.', ',')
print(f"QUADROS: {len(q)} · {w}×{h} · {mb} MB · {fps} fps")
PYQUADROS: 144 · 1024×576 · 1,5 MB · 24 fps f_0001.jpg f_0002.jpg f_0003.jpg OK: 144 quadros · 24 fps · 1024 px · 1,5 MB saída: 0
144 quadros = 6 s × 24. A pasta pesa 1,5 MB para 1024 px com -q:v 6.
Quadros de menos e nome sem zeros. Os dois passam despercebidos olhando a pasta.
K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a2; mkdir -p "$E/poucos" "$E/sem-zero"
# erro 1: "uns quadros por segundo bastam" (6 por segundo de um clipe de 24)
ffmpeg -v error -i "$E/clipe.mp4" -vf "fps=6,scale=1024:-2" -q:v 6 "$E/poucos/f_%04d.jpg"
python3 "$K/scripts/conferir-quadros.py" "$E/poucos" "$E/clipe.mp4"; echo "saída: $?"
# erro 2: nome sem zeros à esquerda (f_%d em vez de f_%04d)
ffmpeg -v error -i "$E/clipe.mp4" -vf "scale=1024:-2" -q:v 6 "$E/sem-zero/f_%d.jpg"
python3 "$K/scripts/conferir-quadros.py" "$E/sem-zero" "$E/clipe.mp4"; echo "saída: $?"FALHA: 36 quadros = 6 fps (fonte 24): esperava 144 FALHA: sem manifest.json saída: 1 FALHA: nomes sem zeros à esquerda (f_109.jpg vem antes de f_11.jpg na ordem alfabética) FALHA: sem manifest.json saída: 1
Os dois saem com código 1. O conferidor também cobra o manifest.json, que só o quadros.sh escreve.
Do clipe à pasta conferida, e uma versão sua.
Rode o bloco "fazer o clipe de ensaio".
Pronto quando: clipe.mp4: 6,0 s · 24 fps · 1920×1080.
Rode o bloco "extrair os quadros e conferir".
Pronto quando: OK: 144 quadros · 24 fps · 1024 px e saída: 0.
Faça um clipe de 8 s com uma foto sua (bash clipe.sh sua-foto.jpg seu.mp4 8), extraia em 1280 px com -q:v 5 e confira. Anote o peso da pasta.
Pronto quando: O conferidor responde OK: 192 quadros · 24 fps · 1280 px com saída: 0.
A explicação aparece depois da sua resposta.
Pergunta 1 de 4
Um clipe de 6 s em 24 quadros por segundo. Quantos quadros a pasta deve ter?
Pergunta 2 de 4
A pasta tem f_1.jpg … f_144.jpg. O que dá errado?
Pergunta 3 de 4
A página do celular pesa demais. O que mexer primeiro?
Pergunta 4 de 4
Para que serve o manifest.json?
Escolha uma alternativa. A explicação aparece depois da sua tentativa.