cut-rough
Aperto mecânico: pausas, palavras de preenchimento, retakes, higiene de emendas. Tudo aqui é reversível e cada decisão carrega proveniência.
O argumento $project é o slug; a solicitação completa está em $ARGUMENTS. Um espaço reservado $ vazio
significa que a skill foi acionada automaticamente, e não por barra: pegue o projeto de
PIPELINE_STATE no contexto da sessão e diga qual você escolheu. Os nomes dos verbos seguem o
contrato de construção; python engine/ve.py --help prevalece em caso de conflito.
Pré-condições, e por que são rigorosas
Execute cut-story primeiro. Se story.blocks estiver ausente, diga isso e ofereça cut-story em vez de
prosseguir — cortar mecanicamente sobre material que está prestes a ser descartado por inteiro queima
tempo em detecção de retakes e fillers que ninguém ouvirá.
Se o usuário explicitamente quiser uma passagem mecânica sobre tudo ("einfach nur die Ähms raus"), isso é legítimo. Faça isso e diga que nenhuma seleção de conteúdo ocorreu.
A regra do quadro
Os pontos de corte se encaixam em quadros inteiros. Isso não é capricho — pontos de corte fora da grade de quadros fazem o filtro de concatenação acumular 8,33 ms de deriva de A/V por corte, 1250 ms em 150 cortes. Com encaixe, os mesmos 150 cortes derivam exatamente 0 amostras.
in_frame = floor(t_in * fps + 0.5) # arredonda metade PARA CIMA -> empates vão para depois
out_frame = ceil (t_out * fps - 0.5) # arredonda metade PARA BAIXO -> empates vão para antes
if out_frame <= in_frame: out_frame = in_frame + 1
out é exclusivo — ffmpeg implementa trim=end como um < estrito, e o intervalo semiaberto
[in, out) é o que torna a concatenação exata. Errar o arredondamento de OUT faz cada segmento
ter um quadro de comprimento; 200 cortes são 6,7 s de deriva e sincronia quebrada audivelmente.
Nunca faça esta aritmética manualmente. vedit/timebase.py é dona disso: snap_in / snap_out.
Passo 1 – execute as passagens
python engine/ve.py cut $project
Quatro passagens sobre a lista de palavras achatada, depois o encaixe:
- Hierarquização de silêncio. Lacunas abaixo de
min_gapnunca são cortadas. Acima disso, a pausa retida é dimensionada de acordo com a pontuação da palavra anterior:.?!x1,5 (mínimo 0,40 s),,;:x1,0, meio da oração x0,7 (mínimo 0,20 s), mudança de tópico x2,0 (mínimo 0,60 s). Um comprimento de pausa uniforme é o sinal mais reconhecível de uma edição automática — o ouvido espera uma respiração mais longa após um ponto final. - Hierarquização de fillers. Veja abaixo.
- Detecção de retakes. N-gramas repetidos onde a tomada posterior substitui a anterior.
- Higiene de emendas. Padding, crossfades, snap de cruzamento de zero, limitação de densidade de corte.
Passo 2 – níveis de fillers, e o que não deve ser automatizado
- Nível A – não lexical (
äh ähm hm mh uh um er): remoção automática. Ninguém quer isso. - Nível B – fillers lexicais (
weißt du, sozusagen, quasi, im Prinzip, you know, I mean): remoção automática com proteções — não no início de uma frase, não quando a remoção deixa um fragmento abaixo demin_clip. - Nível C – partículas modais:
also halt eben ja mal doch schon eigentlich genau, e em inglêslike just well right so basically actually. Apenas sinalizar. Nunca remover automaticamente.
O nível C é onde editores automáticos estragam a fala em alemão. doch, eben, halt e ja carregam
atitude e estrutura discursiva; removê-los não faz o falante soar mais conciso, mas sim
como uma tradução. Se o usuário pedir para removê-los mesmo assim, faça — mas diga
uma vez o que isso custa e depois pare de mencionar.
Ordem do sinal de detecção: correspondência lexical, depois duração/caractere >= 0,12 s, depois lacuna
adjacente >= 0,10 s, depois energia dentro de 6 dB da fala circundante.
Nunca use a pontuação score do WhisperX como sinal de filler. Ela mede alinhamento, não hesitação. Pontuações
baixas se aglomeram em palavras raras e nomes próprios — o oposto de fillers. Use-a apenas como um
indicador de confiabilidade de timestamp: score < 0,35 aumenta o padding em 60 ms e proíbe corte dentro
dessa palavra.
Passo 3 – os padrões e seu status
| parâmetro | padrão | observação |
|---|---|---|
pad_in | 0,08 s | fechamento plosivo antes de /p t k b d g/ |
pad_out | 0,10 s | liberações de /t k s/ vão além do end do alinhador |
keep_pause | mínimo 0,18 s | o espaço de respiração deixado onde havia silêncio |
min_gap | 0,55 s | abaixo disso, nunca cortar |
min_removal | 0,20 s | remoções mais curtas não valem uma emenda |
max_cut_density | 1 por 1,5 s | fadiga de jump-cut |
min_clip | 0,35 s | clipes mantidos mais curtos se fundem com um vizinho |
| crossfade | 20 ms (10 mínimo, 40 máximo) | curve=tri mesma tomada, qsin entre tomadas |
| busca de cruzamento de zero | +/-5 ms (240 amostras) | apenas áudio, nunca move vídeo |
Estes são derivados de pesquisa, não testados perceptualmente. Enquanto project.json tiver
"calibrated": false, diga isso sempre que defender um corte. Não apresente um limite não calibrado
como ajustado. O hook de sessão exibe esta flag toda sessão por esse motivo.
O snap de cruzamento de zero vale a pena entender: um corte abrupto em um ponto não zero produziu um salto de amostra 29,5x maior que o máximo natural do sinal — um clique audível. Tanto um snap de cruzamento de zero quanto um crossfade de 20 ms trazem de volta à linha de base. Use ambos. O snap move apenas áudio, nunca vídeo; um deslocamento de vídeo sub-quadro não é representável.
Passo 4 – cortes J/L
4-12 quadros é a faixa útil; padrão 6.
Rejeite qualquer corte J/L onde ambos os lados compartilhem um source_id e nenhum seja coberto por B-roll ou
uma sobreposição de quadro inteiro. Em uma boca visível que não é um J-cut, é erro de lip-sync, e
é lido como uma falha técnica, e não como edição.
Passo 5 – escrever segmentos
Os segmentos são escritos em segments[] com src_in_frames (inclusivo) e src_out_frames
(exclusivo) como a única autoridade. Também é necessário em todo segmento:
enabled– material rejeitado éfalsecom um motivo, nunca removido. Toda decisão automática deve ser reversível ao inverter um único booleano. Esta é a propriedade que torna um padrão agressivo seguro.order– ordem de saída explícita, densa sobre segmentos habilitados.provenance–stage(contentpara quedas no nível da história,silence,filler,retake),rule,confidence,applied_bye o valor medido que o acionou (original_gap_s). Proveniência é o que permite ao usuário dizer "desfazer todas as remoções de nível B".word_rangeetextdesnormalizado. O texto é apenas para leitura e nunca é autoritativo – se ele discordar deword_range, o intervalo de palavras vence.
As posições na linha do tempo são derivadas, nunca armazenadas. Elas são uma soma contínua sobre segmentos
habilitados escrita em _computed no carregamento. Nunca escreva _computed manualmente.
Defina stage como "rough_cut".
Passo 6 – relate como um editor, não como um script
Relate: duração da fonte, duração do corte, porcentagem removida, número de cortes, densidade de cortes
(cortes por minuto) e a contagem por regra de proveniência. Em seguida, sinalize algo que pareça um
corte excessivo: um trecho com mais de um corte a cada 1,5 s, qualquer clipe mantido próximo a min_clip, e
o número de fillers de nível C sinalizados mas deixados intactos.
Ofereça três próximos passos: pré-visualizar uma seção, ajustar um limite ou avançar para gráficos/legendas.
Modos de falha
| Sintoma | Causa | Correção |
|---|---|---|
| Cada segmento tem 1 quadro | OUT arredondado para cima em vez de para baixo | Use snap_out; nunca insira a matemática inline |
| Cliques audíveis nas emendas | Snap de cruzamento de zero ignorado | Snap mais um crossfade de 20 ms |
| A fala parece cortada e sem fôlego | Pausa retida uniforme | Aplique a tabela escalonada por pontuação |
| O falante parece robótico e não alemão | Nível C removido | Nível C é apenas sinalização; restaure por proveniência |
| Cortes caem no meio da palavra | Transcrição é nível 3 (tokens BPE) | Retranscreva; timestamps de token não podem ser cortados |
| Deriva de A/V cresce ao longo do vídeo | Pontos de corte não encaixados no quadro | Encaixe cada ponto de corte, depois execute a verificação de QC (a) |