Edição de papel (Paper Edit)
Arquivos brutos de câmera entram, corte bruto montado sai no Resolve. Em seu primeiro teste real: raw 14:17, saída 10:16, contra a edição manual do próprio criador de 10:32.
Divisão do trabalho: Claude faz o corte amplo, o criador faz o ajuste fino. Não tente entregar uma edição finalizada e não seja tão conservador que o criador tenha que refazer as partes óbvias.
Configuração: preencha estes campos
| Placeholder | O que é | Exemplo |
|---|---|---|
<FOOTAGE_DRIVE> | Onde o material bruto está, uma pasta por vídeo | /Volumes/MeuDriveDeTrabalho |
<LUT_PATH> | LUT opcional, relativo à pasta de LUTs do Resolve | MinhasLuts/SLog3-to-709.cube |
WHISPER_MODEL (env) | Arquivo de modelo whisper.cpp | padrão ~/.cache/whisper-models/ggml-small.en.bin |
RESOLVE_APP (env, opcional) | Caminho do app Resolve se não padrão | padrão /Applications/DaVinci Resolve/DaVinci Resolve.app |
Requisitos: ffmpeg, ffprobe, whisper-cli (whisper.cpp), Python 3, DaVinci Resolve com um servidor MCP Resolve que exponha execute_resolve_code.
Executando
Dir de trabalho: use o scratchpad da sessão, ex. <scratchpad>/paperedit. O diretório do skill abaixo é .claude/skills/paper-edit.
1. Encontre o material
O material bruto está na <FOOTAGE_DRIVE>, uma pasta por vídeo, geralmente com nomes soltos.
find "<FOOTAGE_DRIVE>" -maxdepth 4 -iname "*<palavra-chave>*" -not -path "*/.*"
Confirme a pasta com o usuário se mais de uma corresponder. Não copie os arquivos; o Resolve faz link para eles na unidade.
2. Transcreva cada clipe
bash <skill>/scripts/transcribe.sh "<FOOTAGE_DRIVE>/<pasta>" "<trabalho>"
Escreve <clipe>.json (nível de palavra), <clipe>.wav e clips.ndjson com durações. Cerca de 90s para 15 minutos de material. Pula clipes já processados, portanto é seguro reexecutar.
3. Leia a transcrição você mesmo
python3 <skill>/scripts/sentences.py "<trabalho>"
Leia tudo. Esta é a parte que não pode ser roteirizada. Um detector de frases repetidas foi testado e falhou mal: queria cortar 428 de 737 segundos, porque professores repetem frases de propósito ("aqui está o que funciona, aqui está o que não funciona").
4. Escreva a lista de cortes
<trabalho>/cuts.json, um objeto por remoção, tempos em segundos desde o início daquele clipe:
[{"clip":"C0002","start":32.58,"end":39.76,"why":"hesitação: 'o que percebi foi que até mesmo às vezes...'"}]
Corte estes:
- Apartes e falas para a câmera: "isso foi muito bom, não vou mentir", "essa câmera está prestes a morrer", "isso provavelmente vai ser um vídeo de sete minutos"
- Falsos começos, mantendo a última tentativa. Palestrantes frequentemente repetem uma frase duas vezes, melhor na segunda.
- Takes ruins do CTA. Geralmente há 3-4 no final; mantenha o último.
- Longos silêncios entre seções, ruídos entre colchetes (
[BLANK_AUDIO],(teclado clicando),(barulho de papéis)) - Frases abandonadas no meio e reconstruídas ("a razão pela qual eu não fazia isso era porque eu tinha medo, e...")
- Reinícios curtos dentro de uma frase, marcados por uma vírgula e uma cláusula repetida: "tudo que pedi em troca é uma avaliação simples e isso é, e adicionando a parte da avaliação..." Corte da cláusula abandonada até o reinício. São de 1 a 2 segundos e fáceis de ler.
- Os timings das palavras do Whisper variam cerca de 0,5s. Em um falso começo que repete as mesmas palavras ("eu amo chegar oferecendo, eu amo começar"), termine o corte no início do segundo "eu amo", não no final da primeira tentativa, ou uma palavra solta sobrevive.
- Inicie um corte no offset
toda palavra mantida, nunca no seufrom. Em um teste, um corte começou em 40,30 enquanto a palavra mantida ia de 40,19 a 40,92, então a última palavra do gancho foi cortada e teve que ser arrastada de volta manualmente. Imprima os offsets comfrom|topara a palavra anterior a cada corte. - Após uma longa sequência de
[BLANK_AUDIO], os timings não são confiáveis. O Whisper comprimiu as palavras da primeira tentativa de gancho após 30s de silêncio, e o corte deixou um fragmento de palavra como o primeiro segundo do vídeo. Quando um take começa após silêncio morto, verifique o nível de áudio (ffmpeg astats) para descobrir onde a fala realmente começa, em vez de confiar nos offsets de palavra.
Mantenha:
- Repetições deliberadas usadas para ritmo de ensino
- Digressões que ainda ensinam algo, a menos que o usuário diga o contrário
- Qualquer coisa sobre a qual você não tem certeza. Sinalize-a em seu resumo em vez de cortá-la.
5. Construa os segmentos
python3 <skill>/scripts/segments.py "<trabalho>"
Produz segments-v1.json (apenas cortes manuais), segments-v2.json (também reduz pausas acima de 0,50s para 0,22s) e cutlist.txt. Ajustáveis via env: MIN_GAP, KEEP_PAUSE, NOISE_DB.
Ele também remove blips sem fala: segmentos v2 com menos de 1s e sem áudio em nível de fala. São cliques de mouse e olhadas para o laptop, deixados como ilhas entre pausas reduzidas. Ajustáveis: BLIP_MAX, SPEECH_DB.
Leia cada linha join: no cutlist.txt antes de mostrar ao usuário. Ela mostra como a frase soa através de cada corte. Se a mesma frase aparecer em ambos os lados do |, o corte é muito curto.
Ambas as passagens são importantes. Com apenas os cortes manuais, o feedback foi "há grandes pausas ao longo do vídeo, especialmente no início." A redução de pausas foi o que levou de 11:32 para 10:16. Não abaixe KEEP_PAUSE abaixo de ~0,20s; começa a soar apressado.
6. Mostre a lista de cortes antes de construir
Cole o resumo: duração original, v1, v2, contagem de cortes e os cortes notáveis com motivos. O usuário veta o que quiser.
7. Construa no Resolve
Requer Preferências > Sistema > Geral > Scripting externo usando: Local (configurado uma vez, permanece). Não peça ao usuário para abrir o Resolve. Execute isto primeiro; ele inicia o Resolve se estiver fechado e espera até que a API responda:
bash <skill>/scripts/ensure_resolve.sh
Se expirar com o Resolve em execução, o scripting está desligado; esta é a única coisa para pedir ao usuário corrigir.
Escreva <trabalho>/params.json:
{"project":"<Nome do Vídeo> - AAAA-MM-DD","work":"<trabalho>",
"files":["<FOOTAGE_DRIVE>/<pasta>/C0001.MP4","..."],
"fps":23.976,"width":1920,"height":1080}
Em seguida, uma chamada execute_resolve_code:
PARAMS = "<trabalho>/params.json"
exec(open("<skill>/scripts/resolve_build.py").read())
Vários vídeos: construa um de cada vez, nunca como chamadas de ferramenta paralelas. O Resolve tem um projeto atual, então duas construções colidem. Uma vez, duas construções foram executadas juntas e uma v2 saiu vazia, mesmo que o script tenha reportado cada item adicionado. Após cada construção, verifique você mesmo a contagem de itens de cada linha do tempo.
Nomeie o projeto <Vídeo> - AAAA-MM-DD para que projetos com o mesmo nome nunca sejam confundidos. Ele cria um novo projeto, importa os clipes e constrói Paper Edit v1 e Paper Edit v2 (apertado). Nada existente é tocado. Este é um uso sancionado de execute_resolve_code; append_to_timeline não pode receber pontos de entrada/saída, então não há ferramenta alternativa. Mostre o código ao usuário na primeira vez em uma sessão.
Alternativa se o Resolve não puder ser acessado (execução em nuvem/agendada, ou ensure_resolve.sh falhou): escreva um FCPXML de elementos asset-clip, um por segmento, com start e duration em frames*1001/24000s, e deixe o usuário importá-lo. Mesmo resultado, um clique extra.
8. Entregue
Informe ao usuário que ambas as linhas do tempo existem, qual examinar primeiro (v2) e que v1 é a rede de segurança se v2 parecer cortada. Em seguida, pergunte se o corte está bloqueado, porque sobreposições vêm depois (veja video-overlays, se você o tiver).
9. Aproximações (terceira linha do tempo opcional)
Variação de enquadramento estático torna uma cabeça falante assistível. A API do Resolve não tem acesso a keyframes, então aproximações lentas são impossíveis de roteirizar; enquadramento estático por clipe ("de vez em quando um dos clipes está um pouco mais ampliado") é o que é possível.
Relacione cada mudança à transcrição, nunca a um temporizador. Uma versão baseada em temporizador parecia aleatória. Aproxime nas linhas de maior impacto ou onde um novo tópico começa, para que faça sentido.
Escreva <trabalho>/framing.json:
[{"clip":"C0002","at":361.40,"framing":"med","why":"DICA 3"},
{"clip":"C0002","at":371.80,"framing":"close","why":"'esta é a parte que importa'"}]
at é o início da frase de sentences.py. Em seguida python3 <skill>/scripts/punchins.py "<trabalho>" e defina "punchins": true em params.json. Ele divide um segmento onde quer que uma marca caia dentro dele, no ponto mais silencioso perto do início da frase, porque cabeças falantes frequentemente falam por muito tempo sem pausa e, caso contrário, a mudança atrasa.
Se o usuário editou manualmente a v2 no Resolve, a linha do tempo deles é o corte. Leia seus itens (GetLeftOffset/GetDuration, quadros x 1.001/24 = segundos) em segments-locked.json, execute com SEGMENTS=segments-locked.json, e adicione apenas v3 ao projeto existente com "timelines": ["v3"]. Mire em uma mudança a cada ~20-40s: aberto em cada novo tópico, médio para ensino, fechado na linha importante. O construtor insere um marcador azul em cada mudança nomeando o motivo, para que a lógica fique visível.
Enquadramentos: wide 1.00, med 1.11 (inclinação -12), close 1.21 (inclinação -24).
Se o usuário corrigiu a v2 enquanto a editava, a v3 é construída do zero apenas com o LUT, portanto copie a correção da v2 para a v3 imediatamente após construí-la:
src = v2.GetItemListInTrack("video", 1)[5] # qualquer item v2 corrigido
src.CopyGrades(v3.GetItemListInTrack("video", 1)) # funciona entre linhas do tempo; zoom/inclinação sobrevivem
Verifique com GetNodeGraph().GetToolsInNode(1) em cada item v3. Não use a rota da galeria (GrabStill + ExportStills para .drx): a exportação retorna False através da API. Se GrabStill foi usado, exclua o still para que a galeria fique limpa.
Lendo uma v2 bloqueada: GetLeftOffset() e GetDuration() fornecem quadros de origem. O primeiro segmento informa se o gancho foi cortado. Compare os segmentos bloqueados com segments-v2.json e anote o que mudou, para calibrar a próxima edição.
10. Cor
Defina "lut": "<LUT_PATH>" em params.json para aplicá-lo a cada clipe no nó 1. Se a câmera grava em perfil log (ex. S-Log3), o material sem correção parece plano e cinza, então um LUT vale a pena. A API não pode adicionar um segundo nó; para uma correção multinó, corrija um clipe manualmente e propague com CopyGrades.
11. Fotos sobre a fala (opcional)
Quando o palestrante fala sobre algo do qual tem imagens estáticas, coloque-as na V2 da v3, sobre fundo branco.
- Cartões, não uma apresentação de slides. Renderize PNGs 1920x1080 em branco puro: três retratos lado a lado (redimensionar para h840, gaps de 50px), dois retratos (h880, gap de 60px) ou uma paisagem (h900). Agrupe as fotos pelo que está sendo dito.
- Temporize cada cartão para o início de uma frase da transcrição bloqueada, e mude os cartões na próxima frase. Cerca de 2-5s por cartão. Permaneça nas fotos apenas enquanto elas estão sendo descritas.
- Importe-os como ProRes .mov de duração exata, não como imagens estáticas. Imagens estáticas chegam no Resolve com duração fixa de 2s e se sobrepõem. Nomes numerados (
card1.png,card2.png) importam como uma única sequência de imagens, então use nomes com palavras. Renderize comffmpeg -loop 1 -framerate 24000/1001 -i x.png -frames:v N -c:v prores_ks -profile:v 3. - Para um .mov,
AppendToTimelineprecisa deendFrame= a contagem de quadros (não contagem-1), ou cada cartão fica um quadro mais curto e o palestrante aparece entre os cartões. Passe"mediaType": 1para que nenhum áudio venha junto. - Nomeie a faixa "<Tópico> fotos", coloque os cartões em sua própria pasta no media pool, e nunca aplique o LUT a eles (já estão corrigidos).
- Mostre ao usuário uma folha de contato dos cartões no chat antes de colocá-los.
Fatos que vale a pena manter
- Calibração a partir de edições reais: após uma v2, o criador normalmente remove 10-20s manualmente de um corte de ~10 minutos. A maior parte é ajuste de quadro nas bordas dos segmentos, mais linhas repetidas, onde um ponto é dito e dito novamente melhor em poucos segundos. Quando uma frase repete a anterior, corte a primeira versão. Isso é diferente da repetição deliberada de ensino, que repete uma frase entre seções, não consecutivamente. Quando um ponto é feito duas vezes distantes, sinalize a versão mais fraca como um corte possível.
- A preocupação usual é cortar demais e ter que adicionar de volta, então aperte apenas com evidência, nunca por palpite.
- Exemplo de formato de origem: 4K 23.976 MP4 com áudio 48kHz; linha do tempo de entrega 1920x1080 23.976, começando em 01:00:00:00. Ajuste
fps/width/heightemparams.jsonpara seu material. - Timecode a 23.976 conta 24 quadros por segundo de timecode:
frames = round(seconds / 1.001 * 24). AppendToTimelinetrataendFramecomo exclusivo: passe o quadro após o último que você deseja. Uma regra "inclusivo, subtraia 1" remove um quadro de cada segmento (cerca de 4s em uma linha do tempo de 10 minutos, e qualquer segmento de 1 quadro desaparece).- Alguns palestrantes usam quase nenhuma palavra de enchimento; verifique antes de construir em torno da remoção de enchimentos.
- Aproximadamente 20% do material bruto de cabeça falante é removível, e cerca de três quartos disso é julgamento (takes e reinícios), um quarto é silêncio morto.
- Modelo Whisper:
ggml-small.en.biné preciso o suficiente; ele ouve mal algumas palavras, o que não importa para pontos de corte, mas importa se você citar o palestrante.
Relacionados
video-overlays: gráficos animados, execute após o corte estar bloqueado (se instalado)video-reels: cortes verticais do mesmo material (se instalado)video-thumbnails: miniaturas e títulos (se instalado)lapel-sync: execute primeiro quando o áudio foi gravado em um microfone de lapela/gravador separado