E1 · Rehearsal clip
5 minRun the "make the rehearsal clip" block.
Done when: clipe.mp4: 6,0 s · 24 fps · 1920×1080.
Lesson 2 · 15 min
The quality of the scroll motion is decided here. Too few frames and the film turns into a slideshow; frames that are too big and the page won't open on a phone; names without zeros and the film jumps. You make a rehearsal clip with ffmpeg from a photo, extract every frame, and check count, order, and weight with a script.
Start the lesson
Goal: turn a clip into frames at the native rate, with names in order and weight checked, ready for scroll.
Click each step.
Rule from INEMA's two skills: extract at the native rate. A 72 s film at 24 frames per second has 1,728 frames; taking "about 300" becomes 4 frames per second on scroll (scroll-film-studio, references/engine.md).
6 s, 24 frames per second, the camera going from 1.0 to 1.35 zoom over the kit's lens photo.
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
Swap the photo for one of your product and you have a clip to practice the whole path without spending anything.
quadros.sh extracts; conferir-quadros.py compares the folder with the clip.
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 frames = 6 s × 24. The folder weighs 1.5 MB at 1024 px with -q:v 6.
Too few frames and names without zeros. Both go unnoticed when you just look at the folder.
K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a2; mkdir -p "$E/poucos" "$E/sem-zero"
# mistake 1: "a few frames per second is enough" (6 per second from a 24 fps clip)
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: $?"
# mistake 2: names without leading zeros (f_%d instead of 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
Both exit with code 1. The checker also demands the manifest.json, which only quadros.sh writes.
From the clip to the checked folder, and a version of your own.
Run the "make the rehearsal clip" block.
Done when: clipe.mp4: 6,0 s · 24 fps · 1920×1080.
Run the "extract the frames and check" block.
Done when: OK: 144 quadros · 24 fps · 1024 px and saída: 0.
Make an 8 s clip from a photo of yourself (bash clipe.sh sua-foto.jpg seu.mp4 8), extract at 1280 px with -q:v 5 and check it. Note the folder's weight.
Done when: The checker answers OK: 192 quadros · 24 fps · 1280 px with saída: 0.
The explanation appears after you answer.
Question 1 of 4
A 6 s clip at 24 frames per second. How many frames should the folder have?
Question 2 of 4
The folder has f_1.jpg … f_144.jpg. What goes wrong?
Question 3 of 4
The phone page weighs too much. What should you change first?
Question 4 of 4
What is the manifest.json for?
Choose an option. The explanation appears after your attempt.