Video Edit
Fork de browser-use/video-use (MIT): whisper.cpp local em vez de ElevenLabs, uma porta de validação antes de cada renderização, legendas Hyperframes em vez de subtítulos libass e reenquadramento de canvas para variantes de anúncios sociais.
Princípio
- LLM raciocina a partir da transcrição bruta + visuais sob demanda. O único artefato derivado que vale a pena manter é uma transcrição compactada em nível de frase (
takes_packed.md). Todo o resto — marcação de vícios de linguagem, detecção de retakes, classificação de tomadas, pontuação de ênfase — você deriva no momento da decisão. - Áudio é primário, visuais seguem. Os candidatos a corte vêm de limites de fala e lacunas de silêncio. Aprofunde-se nos visuais apenas nos pontos de decisão.
- Pergunte → confirme → execute → itere → persista. Nunca toque no corte até que o usuário tenha confirmado a estratégia em linguagem natural.
- Generalize. Não presuma que tipo de vídeo é este. Observe o material, pergunte ao usuário e então edite.
- Liberdade artística é o padrão. Cada valor específico, predefinição, fonte, cor, duração, estrutura de tom e técnica neste documento é um exemplo prático de um vídeo comprovado — não uma obrigação. Leia-os para entender o que é possível e por que cada um funcionou. Depois, faça suas próprias escolhas de gosto com base no que o material realmente é e no que o usuário realmente deseja. As únicas coisas que você DEVE fazer estão na seção Regras Rígidas abaixo. Todo o resto é seu.
- Invente livremente. Se o material exigir uma técnica não descrita aqui — tela dividida, picture-in-picture, cartões de identificação de terço inferior, cortes de reação, rampas de velocidade, congelamento de quadro, crossfades, cortes de correspondência, L-cuts, J-cuts, rampas de velocidade sobre respiração, o que for — construa-a. Os auxiliares são ffmpeg e PIL. Eles podem fazer qualquer coisa que o formato suporte. Não espere permissão.
- Verifique sua própria saída antes de mostrá-la ao usuário. Se você não enviaria, não apresente.
Regras Rígidas (correção de produção — inegociáveis)
Estas são as coisas onde o desvio produz falhas silenciosas ou saída quebrada. Não são gosto, são correção. Memorize-as.
- As legendas são aplicadas por ÚLTIMO na cadeia de filtros, após todas as sobreposições. Caso contrário, as sobreposições escondem as legendas. Falha silenciosa.
- Extração por segmento → concatenação lossless
-c copy, não filtro de passagem única. Caso contrário, você codifica duas vezes cada segmento quando as sobreposições são adicionadas. - Fades de áudio de 30ms em cada limite de segmento (
afade=t=in:st=0:d=0.03,afade=t=out:st={dur-0.03}:d=0.03). Caso contrário, estalos audíveis em cada corte. - Sobreposições usam
setpts=PTS-STARTPTS+T/TBpara deslocar o quadro 0 da sobreposição para o início de sua janela. Caso contrário, você vê o meio da animação durante a janela de sobreposição. - Legendas usam deslocamentos de linha do tempo de saída:
output_time = palavra.inicio - segmento.inicio + segmento.offset, onde cada segmento dura seu comprimento de quadro inteiro (captions.pyfaz isso). Caso contrário, as legendas desalinham após a concatenação do segmento. - Nunca corte dentro de uma palavra. Ajuste cada borda de corte para um limite de palavra da transcrição.
validate_edl.py --fixfaz isso mecanicamente. - Acrescente padding em cada borda de corte. Janela de trabalho: 30–200ms. As bordas das palavras já estão ajustadas ao envelope de áudio, mas o padding absorve o que resta. Mais apertado para ritmo acelerado, mais solto para cinematográfico.
- Apenas ASR (Reconhecimento Automático de Fala) literal em nível de palavra. Nunca modo SRT/frase (perde dados de lacunas de submilissegundos). Nunca preenchimentos normalizados (perde sinal editorial).
transcribe.pyinstrui o whisper a manter "um"/"uh" — não remova a instrução. - Armazene em cache as transcrições por origem. Nunca retranscreva a menos que o próprio arquivo de origem tenha mudado.
- Subagentes paralelos para múltiplas animações. Nunca sequencial. Gere N de uma vez através da ferramenta
Agent; o tempo total de parede ≈ o mais lento. - Confirmação da estratégia antes da execução. Nunca toque no corte até que o usuário tenha aprovado o plano em linguagem natural.
- Todas as saídas da sessão em
<videos_dir>/edit/. Nunca escreva dentro do diretório da skill. - Valide antes de cada renderização.
validate_edl.py <edl> --fix, então renderize apenas no código de saída 0. Ele detecta ids de origem inventados, tempos após o final de um arquivo, cortes no meio da palavra, arquivos de sobreposição ausentes e sobreposições que excedem o corte — os modos de falha que as listas de edição escritas por LLM realmente têm. - Legendas são uma camada Hyperframes, não subtítulos queimados. O ffmpeg do Homebrew não tem libass, então
subtitlesno EDL falha. Usecaptions.py;render.pycompõe o WebM das legendas acima de cada sobreposição. - Ids de origem são stems de arquivo. Em
sources, a chave deve ser o nome do arquivo de vídeo sem extensão (take_Bparatake_B.mp4), ou<stem>.track<N>quando transcrito com--audio-track N— é assim que as transcrições são encontradas. O validador erra em uma incompatibilidade quando as legendas estão ativadas. - Uma taxa de quadros por renderização. Se você passar
--fpspararender.py, passe o mesmo--fpsparavalidate_edl.pyecaptions.py. Os intervalos são arredondados para quadros inteiros para que as legendas nunca se desviem.
Todo o resto neste documento é um exemplo prático. Desvie sempre que o material exigir.
Layout do diretório
A skill reside em seu próprio diretório (auxiliares + modelos próximos a este arquivo). A filmagem do usuário fica onde ele a colocar. Todas as saídas da sessão vão para <videos_dir>/edit/.
<videos_dir>/
├── <arquivos de origem, intocados>
└── edit/
├── project.md ← memória; anexado a cada sessão
├── takes_packed.md ← transcrições em nível de frase, a principal visão de leitura do LLM
├── edl.json ← decisões de corte (edl_9x16.json, edl_1x1.json … para variantes)
├── transcripts/<nome>.json ← transcrições em cache do whisper.cpp (nível de palavra + silêncios)
├── captions_<stem_edl>/ ← composição de legendas Hyperframes + captions.webm
├── animations/slot_<id>/ ← fonte de animação + renderização + raciocínio
├── clips_graded/ ← extrações por segmento com gradação + fades
├── downloads/ ← saídas do yt-dlp
├── verify/ ← quadros de depuração / PNGs de linha do tempo
├── preview.mp4
└── final.mp4
Configuração
install.sh / setup.sh instala tudo (pacotes Homebrew, .venv, modelo whisper, Hyperframes + Chrome). Na inicialização a frio, apenas verifique — e se .venv estiver faltando ou um auxiliar falhar em uma importação ou ferramenta ausente, execute <diretório_desta_skill>/setup.sh (é idempotente) antes de qualquer outra coisa:
PY=<diretório_desta_skill>/.venv/bin/pythonexiste. Execute cada auxiliar com$PY, nunca o python do sistema (falta numpy/Pillow/OpenCV).ffmpeg,ffprobe,whisper-clino PATH, e um modelo ggml whisper. Padrão:~/.claude-video-vision/models/ggml-large-v3-turbo.bin; substitua comVIDEO_EDIT_WHISPER_MODEL.- Node.js 22+ para Hyperframes. Sempre chame a versão fixada:
npx --yes [email protected] …. yt-dlpe Manim apenas no primeiro uso. Esta skill vendeskills/manim-video/; leia seu SKILL.md ao construir um slot Manim.- Sem chaves de API. Nada sai da máquina, exceto o download único do npm do Hyperframes.
Os auxiliares residem em helpers/ próximo a este SKILL.md. Resolva seus caminhos relativos ao diretório que contém este arquivo.
Auxiliares
Todos tomam $PY helpers/<nome>.py ….
transcribe.py <video>— whisper.cpp local, nível de palavra, preenchimentos mantidos, bordas de palavras ajustadas ao envelope de áudio, silêncios listados. Em cache por origem (executa novamente apenas se o arquivo mudou).--language enignora detecção;--audio-track Npara gravações multi-track.transcribe_batch.py <videos_dir>— cada vídeo em uma pasta, um de cada vez (whisper já satura a GPU).pack_transcripts.py --edit-dir <dir>—transcripts/*.json→takes_packed.md(nível de frase, quebra em silêncio ≥ 0.5s; diminua--silence-thresholdpara 0.3 para falantes rápidos).timeline_view.py <video> <inicio> <fim>— tira de filme + PNG de forma de onda. Aprofundamento visual sob demanda. Não é uma ferramenta de varredura — use-a em pontos de decisão, não constantemente.validate_edl.py <edl.json> [--fix]— a porta antes de cada renderização (Regra Rígida 13).--fixajusta bordas a lacunas de palavras, adiciona padding a elas (--pad-in,--pad-out), arredonda intervalos para quadros inteiros, recalculatotal_duration_s, mantémedl.json.bak. Avisos sobre bordas com < 30ms de silêncio sobrevivem a--fix: esses cortes ficam onde as palavras se tocam — mova-os para uma pausa real.captions.py <edl.json>— legendas de palavras em linha do tempo de saída como uma composição Hyperframes →captions.webmtransparente, define a chavecaptionsdo EDL. Flags de estilo:--accent,--color,--top,--size,--font,--case,--words,--no-pop.render.py <edl.json> -o <saida>— extração por segmento (quadro exato, HDR→SDR, reenquadramento de canvas, gradação, fades) → concatenação lossless → sobreposições (PTS deslocado) → legendas → loudnorm.--previewpara controle de qualidade,--draftapenas para verificações de corte.reframe.py <edl.json> [--apply]— detecção facial OpenCV (YuNet) em cada intervalo →crop_x/crop_yque mantêm o orador centrado com espaço nocanvasdo EDL. Execute apósvalidate_edl.py --fixsempre que umcanvasalterar a proporção. Ele sinaliza intervalos onde o rostoMOVEdemais para um corte estático (divida-os) e intervalos comsem rosto(escolha o corte você mesmo)."crop_lock": trueem um intervalo protege um corte manual.scenes.py <video>— detecção de mudança de cena OpenCV mais flagsDARK/BLURRYpor cena →edit/shots/<stem>.json. Use-o para filmagens que a transcrição não consegue estruturar: b-roll, fotos de produtos, montagens, exportações multicâmera, clipes silenciosos. Os limites de cena são pontos de corte visuais limpos; cenas sinalizadas raramente são utilizáveis em um anúncio.grade.py <in> -o <saida>— cadeia de filtros ffmpeg para gradação. Predefinições +--filter '<raw>'para personalizado.
Para animações, crie <edit>/animations/slot_<id>/ com Bash e gere um subagente através da ferramenta Agent.
O processo
-
Inventário.
ffprobeem cada origem.transcribe_batch.pyno diretório. Para origens com pouco ou nenhum discurso (b-roll, fotos de produtos), executescenes.pypara obter suas cenas. Leia as linhasQC:que ele imprime (também sobqcem cada transcrição): palavras comprimidas para ≤20ms ou começando dentro de um silêncio têm tempos não confiáveis — verifique qualquer corte próximo a elas comtimeline_viewantes de usá-lo.- Múltiplos oradores (chamadas, entrevistas): não há rótulos de orador. Infira turnos a partir do conteúdo (perguntas vs respostas), depois confirme cada frase que planeja manter com
timeline_view(em chamadas de vídeo, o tile do orador ativo mostra quem fala). Se a chamada foi gravada com uma pessoa por faixa de áudio, transcreva cada faixa com--audio-track N.pack_transcripts.pypara produzirtakes_packed.md. Amostre um ou doistimeline_views para uma primeira impressão visual.
- Múltiplos oradores (chamadas, entrevistas): não há rótulos de orador. Infira turnos a partir do conteúdo (perguntas vs respostas), depois confirme cada frase que planeja manter com
-
Pré-varredura para problemas. Uma passagem sobre
takes_packed.mdpara anotar deslizes verbais, erros de fala óbvios ou frases a evitar. Lista simples, alimente o briefing do editor. -
Converse. Descreva o que você vê em linguagem natural. Faça perguntas moldadas pelo material. Colete: tipo de conteúdo, duração/proporção alvo, direção estética/de marca, sensação de ritmo, momentos a preservar, momentos a cortar, preferências de animação e gradação, necessidades de legenda. Não use uma lista de verificação fixa — as perguntas certas são diferentes a cada vez.
-
Proponha estratégia. 4–8 frases: forma, escolhas de takes, direção de corte, plano de animação, direção de gradação, estilo de legenda, estimativa de duração. Aguarde confirmação.
-
Execute. Produza
edl.jsonatravés do briefing do subagente editor. Aprofunde-se emtimeline_viewem momentos ambíguos. Construa animações em subagentes paralelos. Executevalidate_edl.py --fixaté sair com 0. Depoiscaptions.pyse legendas foram solicitadas (as legendas são construídas a partir dos intervalos finais, então execute novamente após qualquer alteração de intervalo). -
Visualização.
validate_edl.py(sem--fix) →render.py --preview. -
Autoavaliação (antes de mostrar ao usuário). Execute
timeline_viewna saída renderizada (não nas origens) em cada limite de corte (janela ±1.5s). Verifique cada imagem para:- Descontinuidade visual / flash / salto no corte
- Pico de forma de onda no limite (estalo de áudio que escapou do fade de 30ms)
- Legenda escondida atrás de uma sobreposição (violação da Regra 1)
- Sobreposição desalinhada ou mostrando quadros errados (violação da Regra 4)
Também amostre: primeiros 2s, últimos 2s e 2-3 pontos médios — verifique consistência da gradação, legibilidade das legendas, coerência geral. Execute
ffprobena saída para verificar se a duração corresponde à expectativa do EDL.Meça o áudio, não presuma:
ffmpeg -i out.mp4 -af ebur128=peak=true -f null -para loudness integrada e pico verdadeiro, mais RMS por seção (diálogo, apenas música, cartão final). Um cartão final 15 dB abaixo do diálogo, ou efeitos mais altos que a fala, é um bug. Você não pode ouvir: diga isso e relate os números.Para qualquer coisa que o usuário publicará (lançamento, promoção, anúncio), também gere um subagente crítico com o arquivo renderizado, o EDL e quaisquer vídeos de referência que o usuário forneceu. Instrua-o a criticar, não a elogiar: um veredito, problemas classificados com timecodes e evidências (quadros, níveis), e as 5 correções a fazer primeiro. Olhos frescos captam o que o autor parou de ver — linhas de payoff cortadas, memes de 0.5s, texto de 28px ilegível em tamanho de telefone.
Se algo falhar: corrija → re-renderize → re-avalie. Limite a 3 passagens de autoavaliação — se os problemas persistirem após 3, sinalize-os ao usuário em vez de entrar em loop infinito. Apenas apresente a visualização uma vez que a autoavaliação passe.
-
Itere + persista. Feedback em linguagem natural, replaneje, re-renderize. Nunca retranscreva. Renderização final após confirmação. Anexe a
project.md.
Técnicas de corte
- Áudio primeiro. Cortes candidatos a partir de limites de palavras e lacunas de silêncio.
- Preserve picos. Risadas, punchlines, batidas de ênfase. Estenda após punchlines para incluir reações — a risada É a batida.
- Transições de orador se beneficiam de ar entre as falas. Valores comuns: 400–600ms. Menos para ritmo acelerado, mais para cinematográfico. Decisão de gosto.
- Risadas e reações não são marcadas (whisper não emite eventos de áudio). Encontre-as como trechos sem fala, mas altos, nas formas de onda
timeline_view; estenda após elas — a risada É a batida. - Lacunas de silêncio são candidatas a corte. Corte em um silêncio de 200–500ms. Menos em ritmo acelerado, mais pausas em tomadas contemplativas. Risos, respirações e reações em grupo são especialmente bons para cortar: encontre o silêncio mais próximo após a reação terminar e corte ali.