feat(voz): legenda por ênfase, forced align, IA local e correções de zoom/revisão
Trabalho da branch feat/revisao-enfases: pipeline de edição por voz ganha alinhamento forçado (whisperx), roteirização por LLM local (Ollama), e a etapa 5 (revisão de frases) passa a refletir de verdade o que é aplicado. - generate_subtitles_by_emphasis: legenda comum cobre o clipe inteiro, legenda dinâmica só nas frases de ênfase, e a comum é desativada (enabled="0") onde a dinâmica cobre, em vez de nunca ser gerada ali. - validate_subtitle_layout ignora títulos com enabled="0" — corrige falso positivo de colisão contra o que está desativado no lugar dele. - Corrige zoom/marcador sendo descartado quando a borda encosta exatamente no início de um corte. - Etapa 5 do Assistente: recarrega quando as decisões da IA mudam (com fresh=true, ignorando a revisão salva antiga) — resolve a dessincronia entre "ativa" na tela e o que já foi cortado no FCPXML. - Etapa "Processar" reaplica as decisões da revisão (_phrase_actions.json) antes da cadeia de remoção de silêncio/legendas — antes, desativar uma frase na etapa 5 não tinha efeito nenhum no vídeo final. - Etapa "Concluído" fundida em "Processar" — abrir no Final Cut/Finder aparece assim que termina, sem slide extra. - Palavra clicável na etapa 5 agora funciona como toggle (clique de novo desfaz) e mostra a própria ênfase (sublinhado colorido + peso da fonte). - fcpxml/forced_align.py, fcpxml/llm_local.py, ai_edit.py: alinhamento fonético via whisperx e roteirização local via Ollama/Gemma. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
711c397dfe
commit
7b5aed79ee
@@ -53,14 +53,19 @@ use para decidir; existem para permitir a reanálise da Fase 2.
|
||||
## O timestamp por palavra tem um viés conhecido
|
||||
|
||||
O início de cada palavra vem sistematicamente **adiantado em ~0,3-0,5s** em
|
||||
relação ao ataque real da fala — medido em material real com ffmpeg
|
||||
(`astats`), consistente em 6 pontos do mesmo vídeo. O fim da palavra não
|
||||
tem esse problema (erro de poucos centésimos). Causa: `word_timestamps` do
|
||||
faster-whisper deriva por atenção cruzada, sem alinhamento forçado — ver
|
||||
`05_EXPERIENCIAS.md`, entrada de 2026-08-19.
|
||||
relação ao ataque real da fala — medido em material real com ffmpeg (`astats`),
|
||||
consistente em 6 pontos do mesmo vídeo. O fim da palavra não tem esse problema
|
||||
(erro de poucos centésimos). Causa: `word_timestamps` do faster-whisper deriva
|
||||
por atenção cruzada, sem alinhamento forçado — ver `05_EXPERIENCIAS.md`, entrada
|
||||
de 2026-08-19.
|
||||
|
||||
**Quando o pipeline já corrigiu isso:** se `layers.alignment` for `true`
|
||||
(transcript gerado com alinhamento forçado fonético via whisperx, implementado
|
||||
depois desse aviso), o viés foi removido na origem — **não aplique o offset
|
||||
manual** abaixo. O aviso vale só para transcripts antigos sem `layers.alignment`.
|
||||
|
||||
Isso não é "reestimar no olho" — é um bug de medição na fonte, não um
|
||||
julgamento seu. Na prática:
|
||||
julgamento seu. Na prática (somente sem `layers.alignment`):
|
||||
|
||||
- Ao posicionar um `zoom` cujo `start` precisa cair exatamente na palavra
|
||||
(não uma frase inteira), some **+0,3 a +0,4s** ao timestamp do JSON antes
|
||||
@@ -69,6 +74,3 @@ julgamento seu. Na prática:
|
||||
- **Não aplique essa correção a `gap_before` para decidir corte** — a régua
|
||||
de silêncio (`06-texto-corte-marcador.md`) já é conservadora o bastante
|
||||
para absorver esse erro; corrigir os dois ao mesmo tempo é redundante.
|
||||
- Se um dia o pipeline ganhar alinhamento forçado (WhisperX), este aviso
|
||||
perde a razão de existir — confira se `layers` ou a versão do documento
|
||||
já indicam isso antes de aplicar o offset manualmente.
|
||||
|
||||
Reference in New Issue
Block a user