video-framing
Execute após video-tighten (esconda os cortes que ele cria) e antes de video-color. Requer a skill resolve-bridge instalada ao lado desta (ele a encontra em ../resolve-bridge, ou defina RVS_BRIDGE), além de ffmpeg, ffprobe e swift (macOS já o inclui; Apple Vision mede rostos e mãos). A transcrição precisa de uv (Whisper local) ou de um comando de transcrição em RVS_TRANSCRIBE_CMD; se a transcrição falhar, prepare continua com um aviso e a transcrição fica incompleta.
Execute os scripts como python3 <pasta desta skill>/scripts/framing.py <comando> --workdir <pasta>. Comandos: prepare, solve, apply, pushes.
Os scripts medem e fazem as contas. Você faz os julgamentos (o que é desordem, quais configurações são simples, quais falas recebem zoom). Nunca pare para pedir aprovação. O usuário revisa depois. Uma decisão que você não tem certeza ainda recebe sua melhor resposta e a compilação continua; adicione-a à lista issues em decisions.json (veja Como decidir), e apply a transforma em um item de checklist. Os campos reason vão apenas para o relatório.
Fluxo de trabalho
-
Onde estamos.
python3 <resolve-bridge>/scripts/rvs.py --workdir <pasta> status. Adote a linha do tempo primeiro se nada ainda estiver rastreado (veja resolve-bridge). -
Preparar. Não muda nada no Resolve:
python3 scripts/framing.py prepare --workdir <pasta>Se o Resolve estiver aberto e a linha do tempo rastreada tiver edições manuais não registradas,
prepareprimeiro as registra como uma nova versão (manual, "edições manuais antes do enquadramento") através do resolve-bridge, e avisa. Informe o usuário. Se o Resolve estiver aberto e seu modo de escala fizer com queapplyrecuse (veja O que faz com a linha do tempo),prepareimprime um aviso no início, para que o usuário possa alterá-lo antes da execução longa.Encontra os itens em cena, agrupa-os em configurações de câmera, mede rosto, olhos, corpo e mãos (cerca de 4 amostras por segundo), e escreve:
generated/framing/setups/<id>.jpg: uma imagem estática por configuração com uma grade 10% rotulada (0.0 a 1.0 em ambos os eixos);.edit/framing/transcript.md:MM:SS.ss-MM:SS.ss <configuração> <texto>, uma linha por frase ouvida em cena, no tempo da linha do tempo. Cada peça em cena tem apenas as palavras dentro de seu próprio intervalo de origem (tempos das palavras do Whisper), então nada se repete entre as peças, e os tempos são os da primeira e última palavra. Escolha os intervalos de zoom diretamente dessas linhas;.edit/framing/decisions.json: um modelo com cada configuração vazia (uma reexecução mantém decisões para configurações cujos itens não mudaram),context.jsoncom orçamentos e imagens estáticas.
O primeiro
prepareé lento: a medição leva cerca de 1.5 s por segundo de fonte, e o Whisper é executado uma vez por arquivo de origem. Execute-o em segundo plano e espere dezenas de minutos em um vídeo de 5 minutos. Ele imprime uma linha de progresso por item e por fonte (descarregada, então um log redirecionado a mostra). Execuções posteriores são armazenadas em cache e rápidas; uma atualização da skill que muda como a medição funciona mede mais uma vez.Ele imprime uma linha por configuração (itens, orçamento de zoom, imagem estática) e o número de itens que já possuem enquadramento manual: estes são deixados exatamente como estão, e a lista está em
context.jsoneREPORT.md. -
Decidir. Observe cada imagem estática da configuração e preencha
decisions.json(veja Como decidir). Em seguida, escolha as linhas de zoom. -
Resolver. Uma execução simulada que não muda nada no Resolve e nunca se conecta a ele. Sempre funciona a partir do plano registrado da versão atual no estado rastreado (uma linha do tempo adotada através do resolve-bridge), portanto edições manuais feitas no Resolve desde a última versão registrada não estão nele:
prepareeapplyas registram primeiro.python3 scripts/framing.py solve --workdir <pasta>Escreve
generated/framing/REPORT.md,setups/<id>_before_after.jpgpor configuração eflags/<n>.jpgpor item sinalizado, e.edit/framing/solution.json. Umdecisions.jsoninválido (rótulo ausente, caixa fora de 0..1) para com o motivo e código de saída 2. -
Verifique as visualizações você mesmo. Abra cada imagem antes/depois e as imagens de sinalização. Cada visualização mostra um quadro: o primeiro item da configuração, ou o item sinalizado, em seu meio. Um gesto em outro item ou em outro momento não está nela, então verifique a visualização de cada item sinalizado, não apenas as da configuração, e leia o texto da sinalização. Para uma mão que está baixa no quadro (alcançando a lente, gesticulando perto da borda inferior), considere
"bottom_hands": "gesture"mesmo quando o único quadro mostrado parecer OK. Layout: a metade esquerda é a fonte inteira com o quadro que será enviado em verde, caixas de exclusão em vermelho e caixas de inclusão em azul (o quadro final de um zoom em ciano; em uma sinalização sobre um zoom de aproximação ignorado ou um zoom desistido, a tentativa rejeitada em laranja); a metade direita é o resultado como o espectador o vê, com regra dos terços. Procure pelas coisas que as regras proíbem: uma tangente ao longo da borda do quadro, uma mão cortada (se uma mão é cortada na borda inferior enquanto alcança a lente ou gesticula, não descansando nos joelhos ou em uma mesa, defina"bottom_hands": "gesture"nessa configuração e resolva novamente), uma cabeça muito perto do topo, desordem ainda em uma borda, uma planta escolhida cortada. Se um quadro parecer errado, corrija suas próprias decisões (mova uma caixa, mude um rótulo, descarte um zoom) e resolva novamente. Repita até que as visualizações estejam corretas ou os problemas restantes sejam aqueles que apenas uma pessoa pode julgar. Leia também as sinalizações e zooms descartados do relatório: o relatório fornece os detalhes brutos de cada sinalização (coordenadas da caixa, chaves do item) abaixo dela; os itens do checklist obtêm o texto curto em palavras simples. -
Aplicar. Precisa do Resolve aberto com o projeto carregado.
python3 scripts/framing.py apply --workdir <pasta>Resolve novamente, então bifurca
<base>_vNN_framingatravés do resolve-bridge (grades, efeitos e edições manuais permanecem), define Zoom, Pan e Tilt (um clipe com zoom obtém seu quadro inicial), arquiva a versão anterior e salva o projeto. Após a etapa ser registrada, cada sinalização e cada entrada da sua listaissuesse torna um problema emEDIT_CHECKLIST.md, localizado pelo nome do clipe e timecode. Sinalizações são mescladas primeiro: todos os zooms de aproximação ignorados de uma configuração tornam-se um problema com seus motivos contados, e sinalizações idênticas em uma configuração tornam-se uma. Informe ao usuário o novo nome da linha do tempo, os IDs dos problemas e onde está o relatório. Código de saída 2 significa uma falha esperada com uma mensagem (nenhuma linha do tempo rastreada, modo de escala para o qual o enquadramento não está calibrado, e assim por diante). -
Criar keyframes dos zoons no Inspetor. A API de Script do Resolve não pode criar keyframes, então
applydeixa cada clipe com zoom em seu quadro inicial, escreve.edit/framing/keyframes_todo.jsone adiciona um problema de checklist por zoom com os valores exatos. Se você tiver controle de computador, faça-os agora; caso contrário, informe ao usuário que os problemas são dele (cerca de um minuto por clipe), e eles são marcados como concluídos porpushes checkapós a próxima sincronização de edição manual do usuário.python3 scripts/framing.py pushes begin --workdir <pasta> # bifurca <base>_vNN_pushins, lista os zooms python3 scripts/framing.py pushes goto 1 start --workdir <pasta> python3 scripts/framing.py pushes finish --workdir <pasta> # verifica os keyframes, salva, fecha os problemasPara cada zoom, no Inspetor da página Edição do Resolve (Vídeo > Transformar). O controle de aplicativo em segundo plano não pode digitar no Resolve, então isso precisa de controle de tela cheia:
pushes goto N start. O script move o cabeçote de reprodução, e o Inspetor o segue. Clicar em um clipe pode mover o cabeçote de reprodução um quadro, então não clique na linha do tempo depois. Verifique se o Inspetor nomeia o clipe.- Clique nos losangos de keyframe de Zoom e Posição, à direita de cada linha. Eles ficam vermelhos. Os valores já são o quadro inicial.
pushes goto N end. Clique duas vezes em Zoom X, então selecione tudo, digite o zoom final e pressione Return (Zoom Y segue quando vinculado). Faça o mesmo para Posição X e Y. Novos keyframes aparecem por conta própria.- Suavização: clique com o botão direito em cada losango vermelho. No final, escolha Ease In. No início, uma vez que o final exista, escolha Ease In and Out. O menu de um keyframe só oferece as suavizações que seus vizinhos permitem, e a marca de seleção nem sempre atualiza, então verifique o resultado: na metade do caminho, o Zoom deve estar próximo da média dos dois valores, e em um quarto deve estar abaixo do valor da linha reta.
- Nunca defina uma propriedade por script em um clipe com keyframes: o Resolve exclui todos os seus keyframes.
pushes finishlê os keyframes de volta (através de uma exportação FCPXML) e compara quadros e valores. Se um estiver faltando ou errado, ele diz qual e deixa a etapa aberta.--partialsalva de qualquer maneira e deixa esses problemas abertos.pushes checkfaz a mesma verificação sem salvar.apply --pushes fusionfaz zoons de Transformação Fusion em vez disso (o método antigo, totalmente scriptado).
Como decidir
decisions.json:
{
"setups": {
"A": {
"items": ["..."],
"label": "plain",
"reason": "sentado à mesa, de frente, estático. Micro-ondas com ímãs na borda direita, cadeira extra bem à esquerda; a planta permanece.",
"keep_out": [[0.00, 0.45, 0.12, 1.00], [0.86, 0.30, 1.00, 0.80]],
"keep_in": [[0.60, 0.20, 0.74, 0.62]]
},
"B": {"items": ["..."], "label": "dynamic", "reason": "sentado no balcão, ângulo alto", "keep_out": [], "keep_in": []}
},
"reclassify": {"V1@1234": "broll"},
"push_ins": [
{"start_s": 41.2, "end_s": 47.0, "text": "Escrever é pensar.",
"reason": "a tese, primeira vez que é dita claramente"}
],
"issues": [
{"text": "Planta na borda direita cortada com as mesas de centro; não tenho certeza se era desordem",
"where": "S04_IMG_1234.MOV at 00:14.00"}
]
}
Caixas são [esquerda, topo, direita, base], normalizadas 0..1 na imagem estática da configuração (leia-as em sua grade). start_s e end_s são segundos da linha do tempo de transcript.md. items é preenchido por prepare; deixe-o.
- Caixas de exclusão: tudo que ninguém escolheu mostrar, perto das bordas. Eletrodomésticos, ímãs, cadeiras extras, luminárias, cabos, termostatos, batentes de porta, um pedaço de sofá. O resolvedor as corta onde puder sem cortar um gesto.
- Caixas de inclusão: objetos de decoração que o falante escolheu. Plantas, flores, um vaso. O resolvedor as mantém inteiras, ou as corta claramente, nunca um pedaço. Moldura a parte que importa (o buquê, as folhas da planta), não até a borda da fonte: uma caixa que toca a borda da fonte nunca pode ser mantida inteira dentro de um corte.
- Rotule cada configuração como
plainoudynamic.plainé de frente, nível dos olhos e estático (sentado à mesa).dynamicé um ângulo alto ou baixo, uma posição incomum (sentado em um balcão) ou uma diagonal forte. Configurações dinâmicas não recebem zoons. - Motivo: uma linha por configuração, sempre. Vai para o relatório.
- Mãos na base (opcional):
"bottom_hands": "gesture"em uma configuração. Por padrão, mãos tocando a base da fonte (a partir de 93% de sua altura) contam como descansando: o quadro pode parar acima delas. Mãos alcançando a lente tocam a borda inferior também, e essa regra as cortaria. Se uma visualização antes/depois ou de sinalização mostrar uma mão cortada na borda inferior enquanto alcança ou gesticula, defina isso nessa configuração e resolva novamente: essas mãos então contam totalmente, e o quadro fica mais solto. - Problemas: cada decisão da qual você não tem certeza (desordem ou escolhido, qual de duas coisas manter, uma fala que você quase escolheu), com sua melhor resposta aplicada.
textdiz o que você decidiu e o que uma pessoa deve verificar;whereé o nome do clipe e timecode (decontext.json), por exemploS04_IMG_1234.MOV at 00:14.00. Ambos devem ser não vazios. Eles se tornam problemas de checklist quandoapplytermina. - Reclassificar apenas para corrigir o agrupamento: um item que o script tratou como em cena mas que é realmente b-roll (
broll), ou vice-versa (on_camera). A chave éV<trilha>@<quadro inicial>(por exemploV1@1234): as chaves deitemsem.edit/framing/context.json, que também fornece o nome do clipe e timecode de cada item. Uma chave que não corresponde a nenhum item é ignorada, então verifique-a emcontext.json. Uma configuração cujos itens são todos reclassificados comobrollnão precisa de rótulo. - Linhas de zoom vêm do script e
transcript.md: a tese, uma virada no argumento, uma piada, uma chamada para ação. Não preenchimento, não frases de configuração. Mantenha-as com 3 a 8 s de duração e com pelo menos 30 s de intervalo, coloque-as em configurações simples onde nenhum b-roll cobre o falante, e escreva um motivo para cada uma. Menos é melhor do que fracas. O resolvedor descarta qualquer uma que quebre as regras e diz qual regra no relatório (e mostra o zoom rejeitado em laranja em sua visualização de sinalização). Os zoons são mantidos em segundos da linha do tempo, entãosolveverifica otextde cada um contra a transcrição da linha do tempo atual: quando a fala não é mais dita em seu intervalo (a linha do tempo mudou desde que você a escolheu), o zoom é descartado com um problema para reescolhê-lo. Copietextdetranscript.mdpara que a verificação possa encontrá-lo. Sem uma transcrição em cache para o intervalo, o zoom é mantido e o relatório diz que não foi verificado.
As regras de enquadramento
Estas são o que os scripts aplicam. As razões estão aqui para que você possa julgar tomadas que as regras não cobrem.
Quadro base, um por configuração
- Olhos na ou logo acima da linha do terço superior, um espaço de cabeça pequeno e igual para cada clipe. Olhos perto do terço superior leem como naturais e engajados; muito espaço vazio acima parece amador. Um quadro que corta a testa ou toca o cabelo parece um erro. Quando mãos baixas no quadro puxam o quadro para baixo e empurram os olhos acima do terço, o quadro se inclina para trás para manter cerca de 10% da altura do quadro acima da cabeça (estimado a partir do tamanho do rosto), no mesmo zoom; onde gestos, desordem ou uma articulação não deixam espaço, a linha dos olhos decide sozinha.
- Centralizado no rosto para discurso direto, deslocando-se para fora do centro em no máximo 5% da largura para manter a desordem fora. Olhar diretamente para a lente implica simetria; rostos descentralizados parecem um erro a menos que a tomada seja claramente composta assim.
- A borda inferior nunca se apoia em uma articulação (queixo, pescoço, cotovelos, pulsos, cintura...