O que Editor de Reels Cinematográficos faz?
Transforme uma pasta de clipes brutos + uma faixa de música em um reel vertical de 15 a 45 segundos, 9:16, sincronizado com a batida. Toda a edição é feita com FFmpeg pela linha de comando. O plano reside em uma lista de edição editável (edl.json) para que qualquer alteração possa ser re-renderizada sem recomeçar.
0. Regras rígidas
- NUNCA modifique ou exclua nada em
raw/. Escreva todas as saídas emwork/eout/. - A música deve ser fornecida pelo usuário (licenciada / livre de royalties). Se
music/estiver vazia, peça uma faixa — não baixe música protegida por direitos autorais. - Mostre ao usuário o plano de tomadas (passo 4) e obtenha uma aprovação antes da renderização final.
- Prefira cortes secos nas batidas. Use transições com moderação (máximo 2–3 por reel).
1. Verificar pré-requisitos
ffmpeg -version && ffprobe -version
python3 -c "import librosa, numpy" || pip install librosa numpy soundfile
Se o FFmpeg estiver faltando, diga ao usuário para instalá-lo (Windows: winget install ffmpeg, Mac: brew install ffmpeg, Linux: sudo apt install ffmpeg) e pare.
2. Estrutura de pastas
projeto/
raw/ # clipes da câmera (somente leitura)
music/ # uma faixa de música
luts/ # LUT .cube opcional para correção de cor
work/ # miniaturas, segmentos, edl.json, beats.json
out/ # renders finais (reel_v1.mp4, reel_v2.mp4 ...)
3. Inventário e análise das filmagens
Para cada clipe, registre duração, resolução, fps e orientação:
ffprobe -v error -show_entries format=duration:stream=width,height,r_frame_rate,codec_type -of json raw/CLIPE.mp4
Crie uma folha de contato por clipe (um quadro a cada 2 s) e VEJA-a com a ferramenta Read para saber o que há em cada tomada:
ffmpeg -y -i raw/CLIPE.mp4 -vf "fps=1/2,scale=320:-1,tile=4x3" -frames:v 1 work/thumbs/CLIPE.jpg
Marque cada momento utilizável: tipo de tomada (aberta / média / close-up / detalhe), assunto, movimento, qualidade (nítido, estável, bem iluminado) e se é capaz de câmera lenta (fonte ≥ 50 fps).
4. Construir a história (plano de tomadas)
Estruture cada reel como:
- Gancho (0–2 s) — a tomada mais impactante. Sem logotipo ou introdução de texto.
- Construção — detalhes e antecipação (close-ups, câmera lenta).
- Momento herói — na maior batida / drop da música.
- Emoção / recompensa — reações, pessoas, celebração.
- Saída (últimos 2–3 s) — tomada aberta limpa, texto ou logotipo opcional, fade da música.
Modelo de entrega de carro (adaptar às filmagens): exterior aberto → close-up do logotipo → detalhes da roda/farol → família chegando (câmera lenta) → revelação da capa (no drop) → entrega das chaves → reações/sorrisos → interior + volante → bolo / guirlanda / pooja → primeira saída (aberta, saída).
Regras: varie os tamanhos das tomadas (nunca duas abertas seguidas), mantenha cada tomada entre 0,5 e 2,5 s, use câmera lenta apenas para tomadas emocionais ou de revelação, corte em movimento sempre que possível.
5. Detecção de batidas
# work/beats.py
import librosa, json, sys
y, sr = librosa.load(sys.argv[1])
tempo, frames = librosa.beat.beat_track(y=y, sr=sr)
beats = librosa.frames_to_time(frames, sr=sr).tolist()
onset = librosa.onset.onset_strength(y=y, sr=sr)
json.dump({"tempo": float(tempo), "beats": beats}, open("work/beats.json", "w"), indent=1)
print(f"tempo {float(tempo):.1f} BPM, {len(beats)} batidas")
Corte nas batidas (cada batida para seções rápidas, a cada 2ª ou 4ª batida para seções lentas). Encontre o drop (maior salto de energia) e coloque a tomada herói ali.
6. Escrever a lista de edição work/edl.json
{
"output": {"w": 1080, "h": 1920, "fps": 30},
"music": {"file": "music/track.mp3", "start": 12.0, "fade_out": 1.5},
"grade": {"lut": "luts/laranja_azulado.cube", "vignette": true},
"shots": [
{"id": 1, "src": "raw/C0001.mp4", "in": 4.20, "dur": 1.40, "speed": 1.0, "crop_x": "center", "note": "gancho – carro aberto"},
{"id": 2, "src": "raw/C0007.mp4", "in": 10.0, "dur": 1.00, "speed": 0.5, "crop_x": "center", "note": "roda câmera lenta"}
],
"transitions": [{"after_shot": 4, "type": "fade", "dur": 0.3}],
"text": [{"text": "Bem-vindo ao Lar", "start": 18.0, "end": 21.0}]
}
dur é o comprimento na linha do tempo. Com speed 0.5, o intervalo de origem usado é dur × speed segundos. Mostre este plano ao usuário como uma tabela simples (tomada, tempo, descrição) antes de renderizar.
7. Renderizar cada tomada como um segmento uniforme
Cada segmento deve ter resolução, fps, formato de pixel idênticos e sem áudio, para que sejam unidos de forma limpa:
# fonte paisagem → corte 9:16, velocidade, correção de cor
ffmpeg -y -ss IN -t SRC_DUR -i raw/CLIPE.mp4 -an -vf "\
setpts=PTS/VELOCIDADE,\
scale=-2:1920,crop=1080:1920,\
fps=30,\
lut3d=luts/laranja_azulado.cube,\
eq=contrast=1.06:saturation=1.10,\
vignette=PI/5,\
format=yuv420p" \
-c:v libx264 -crf 16 -preset medium work/seg_01.mp4
SRC_DUR = dur × speed. Para câmera lenta, use uma fonte de alta fps; eviteminterpolatea menos que solicitado (lento e com artefatos).- Fonte vertical: use
scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920. - Sem LUT disponível: use
eq=contrast=1.08:saturation=1.15:gamma=0.98maiscurves=preset=increase_contrastpara um visual cinematográfico. - Barras cinematográficas opcionais NÃO são usadas em reels 9:16.
8. Juntar segmentos
Sem transições — demuxer concat:
printf "file 'seg_%02d.mp4'\n" 1 2 3 ... > work/list.txt
ffmpeg -y -f concat -safe 0 -i work/list.txt -c copy work/video.mp4
Com uma transição entre dois segmentos, use xfade (offset = comprimento do primeiro clipe − duração da transição):
ffmpeg -y -i work/seg_04.mp4 -i work/seg_05.mp4 -filter_complex \
"[0][1]xfade=transition=fade:duration=0.3:offset=1.2,format=yuv420p" work/seg_04_05.mp4
Cada transição encurta a linha do tempo pela sua duração — verifique novamente o alinhamento com as batidas.
9. Música, texto, exportação final
ffmpeg -y -i work/video.mp4 -ss MUSIC_START -i music/track.mp3 -filter_complex "\
[1:a]afade=t=in:d=0.3,afade=t=out:st=FADE_START:d=1.5,loudnorm=I=-14:TP=-1:LRA=11[a];\
[0:v]drawtext=fontfile=FONTE.ttf:text='Bem-vindo ao Lar':fontsize=72:fontcolor=white:\
x=(w-text_w)/2:y=h*0.72:enable='between(t,18,21)':alpha='if(lt(t,18.4),(t-18)/0.4,1)'[v]" \
-map "[v]" -map "[a]" -shortest \
-c:v libx264 -crf 18 -preset slow -profile:v high -pix_fmt yuv420p -r 30 \
-c:a aac -b:a 192k -movflags +faststart out/reel_v1.mp4
Encontre um arquivo de fonte na máquina para drawtext (ou pergunte). Mantenha o texto mínimo, dentro da área segura (evite os 15% superiores e 25% inferiores, onde fica a interface do Instagram).
10. Verificação de qualidade (sempre)
ffprobe out/reel_vN.mp4→ 1080×1920, 30 fps, H.264, AAC, duração conforme planejado.- Folha de contato do reel final (
fps=2,scale=270:-1,tile=6x5) e visualize-a: sem quadros pretos, sem cortes errados (cabeças cortadas), cor consistente. - Verifique o volume e se a tomada herói cai no drop.
- Relate ao usuário: duração, número de tomadas, caminho do arquivo e qualquer coisa sobre a qual você não tinha certeza.
11. Revisões
Nunca recomece. Edite work/edl.json (troque uma tomada, altere in/dur, velocidade, texto, correção de cor), re-renderize apenas os segmentos alterados, junte e exporte como a próxima versão (reel_v2.mp4). Mantenha as versões antigas para que o usuário possa comparar.