Communitygithub.com

resolve-cut

Edite vídeos de cabeça falante (aulas, cursos, entrevistas) do início ao fim no DaVinci Resolve Studio: transcrições em nível de palavra, um dossiê de cada take, o último take completo de cada parágrafo, uma lista de cortes precisa por quadro, montagem da linha do tempo a partir do roteiro, renderização com predefinições, controle de qualidade (loudness, quadros, palavras repetidas) e entrega. Carregue antes de qualquer trabalho de script, montagem, renderização, controle de qualidade ou entrega de vídeo no Resolve.

O que é resolve-cut?

O resolve-cut é uma habilidade especializada para agentes de IA que trabalham com edição de vídeo no DaVinci Resolve Studio. Ela automatiza o fluxo de edição de vídeos de cabeça falante, como aulas, cursos e entrevistas, desde a transcrição até a entrega final. A habilidade usa scripts Python que se comunicam com a API do Resolve e ferramentas de mídia como ffmpeg para gerar transcrições no nível da palavra, criar um dossiê de todas as gravações, selecionar o último take completo de cada parágrafo, gerar uma lista de cortes precisa por quadro (com base na posição mais silenciosa próxima às palavras), montar a linha do tempo no Resolve a partir do roteiro, renderizar com predefinições específicas para cada plataforma (Reels, YouTube, LinkedIn, etc.), e realizar controle de qualidade verificando loudness, quadros e palavras repetidas. Ela também suporta a criação de novas versões com correções, entrega com normalização de loudness e remoção de metadados, e documentação de armadilhas conhecidas para evitar erros comuns. É útil para desenvolvedores e editores que desejam automatizar tarefas repetitivas de edição de vídeo com alta precisão.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Developh/resolve-cut/tree/HEAD/skills/resolve-cut

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que resolve-cut faz?

Você monta, renderiza e verifica vídeos no DaVinci Resolve Studio por meio de scripts salvos com parâmetros. Você não reescreve a montagem em cada sessão: você chama os scripts, lê o que eles retornam e verifica o resultado com números e quadros. O gosto permanece humano: a pessoa decide o que fica, você executa e mede.

$SKILL abaixo é a pasta desta habilidade (onde este arquivo está). Scripts em scripts/resolve/ são executados dentro do Resolve através de run.py; scripts em scripts/media/ são Python puro com ffmpeg. Cada script tem --help.

Antes de começar

  1. Resposta do Resolve: python3 "$SKILL/scripts/resolve/run.py" - '{}' <<< 'result = resolve.GetVersionString()'. Código de saída 2 significa que o Resolve está fechado, é a edição gratuita, ou em Preferências > Sistema > Geral > Scripts externos usando não está definido como Local.
  2. ffmpeg -version, python3 -c "import numpy, PIL" e ELEVENLABS_API_KEY (ambiente ou ./.env).
  3. Se o projeto mantém um arquivo de notas (VIDEO_NOTES.md ou similar), leia-o: o que a pessoa aprovou e rejeitou antes. Não peça a mesma correção duas vezes.
  4. Pasta de trabalho: tudo o que você escreve (transcrições, dossiê, quadros, renderizações) vai para uma pasta de trabalho, nunca para a pasta de filmagem bruta.

O fluxo

1. Transcrever. Transcrições em nível de palavra, um JSON por clipe: python3 "$SKILL/scripts/media/transcribe.py" <pasta de clipes> --out work/transcripts [--language por]. A transcrição é a base de tudo: escolher takes, cortar nos limites dos quadros e verificar a mixagem final.

2. Dossiê. Todo o material em um arquivo de texto compacto, leia uma vez: python3 "$SKILL/scripts/media/dossier.py" <pasta de clipes> --transcripts work/transcripts --out work/dossier.md [--sheets]. Ele lista cada frase com seu tempo e sinaliza «repeats C0076 20.2» quando uma frase começa como uma anterior: outra tentativa da mesma fala. Com um roteiro, mantenha o último take completo de cada parágrafo; descarte hesitações, falsos começos e tentativas repetidas. Abra um clipe apenas para decidir algo: python3 "$SKILL/scripts/media/inspect_range.py" <clipe> <t0> <t1> --words work/transcripts/<clipe>.json (quadros, forma de onda e palavras em uma imagem).

3. Lista de cortes. Escreva work/plan.json com os takes escolhidos em ordem ({"Lesson 01 v1": [["01a", "C0081", 1.9, 12.6], ["01b", "C0083", 5.4, 23.8], ...]}: take, clipe, de, até em segundos do clipe), então: python3 "$SKILL/scripts/media/cut_list.py" work/plan.json work/transcripts <pasta de clipes> work/cuts.json. Os cortes pousam no limite de quadro mais silencioso próximo às palavras, pausas acima de 1 s são encurtadas, e os segmentos alternam zoom 1 / 1.2 para que cortes entre takes não saltem. Para um falso começo sem lacuna ("co- contar"), force o quadro com {"in_frame": N} ou {"out_frame": N}. Notas para o editor: add_markers.py.

4. Montar no Resolve. Uma operação pesada por chamada, e leia cada result antes da próxima:

R="$SKILL/scripts/resolve/run.py"
python3 "$R" "$SKILL/scripts/resolve/project.py" '{"name": "Lesson 01", "width": 1920, "height": 1080, "fps": "25"}'
python3 "$R" "$SKILL/scripts/resolve/assemble.py" '{"phase": "import", "bin": "Raw", "media": "/abs/clips", "files": ["C0081.MP4"]}'
python3 "$R" "$SKILL/scripts/resolve/assemble.py" '{"phase": "timeline", "bin": "Raw", "cuts": "/abs/work/cuts.json", "timeline": "Lesson 01 v1", "zoom": {"center": [0.45, 0.37]}, "voice_isolation": 50}'

zoom.center é onde o rosto está (fração do quadro), então o close-in o mantém no lugar. Verifique se frames == expected e failures está vazio.

5. Olhar antes de renderizar. frames.py exporta quadros diretamente da linha do tempo em menos de um segundo ({"timeline": "Lesson 01 v1", "frames": [100, 500], "folder": "/abs/work/frames", "max": 960}). Olhe um quadro simples e um com close-in.

6. Renderizar. python3 "$R" "$SKILL/scripts/resolve/render.py" '{"phase": "start", "timeline": "Lesson 01 v1", "folder": "/abs/out", "name": "lesson-01", "preset": "reel", "width": 1920, "height": 1080, "mark": [0, <frames - 1>]}', depois verifique {"phase": "status", "job": "<id>"} a cada 10 s até que JobStatus seja Complete. Aguarde a renderização terminar antes de responder: uma execução headless que termina sua vez em "renderização iniciada" deixa ninguém para verificá-la.

7. Verificar. python3 "$SKILL/scripts/media/qc.py" out/lesson-01.mp4 --expected <frames> --transcribe (adicione --ref contra a última versão aprovada, --frames para uma planilha, --simulate para Instagram). Leia a transcrição da mixagem final em cada corte: palavras repetidas ("decide, decide"), palavras cortadas e palavras no lugar errado são os defeitos que uma lista de cortes cria. Confirme um corte suspeito na forma de onda (inspect_range.py) antes de movê-lo, corrija a lista de cortes, monte uma nova versão (v2) e renderize novamente. No máximo 3 rodadas, cada defeito nomeado com seu tempo exato. Nunca considere concluído porque "parece certo": cite os números.

8. Entregar. loudness.py quando a mixagem estiver fora do alvo (ganho linear e um limitador, nunca loudnorm), depois deliver.py export.mp4 clean.mp4 [--no-editlist] [--copy <pasta>]: sem trilha de timecode, sem metadados, moov primeiro, cópia comparada byte a byte.

9. Revisar, após a aprovação da pessoa. Escreva no arquivo de notas o que eles aprovaram e rejeitaram, em suas palavras, uma linha cada; toda nova armadilha com sua data; e toda rotina que você fez manualmente mais de uma vez se torna um script com parâmetros ao lado destes.

Executando scripts dentro do Resolve

  • run.py conecta-se ao Resolve aberto e executa um script com resolve, project, P (o JSON) e __file__ definidos, depois imprime result como JSON. Custa muito menos tokens do que escrever o mesmo script através de um MCP.
  • Com um servidor MCP em vez disso (oficial run_script_unsafe): P = {...}; __file__ = "<caminho absoluto do script>"; exec(open(__file__, encoding="utf-8").read()). O sandbox lê arquivos como ASCII sem encoding, e os nomes persistem entre chamadas: os scripts prefixam suas variáveis.
  • Salve antes e depois de escrever (GetProjectManager().SaveProject()); não há desfazer. Faça cada nova versão em uma cópia da linha do tempo (DuplicateTimeline, que copia também composições Fusion).
  • Consulte a API em vez de adivinhar: o MCP oficial tem search_scripting_api, get_scripting_docs e get_whats_new (uma vez por sessão), ou o README da Blackmagic na pasta Developer/Scripting do Resolve (Ajuda > Documentação > Desenvolvedor).
  • Nova operação que se repetirá? Escreva-a uma vez como um script com um dicionário P e um result, ao lado destes.

Destinos de entrega

DestinoImagemSom
Reels, Stories, Shorts, TikTok1440x2560 na taxa de quadros de gravação, H.264 High a cerca de 20 Mbps real, tags Rec.709 (1-1-1), faststart-14 LUFS, pico verdadeiro abaixo de -1.5 dBTP
Aulas e cursoscomo gravado (1920x1080 ou 3840x2160)-16 LUFS, pico verdadeiro até -1 dBTP
YouTubeo master 4K (uploads em 1080p perdem qualidade), MP4 sem listas de ediçãoa mixagem do master
LinkedIn1920x1080 e 1080x1920 a 16 Mbps, com SRTa mixagem do master

Armadilhas verificadas

Medido no macOS com Resolve Studio 21.1.1 e 21.1.2, outubro e novembro de 2026.

Máquina

  • Um ffmpeg por vez, com nice -n 15 e -threads 2: 96 processos ffmpeg paralelos congelaram o Mac e forçaram uma reinicialização.
  • No zsh, $var não divide em palavras (ffmpeg $args quebra): construa listas de argumentos em Python.
  • Escreva saídas na pasta de trabalho: um auxiliar que salvava imagens ao lado do clipe escreveu na unidade de filmagem bruta.

Configuração e API do Resolve

  • O Resolve 21.1 moveu o scripting Python para o Studio: run.py e ambos os servidores MCP precisam do DaVinci Resolve Studio.
  • Scripts externos devem estar definidos como Local (Preferências > Sistema > Geral) ou scriptapp("Resolve") retorna None.
  • StartRendering é a última chamada de um script: tudo o mais retorna None até que a renderização termine.
  • A taxa de quadros do projeto trava quando a primeira linha do tempo é criada: defina-a antes (project.py).
  • Resolução: SetSetting uma chave por vez, useCustomSettings primeiro.
  • O tempo limite do MCP (10 s por padrão, no máximo 60 s) retorna um erro, mas o script continua executando dentro do Resolve: verifique o estado antes de executá-lo novamente.
  • Não há cortar, mover ou deslizar: exclua o item e anexe-o novamente com startFrame, endFrame (exclusivo) e recordFrame.
  • startFrame conta a partir do primeiro quadro do arquivo, mesmo com timecode de câmera.
  • GetSourceStartFrame às vezes lê um quadro antes (866 lê 865) enquanto o posicionamento está correto: leia o ponto de entrada com GetLeftOffset.
  • AddMarker mantém um marcador por quadro.
  • ReplaceClip apaga os metadados do clipe.
  • SetTrackEnable retorna True e não muda nada em algumas linhas do tempo: desative os clipes com SetClipEnabled e confirme em um quadro exportado.
  • SetClipEnabled em uma linha do tempo que não é a atual retorna False: SetCurrentTimeline primeiro, depois confirme com GetClipEnabled.
  • DeleteClips(items, True) ondula todas as faixas: primeiro exclua, sem ondular, o que cruza o corte (stems, legendas).
  • Isolamento de Voz funciona por script: TimelineItem.SetVoiceIsolationState({"isEnabled": True, "amount": 100}) reduziu a reverberação da sala em 3 a 4 dB; Timeline.SetVoiceIsolationState(track, {...}) define um controle para uma faixa inteira.
  • A API não pode definir parâmetros do ResolveFX (Refinamento Facial, Remoção de Imperfeições): uma pessoa os define, ou você dirige a interface através de acessibilidade.
  • Com a tela bloqueada ou o Resolve minimizado, a janela desaparece da acessibilidade, mas a API continua funcionando: verifique com quadros exportados.
  • Super Scale é uma propriedade do media pool: SetClipProperty("Super Scale", 2); um arquivo de substituição precisa defini-la novamente.
  • LUTs para Graph.SetLUT vão na pasta de LUTs do sistema do Resolve, em uma subpasta, passados por caminho relativo após RefreshLUTList().
  • Mudar de página enquanto o Resolve reproduz trava-o; item.GetFusionCompByIndex(1).Execute(lua) edita uma composição sem abrir a página Fusion.

Importação e mídia

  • Um ProRes por chamada de importação: vários ProRes 4444 (e uma vez dois novos ProRes 422) em uma chamada travaram o Resolve 21.1 (UiMpController, std::out_of_range). MP4s de câmera, 22 em uma chamada, funcionaram bem.
  • Após essa trava, um processo ResolvePython órfão faz o MCP launch_resolve relatar o Resolve como em execução: mate-o e abra o Resolve novamente.
  • ImportMedia com uma lista de caminhos: a forma com dicionários retornou None para MP4 no 21.1.
  • O Resolve armazena em cache a decodificação por caminho: um arquivo que você renderiza novamente recebe um novo nome.
  • PCM 24-bit little-endian em MOV é lido como ruído branco: use pcm_s24be.
  • iPhone HEVC travou o decodificador macOS: edite a partir de ProRes.
  • iPhone HDR (HLG, Dolby Vision): nosso tone mapping parecia desbotado e foi rejeitado duas vezes. Peça uma exportação SDR no início.
  • Um .mov de 1 quadro importa como um still de 150 quadros: dê a ele pelo menos 3 quadros e corte na linha do tempo.
  • Alfa direto: o Resolve lê alfa não pré-multiplicado, então uma sobreposição feita com ffmpeg overlay em uma tela transparente fica escura; posicione-a com pad=W:H:x:y:[email protected].

Renderização

  • Com SelectAllFrames, StartRendering às vezes retorna False: defina MarkIn/MarkOut (render.py mark), que também corta as caudas de som que alongam uma linha do tempo.
  • Um trabalho H.264 criado logo após um trabalho somente de áudio saiu sem vídeo: carregue uma predefinição antes de SetRenderSettings, e verifique o fluxo de vídeo com ffprobe.
  • VideoQuality do H.264 é um teto, não uma média: 20000 deu 14.7 Mbps e 27300 deu 20.7 Mbps em 1440x2560.
  • "Forçar redimensionamento para máxima qualidade" não é uma chave de SetRenderSettings, mas viaja dentro de uma predefinição de renderização (ForceHighestQualitySizing).
  • ExportRenderPreset(name, path) trata path como uma pasta; ImportRenderPreset nomeia a predefinição após o arquivo.
  • As predefinições armazenam uma taxa de quadros: defina FrameRate a partir da linha do tempo, ou uma linha do tempo de 29.97 renderiza convertida (render.py faz isso).
  • ExportFrame (21.1.2) deu 4 quadros em 1440x2560 em 0.75 s, dentro de 41 a 46 dB da renderização: verifique quadros sem renderizar.

Som e transcrições

  • Um corte entre dois takes pode unir uma palavra repetida ("decide, decide"): transcreva a mixagem final e procure por duplicatas. Corrija sem alterar o comprimento: termine a primeira parte antes da palavra, comece a segunda mais cedo na pausa do take bom.
  • A transcrição não ouve sussurros e respirações: os pontos de corte vêm do som da própria câmera (cut_list.py).
  • Scribe uma vez colocou uma palavra 3 s antes, depois de uma palma e um sussurro: confirme na forma de onda antes de mover um corte.
  • Efeitos sonoros MP3 chegam cerca de 60 ms atrasados (o atraso do codificador não é compensado): use WAV para qualquer coisa que precise acertar um quadro.
  • loudnorm em uma passagem é dinâmico e altera a mixagem aprovada; em duas passagens, silenciosamente volta ao dinâmico: use loudness.py.

Filmagem e plataformas

  • 25 fps no Instagram: servido a 25 (ffprobe dos arquivos servidos, novembro de 2026). A gagueira vem dos iPhones ProMotion, que não têm modo de 25 ou 50 Hz. Mantenha filmagem de 25 fps a 25 (converter para 30 repete um quadro em cada cinco); filme novo material a 29.97 com obturador de 1/50.
  • Cintilação sob luzes de 50 Hz depende do obturador, não da taxa de quadros: 1/50 e 1/100 não cintilam; 1/60 a 30 fps cintila.
  • O Instagram recodifica no telefone e novamente no servidor: a entrega básica é cerca de 720x1280 a 1.4 Mbps, com som normalizado para cerca de -14 LUFS, então um master acima de -14 não ganha nada. qc.py --simulate mostra o que sobrevive.
  • CRF no ffmpeg esgota fundos escuros: um reel ficou a 6.8 Mbps. Verifique a taxa de bits real antes de entregar.
  • Uma execução claude -p headless termina sua vez quando a renderização começa, a menos que o prompt diga para esperar.

Scripts

ScriptO que faz
scripts/media/transcribe.pyScribe JSON em nível de palavra por clipe (chave via stdin, nunca na lista de processos)
scripts/media/dossier.pycada clipe como texto compacto: frases com tempos, pausas, tentativas repetidas, folhas de quadro opcionais
scripts/media/inspect_range.pyuma imagem de um intervalo: quadros, forma de onda, palavras com tempos
scripts/media/cut_list.pytake

Habilidades Relacionadas