Edição de vídeo (gravação de tela / OBS / palestra)
Kit de scripts: scripts/ neste skill (prep.sh, transcript_txt.py, ocr_scan.py,
cam_flags.py, df_enhance.py, build_edl.py, render.py, verify_output.py,
chapters.py, overview.py, job.example.json, selftest.sh). Execute-os a partir de uma cópia em
<workdir>/scripts/ para que um trabalho nunca dependa do diretório do skill. scripts/selftest.sh prova
uma instalação de ponta a ponta em alguns minutos.
Entradas
<src>: a gravação, geralmente o arquivo mais recente de~/Desktop/*.mov(nomenclatura OBSYYYY-MM-DD HH-MM-SS.mov). Se houver várias gravações recentes, confirme qual delas ANTES de iniciar o longo pipeline - editar o vídeo errado desperdiça uma hora.<target_minutes>: pergunte se não for informado; típico 20-30 a partir de uma fonte de 45-90 min.<workdir>: diretório temporário novo, ex.:/tmp/<session>/edit.- Toolchain:
ffmpeg6+,python3,mlx_whisper, DeepFilterNet3, Pillow/numpy/soundfile, Apple Vision (pyobjc-framework-Vision/-Quartz).
Passos
- Reconhecimento, nunca toque na fonte.
ffprobe <src>(resolução, fps, áudio). Trabalhe apenas com cópias/extratos em<workdir>. - Preparação.
prep.sh "<src>" $W:orig48.wav,mono16.wav,frames/(1 por 2 s),camall/(recorte da webcam a 1 fps, geometria derivada automaticamente da resolução),sheet_overview.jpg,silences_raw.txt(apenas diagnóstico) etranscript.json(mlx_whisper large-v3-turbo, timestamps por palavra, ~4 min). O Whisper continua rodando em segundo plano após a preparação retornar - iniciedf_enhance.py orig48.wav df_enhanced.wav(DeepFilterNet3, ~6 min CPU) AGORA, é independente. - Leia a transcrição inteira (3 blocos via
transcript_txt.py ... --from/--to). Escreva as faixas a manter (em segundos da fonte) emjob.json -> keep. A remoção de silêncio é menor (~2 de 47 min); os minutos reais vêm das decisões de conteúdo. O Whisper se autoinforma: uma frase repetida 10+ vezes ou execuções de segmento vazio = ar morto, corte isso. - Passagem de estática visual. "Nada acontecendo" é frequentemente visualmente estático, NÃO silencioso. Compare quadros a 0.5 fps: <1% de pixels alterados em uma janela de ~10 s = inativo; mescle execuções separadas por <=1 s de piscadas; exija >=4 s para cortar; 0.5 s de alças. Cursores piscando/spinners falsificam atividade - mascare ou aumente o limiar; verifique quadros intermediários para explosões de mudança-e-reversão. Digitação é ruído, não silêncio: as comportas usam RMS na faixa aprimorada (
pause.loud_db), nunca emsilencedetectbruto. - Abertura. Corte tudo antes do primeiro conteúdo real. Se o início for lento/ chato, comece na demonstração mais interessante; opcionalmente, abra com 1-2 clipes empolgantes e depois acelere a introdução. Nunca abra com papel de parede/preto - os primeiros 30 segundos picados parecem lixo.
- Varredura de vazamentos (executa enquanto você lê).
ocr_scan.py scanapósrunemframes/: IPv4/v6,*.ts.net, e-mails, chaves de API, material SSH. Passagem densa a 2 fps em cada faixa com muito terminal/config (ocr_scan.py dense src.mov dense 600:60 ...). Texto estático ->boxes(preenchimento sólido); saída de terminal em rolagem -> desfoque o painel inteiro (blurwindow +blur_regions, em pixels da fonte) para a janela - caixas por linha perdem texto entre amostras.127.0.0.1/localhostestão ok. Registre cada janela emjob.json. - Cortes de privacidade (webcam).
cam_flags.py(mão perto da boca via Vision) +cam_flags.py --sheet S:DURfolhas ampliadas a 2 fps de cada cluster sinalizado. Corte os momentos que o usuário não publicaria: mão no rosto durante uma pausa, sair da mesa, outra pessoa no quadro, segmentos de rosto em tela cheia. Poses de pensamento comuns e pequenos gestos estão ok. NUNCA corte no meio de uma frase por um gesto - encaixe no limite de frase mais próximo e anote o que foi perdido. - Cortes de timestamp do usuário são literais. "corte 0000 - 01:12" -> coloque em
job.cuts(oukeep), aplique exatamente, depois verifique o ritmo ao redor da emenda. - Master de áudio. Sanidade: correlação entre versão aprimorada e original > 0.95 (
df_enhance.pyimprime isso). Oaudio_chainpadrão é highpass 75, cortes/ aumento em torno de 220 Hz / 3.2 kHz / 9 kHz, de-esser, compressor 3:1; faça notch em qualquer tom persistente de ventilador adicionando um termoequalizer;render.pyfaz o loudnorm de duas passagens para -16 LUFS / -1.5 dBTP. O microfone não tocado permanece como faixa de áudio 2. - EDL + renderização.
build_edl.py->segments.json(pausas >0.7 s dentro das faixas mantidas encurtadas para 0.4 s; ajustadas ao framerate sondado; <0.3 s descartadas).render.py: codificaçõesh264_videotoolboxparalelas agrupadas, concatenação-c copy, multiplexação de ambas as faixas. É reiniciável por grupo - se um grupo falhar, corrija e execute novamente, grupos inalterados são pulados. Entregue 1080p a menos que seja solicitado o contrário (4K dobra o tempo de renderização para nada). - Verifique antes de entregar.
verify_output.pysai com código diferente de zero a menos que a contagem de quadros corresponda ao EDL, ambas as faixas de áudio correspondam à duração do vídeo e o OCR da saída a 4 fps em cada janela de redação encontre zero vazamentos. Também extraia quadros da saída em cada corte de privacidade e em 0:00-1:00 e OLHE para eles. Use--fullpara uma varredura de vazamentos em todo o arquivo quando o material for sensível. - Retranscreva o novo corte. A transcrição, as legendas e os capítulos devem corresponder à linha do tempo da SAÍDA, não à fonte - refaça o Whisper no corte (ou
chapters.py, que remapeia através do EDL) antes de escrever SRT/capítulos. Nunca envie tempos de SRT retirados da transcrição da fonte. - Metadados + entrega. Sem ser perguntado duas vezes: timestamps de capítulo (
chapters.py, >=3, primeiro em 0:00), 2-3 opções de título, ~30 tags com menos de 500 caracteres (+2 variantes de tag/descrição se solicitado), descrição, SRT por idioma (~42 caracteres/linha; multilíngue sob solicitação), tudo como texto simples. Miniatura via youtube-pack: leia as últimas 10 miniaturas do usuário para estilo; fundo branco/creme padrão + texto preto, sem rosto a menos que solicitado, logotipos/texto grandes e sem desordem. Em seguida, mova<output>.mp4(e SRTs/metadados) para~/Downloadseopeno arquivo / abra a pasta no aplicativo padrão.
Saídas
<Topic> - YYYY-MM-DD - edit.mp4(1080p, 2 faixas de áudio) em~/Downloads, aberto no aplicativo padrão.<workdir>:job.json,segments.json,group_bounds.json,vf_<n>.txt, logs de redação/privacidade.~/Downloads: SRTs,metadata.txt(títulos, descrição, tags, capítulos).- Opcional sob solicitação: subvídeos temáticos divididos da mesma fonte, cada um com seus próprios capítulos.
Compõe com
whisper/DFN3 (in-kit) -> video-edit (mp4 verificado em ~/Downloads) -> youtube-pack (thumbnail.png) -> upload no navegador para o YouTube Studio configurado como os outros vídeos do usuário.
Regras
- Nunca modifique a gravação original.
- O comprimento alvo é um alvo; se o conteúdo não encolher sem destruir a palestra, entregue um pouco acima e nomeie os próximos dois cortes.
- Corte digressões inteiras antes de reduzir mais pausas; mantenha conversas sobre hardware, demonstrações ao vivo, ressalvas honestas, o resumo.
- Sempre termine com: mover para ~/Downloads + abrir.
- Relate fielmente: você não pode ouvir o resultado - diga isso e aponte para a faixa 2.
- Áudio gravado separadamente (Discord/Craig) geralmente não existe; verifique Desktop/Downloads/iCloud/Voice Memos, se ausente, use o microfone do OBS e diga isso.
- Quando solicitado a liberar espaço: exclua rascunhos/variantes antigos não aceitos, mantenha a fonte e o final.
- Podcasts com várias pessoas: encontre as faixas de áudio CORRETAS (geralmente 2 de muitas), mapeie o áudio para o palestrante correto, alterne o vídeo com a pessoa falando, transições limpas.
- Nunca afirme que a edição está concluída porque a renderização terminou; apenas
verify_output.py+ quadros inspecionados visualmente resolvem isso.
Verificação
verify_output.pyimprime PASS (contagem de quadros, duas faixas de áudio, sem vazamentos nas janelas) e sai com código 0.- Quadros inspecionados visualmente em 0:00-1:00 e em cada corte de privacidade (
verify_output.py --sheet 0:60). - Verificação pontual da retranscrição SRT contra o corte.
ffprobeno arquivo entregue: duração, resolução, fps, 2 fluxos de áudio.
Falhas conhecidas
- Vídeo errado editado -> confirme que o mais recente/ tópico correspondem antes do pipeline.
- Legendas/capítulos na linha do tempo da fonte -> retranscreva após o corte (passo 12).
- Nome do host visível na saída -> texto em rolagem entre amostras de OCR; desfoque o painel inteiro, amplie a janela, depois OCR da saída.
- Silencedetect corta digitação/reprodução de vídeo -> use comporta no RMS do áudio aprimorado (
pause.loud_db), não apenas silêncio. - Abertura preta e picada -> verifique os quadros da saída 0:00-1:00, abra com conteúdo real.
- Prompt de sobrescrita
cp -i/ bloqueio TCC da sandbox para~/Downloads-> use/bin/cpcom sandbox desabilitada. - O filtro ffmpeg morre ("Cannot allocate memory") após cerca de 100 termos
between()-> menosrender_groups. - Cursor piscando conta como atividade na comparação de quadros -> mascare/ajuste o limiar, verifique quadros intermediários.
render.pyincompatibilidade de quadros -> ele se recusa a concatenar; leiarender_<n>.log(-ssantes de um quadro não-chave, decodificador quebrado).- Whisper ainda rodando quando você lê
transcript.json->transcript_txt.pyrelata segmentos vazios; aguardewhisper.logterminar.
Exemplos
- Palestra de 2026-09-02, 47 min -> 26 min: 32 faixas mantidas, 2 cortes de privacidade (9:52-9:58, 26:08-26:14), 2 janelas de desfoque + 1 caixa para um nome de host
*.ts.net, renderização ~2 h de relógio de parede, vazamento capturado apenas pelo OCR da saída. - Sessão de ensino de OBS de 2026-09-24: o usuário rejeitou o primeiro corte ("ruído de fundo, digitação, começo muito chato") -> removeu ruído de digitação, escolheu uma abertura melhor, refez as transcrições, depois corte literal
0:00-1:12, varredura de vazamentos, miniatura branca/creme com logotipos maiores, 2 variantes de metadados, movido para Downloads. - Podcast (2026-09-18): 1h40m de vídeo + 5 arquivos de áudio candidatos -> identificou as 2 faixas corretas por palestrante, mapeou voz para vídeo, 1080p, cortar cabeça, SRT + traduções para ES/AR/HI, timestamps de capítulo, miniatura com ambos os palestrantes, texto no topo, sem fundo preto.