A skill decidia a edição sem saber que o JSON dela agora passa por uma tela de revisão antes de virar FCPXML. Isso não é detalhe de fluxo: a etapa 5 traduz cada ação para o vocabulário dela, e sem conhecer essa tradução a intenção da IA se perde no caminho — que é exatamente como uma decisão vira "arbitrária" aos olhos de quem revisa. Novo criterios/10-revisao-humana.md, com o que o app faz com cada ação: - cut cobrindo >=60% da frase remove a linha; tocando só uma borda vira trim encaixado na fronteira de palavra. Corte de meia frase é ambíguo — passa do limiar e apaga a linha toda quando a intenção era aparar a hesitação. - zoom ou text sobre uma frase marca ênfase, e ênfase significa DUAS coisas: zoom mais legenda dinâmica; as demais frases ficam com legenda comum. A escala vira o nível (1.15→leve, 1.3→média, 1.5→forte). - sem ação, o nível é derivado do peak_emphasis; a decisão da IA sempre ganha. - reason é exibido ao lado da frase na tela — é o que o editor lê antes de manter ou desfazer. Deixou de ser campo de log. Consequência prática que faltava em 05-zoom.md: não espalhar zoom "por segurança", porque cada um promove a frase em duas dimensões ao mesmo tempo. Na dúvida, deixar sem — promover custa uma tecla, despromover custa mais. Cada arquivo de critério ganhou cabeçalho de escopo (o que cobre, em que fase), no mesmo padrão dos docs do Engine, para ler só o necessário. Todas as afirmações numéricas do novo critério foram verificadas contra fcpxml/phrase_review.py rodando, não assumidas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
75 lines
3.5 KiB
Markdown
75 lines
3.5 KiB
Markdown
# 01 — Leitura do JSON
|
||
|
||
> **Escopo:** Como ler o voice_timeline em camadas, sem recalcular o que já foi medido.
|
||
> **Quando:** Fase 1 — ver a ordem de trabalho em `../SKILL.md`.
|
||
|
||
O arquivo `<mídia>_voice_timeline.json` é a entrada de todo o trabalho.
|
||
Leia em camadas, de cima para baixo, e só desça quando precisar.
|
||
|
||
## Camadas
|
||
|
||
| Camada | O que traz | Para quê |
|
||
|---|---|---|
|
||
| `layers` | o que de fato rodou na análise | **leia primeiro** — ver `07-analise-incompleta.md` |
|
||
| `summary` | forma da peça, `peak_moments`, contagens | visão geral em poucos números |
|
||
| `speakers` | quem fala, % do tempo, frases de exemplo | identificar papéis |
|
||
| `segments` | cada fala com seus agregados | **onde você mais trabalha** |
|
||
| `segments[].words` | detalhe por palavra | achar o instante exato de um destaque |
|
||
| `scales` | o que cada número significa | documentação dentro do próprio arquivo |
|
||
|
||
## Campos que decidem quase tudo
|
||
|
||
**`gap_before`** — silêncio antes da fala, em segundos. É o mapa estrutural
|
||
da gravação: acima de ~3s (`take_boundary: true`) a câmera parou ou a
|
||
tomada recomeçou. Num material real de 3min17s isso identificou 6
|
||
fronteiras, todas exatamente onde a pessoa recomeçava o roteiro.
|
||
|
||
**`take_boundary`** — booleano derivado do `gap_before`. Use para agrupar
|
||
tomadas.
|
||
|
||
**`emphasis`** (0–1) — índice combinado de energia, variação de tom,
|
||
variação de ritmo, pausa anterior e duração. **É relativo ao material
|
||
analisado**, nunca uma medida absoluta. Ver `02-enfase-e-reanalise.md`.
|
||
|
||
**`energy`** (0–1) — intensidade relativa ao trecho mais alto da gravação.
|
||
|
||
**`pitch_delta`** (0–1) — quanto o tom se afasta da média do falante.
|
||
|
||
**`peak_emphasis`** e **`avg_energy`** (por segmento) — permitem julgar uma
|
||
frase inteira sem ler palavra por palavra. É por aqui que você avalia o
|
||
arco narrativo.
|
||
|
||
**`energy_raw`** e **`pitch_hz`** — valores brutos, sem normalização. Não
|
||
use para decidir; existem para permitir a reanálise da Fase 2.
|
||
|
||
## O que NÃO fazer
|
||
|
||
- **Não recalcule** energia, tom ou ênfase. O sistema mede melhor e de
|
||
forma reprodutível.
|
||
- **Não reestime tempos "no olho".** Use os timestamps do JSON.
|
||
- **Não trate `emphasis` como valor absoluto.** Um 0,35 pode ser o pico de
|
||
uma gravação e ruído em outra.
|
||
|
||
## 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.
|
||
|
||
Isso não é "reestimar no olho" — é um bug de medição na fonte, não um
|
||
julgamento seu. Na prática:
|
||
|
||
- 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
|
||
de decidir, ou confira com `ffmpeg -af astats` se a precisão importar
|
||
para o frame.
|
||
- **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.
|