Editor de vídeo por cliente
Motor e fluxo para editar como um editor humano: entender o material, cortar com precisão, aplicar o visual do cliente,
verificar e entregar. O motor não tem estilo próprio: tudo o que é visual vem de clientes/<CLIENTE>/look.py.
SKILL_DIR = pasta desta skill. Ferramentas: engine/reel.py, tools/{takes.py, words.py, media.sh},
modelos em templates/, looks de partida em looks/.
Requisitos (verificar na primeira vez; instalar o que faltar)
ffmpeg,python3,node/npx· macOS:avconvertesips(vêm com o sistema) para HDR→SDR e fotos HEIC.- HyperFrames (renderização e biblioteca de SFX):
npx hyperframes skills update general-video(instala tambémmedia-use). - watch (ver/transcrever vídeos e baixar links do Instagram/TikTok/YouTube com yt-dlp): skill
watchdo github.com/bradautomates/claude-video, motor local WhisperX (gratuito):setup.py --engine locale--backend whisperx. - whisper CLI (janelas de verificação):
uv tool install --python 3.12 openai-whisper --with setuptools. - MFA (alinhamento de palavras ±20 ms):
brew install --cask miniforge,conda create -n mfa -c conda-forge montreal-forced-aligner -y,conda run -n mfa mfa model download acoustic portuguese_mfae… dictionary portuguese_mfa(outro idioma: seu modelo).
Estrutura de pastas (base de trabalho, ex.: ~/Documents/VIDEOS/)
clientes/<CLIENTE>/
├── estilo.md guia do cliente (templates/estilo.md) — é lido SEMPRE antes de editar
├── look.py o estilo traduzido para opções do motor (de looks/nativo.py ou looks/dados.py)
├── refs/ vídeos de referência + folhas de frames + análise
├── marca/ logo, cores, fontes, música própria
└── projetos/<AAAA-MM-DD_nome>/
├── crudo/ material do usuário — NUNCA é modificado nem apagado
├── broll/ tomadas de apoio (opcional)
├── guion.md roteiro ou notas (opcional; se presente, tem precedência sobre estilo.md para este projeto)
├── trabalho/ media/ (convertida), mfa/, gt/, e uma pasta por vídeo com config.py + takes.json
└── final/ apenas entregáveis: <cliente>_<tema>_v1.mp4 · correções = v2, v3 sem apagar a anterior
O usuário não cria pastas: ele diz "novo projeto de , o material está em " e aqui se cria
projetos/<data_nome>/ e se move o material bruto (perguntar antes se estiver fora da base e ele não quiser mover).
Fluxo
0 · Cliente novo → analisar referências e escrever estilo.md
- Baixar/ler as referências (links com
watch, que usa yt-dlp) pararefs/. Ideal ~5. - Para cada uma medir: gancho (primeiros 3 s), cortes/min (
ffmpeg -vf "select='gt(scene,0.3)',showinfo"→ contar), legendas (fonte ou a gratuita mais parecida, tamanho, posição, cor, destaques, animação), cor/look, cartões e animações, som (música, SFX, voz), enquadramento, estrutura, CTA. Folha de frames:fps=16/dur,scale=270:480,tile=8x2. - Escrever
estilo.md(modelo) apenas com padrões vistos em ≥ 2 referências; separar medido de inferido; não copiar frases nem marcas alheias. Se as referências se contradisserem, perguntar qual priorizar. - Criar
look.pya partir do look de partida mais próximo e ajustá-lo ao guia. Mostrar guia + stills de teste e aguardar aprovação antes de editar.
1 · Entender o material bruto
- Ler
estilo.mdeguion.md. Testar cada arquivo (ffprobe: duração, rotação,color_transfer). watchsobre cada bruto comWATCH_WHISPERX_LANGUAGE=pte--out-dir trabalho/watch: o que é dito, quais tomadas servem, retomadas, o que NÃO cortar. Essa transcrição é a única completa: é reutilizada para MFA.- Cruzar com o roteiro: quais partes do roteiro não foram gravadas ou foram improvisadas → avisar o usuário.
- Vários clipes curtos sem voz (eventos): folha de frames por clipe, classificar por tema e propor agrupamentos (um vídeo por tema + soltos + um resumo geral) antes de editar.
2 · Preparar mídia
media.sh video <bruto> trabalho/media/<nome>.mp4 [vertical|horizontal]— converte HDR (iPhone/DJI) para SDR em uma única passada, keyframes a cada 1 s, 30 fps. Não recomprimir mais vezes: cada passada perde detalhe.- Fotos:
media.sh foto <foto> trabalho/media/<nome>.mp4 2.5. Áudio para alinhar:media.sh audio.
3 · Alinhar palavras (vídeos com voz)
corpus/a.wav+corpus/a.txt(texto simples do watch) →conda run -n mfa mfa align --clean <corpus ABSOLUTO> portuguese_mfa portuguese_mfa <saída ABSOLUTA>(caminhos absolutos ou falha; sem--beam).words.py textgrid … words.jsonewords.py show words.json.- Palavras com
~(duram > 1 s) escondem pausas ou retomadas; lacunas longas sem texto podem ser retomadas que o watch não transcreveu. Verificar com janela isolada: cortar 3–15 s do áudio,whisper --model small --language pt --word_timestamps True,words.py whisper … <offset>. MFA pode se desviar segundos onde houve ruídos ou retomadas.
4 · Selecionar tomadas → takes.json → takes.py
- Para cada frase, escolher a melhor tomada (normalmente a última); remover retomadas, arranques falsos, muletas, instruções ao editor ("este quero que seja outro vídeo") e o que não serve ao objetivo. Cumprir a duração máxima.
- Spans por início de palavra:
(início da 1ª, início da última + 0.2). Se o fim cair antes do início da última palavra, a come.word_fixcorrige palavras que o MFA posicionou mal (com tempos da janela isolada). - Texto:
phrases/wordscorrigem o que o ASR ouviu mal (nomes, marcas: "Claudio" não "Claudia", "IA" não "ela"). python3 $SKILL_DIR/tools/takes.py trabalho/<video>/takes.json trabalho/<video>→ imprime duração e texto final. Ler o texto completo: que não falte a última palavra de nenhum trecho nem sobrem palavras cortadas.
5 · Montar o vídeo
trabalho/<video>/:config.py(detemplates/config.py),media → ../media(symlink),media.sh sfx trabalho/<video>,hyperframes.jsonmínimo ({"paths": {"assets": "assets"}}).- Em
edit(e): cartões/POV/CTA, b-roll e sons ancorados a palavras (e.word_t(None, "palavra")). Cartões nas bordas: com zoom o rosto se alarga. Um evento visível a cada ≤ 3 s (o motor insere auto-punches se faltar). python3 $SKILL_DIR/engine/reel.py trabalho/<video>→npx hyperframes check trabalho/<video>(0 erros; os avisos de "arquivo grande / trilha densa / aninhado" são normais neste motor).
6 · Revisar antes de renderizar
npx hyperframes snapshot trabalho/<video> --at <t1,t2,…> --no-end -o <caminho ABSOLUTO>em cada cartão, gancho e CTA. Revisar: nada tapa o rosto, textos não quebram feio, cores corretas, legendas legíveis.- Mostrar stills ao usuário e aguardar aprovação (a menos que o estilo já esteja aprovado e ele diga "renderiza").
7 · Render e entrega
npx hyperframes render --quality delivery -o …/raw.mp4dentro detrabalho/<video>→media.sh final raw.mp4 final/<cliente>_<tema>_v1.mp4(−14 LUFS). Apagar apenas oraw.mp4intermediário que acabou de ser criado.- Verificar com
watch --detail transcript: texto completo e sem repetições. Se o início "faltar", revisar os primeiros 3 s com whisper antes de concluir (a transcrição completa às vezes omite o início).
Lições (não repetir)
- HDR sem converter fica deslavado; converter com
avconvertuma única vez. - Gravar em 4K se houver zooms: 1080p ampliado 13–22 % fica suave. Avisar o cliente.
- Uma frase corrigida com mais palavras não pode dividir o mesmo tempo: legenda de duração 0 fica grudada.
- Emojis em texto de tela nem sempre renderizam: evitá-los.
snapshot -ocom caminho relativo escreve junto ao projeto: usar caminhos absolutos.- Mesmo arquivo usado em duas partes do vídeo → chaves distintas em
takes.json(ids únicos). - Não enviar a biblioteca de SFX para nenhum repositório (licença Pixabay do media-use): é copiada por projeto com
media.sh sfx. - Correções do cliente sobre um único vídeo (ex.: "sem sons no 07") vão em seu
config.py(SFX = {"card": None, "broll": None, "cut": None}esfx: Nonenos cartões), não editando oindex.html(perde-se ao reconstruir).