Files
jhonny-editor/code/engine/integracoes/visual/README.md
T
João Henrique c1b544f4b5 feat: reorganizado o fluxo de edição para validar a análise do Sca
- reorganizado o fluxo de edição para validar a análise do Scanner, selecionar o tipo de vídeo e enviar suas instruções no JSON.
- banco de análises: métricas de fala viraram colunas, busca lexical FTS5, enunciados com embeddings, views achatadas de leitura (fala/palavra/linha do tempo/fala com visual), ingestor do pipeline de voz e gravação idempotente de evidências visuais e cenas.
- retakes passam a ser gravados no banco de análises (SQLite) em vez de JSON por caso, com status de revisão persistido.
- planos de edição e suas aplicações passam a ser registrados no banco, em vez de se perderem no arquivo temporário.
- comando de limpeza das evidências visuais e cenas duplicadas por execuções antigas do Scanner.
- análise visual: OpenCV (rostos) e PySceneDetect passam a entrar no detector local por padrão; novo adapter InsightFace gera assinatura facial (embedding) para reconhecer a mesma pessoa entre tomadas, gravada como evidência visual no banco.
- corrigido: métricas de fala (energia, pitch, velocidade) agora gravam nas colunas dedicadas, não só no JSON; a view fala+visual passa a casar por vídeo e tempo, já que o mesmo arquivo entra na timeline como clipes distintos de vídeo e áudio; views são recriadas a cada abertura do banco para uma correção de consulta chegar a bancos já existentes.
- reordenadas as abas do painel CEP para Scanner, Refinar e Editar vídeo

Resumo:
- 24 arquivos alterados
- 9 novos
- 15 modificados
- 0 removidos

 15 files changed, 872 insertions(+), 29 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/engine/aplicar_plano_de_edicao.py
  - code/engine/integracoes/visual/README.md
  - code/engine/integracoes/visual/__init__.py
  - code/engine/integracoes/visual/analisadores.py
  - code/engine/persistencia/__init__.py
  - code/engine/persistencia/esquema.py
  - code/engine/persistencia/repositorio_de_analises_sqlite.py
  - code/engine/persistencia/repositorio_de_retakes_sqlite.py
  - code/engine/requirements-visual.txt
  - code/engine/scanner/configuracao_visual.py
  - code/engine/scanner/visual.py
  - code/engine/testes/test_analise_visual_local.py
  - .jhonny/analises.db.pos-scanner-084841
  - code/engine/integracoes/embeddings/
  - code/engine/limpar_duplicatas.py
  - code/engine/persistencia/busca_de_conteudo.py
  - code/engine/persistencia/enunciados.py
  - code/engine/persistencia/ingestao_de_voz.py
  - code/engine/persistencia/limpeza.py
  - code/engine/persistencia/repositorio_de_planos.py
  - code/engine/testes/test_busca_de_conteudo.py
2026-09-10 08:58:22 -04:00

177 lines
8.0 KiB
Markdown

# Análise visual local
## Configuração no painel
A configuração do Scanner é apresentada na aba **Scanner** do painel CEP em
`code/cep-plugin/`. O perfil salvo segue o contrato versionado de
`ConfiguracaoVisualDoScanner`; ele define amostragem, faixas, recursos Vision,
cenas, continuidade, reenquadramento e interpretação antes de montar os
adapters.
## Acesso à timeline do Premiere
Quando a análise precisar ler a timeline, a sequência ativa, as faixas ou os
clipes do Premiere, use sempre a classe existente
`engine.integracoes.premiere.leitura.AcessoAoEditor`. O módulo visual não deve
criar chamadas MCP, abrir processos do Premiere ou acessar o bridge diretamente.
O acesso deve seguir esta composição:
```python
from engine.integracoes.premiere.leitura import AcessoAoEditor, AcessoATimeline
from engine.scanner import DescobertaDaTimeline
from engine.integracoes.premiere.conversores import ConversorDeTimeline
acesso_ao_editor = AcessoAoEditor(AcessoATimeline(cliente_mcp))
descoberta = DescobertaDaTimeline(acesso_ao_editor, ConversorDeTimeline())
```
Depois, a timeline convertida entra no `ContextoDeAnalise` e o Scanner executa
`AnaliseVisualDaTimeline`. A classe de acesso isola o MCP e preserva a separação
entre a integração com o Premiere e os analyzers locais.
Não duplicar esse acesso em novos adapters ou analyzers. Para testes, injetar um
fake de `AcessoAoEditor`/`AcessoATimeline` ou usar uma timeline de domínio pronta.
## Captura para análise visual
A análise visual não exporta um frame renderizado pelo Premiere. Para cada clipe
de vídeo, o fluxo usa os campos retornados pelo MCP em `get_active_sequence`:
1. `sourceFile` identifica o arquivo original do `projectItem`.
2. `inPoint` e `outPoint` delimitam o trecho usado pelo clipe.
3. O extrator abre `sourceFile` localmente e amostra o primeiro frame do trecho,
usando `inPoint` como tempo inicial na origem.
4. Vision/OpenCV/ONNX recebem esse frame persistido, mantendo o timestamp de
origem; nenhum frame é exportado da timeline do Premiere.
Portanto, `start`/`end` são tempos da timeline e `inPoint`/`outPoint` são tempos
do arquivo original. Não misturar esses relógios ao analisar um clipe.
O Scanner usa apenas as interfaces em `contratos.py`. As bibliotecas externas
ficam em adapters concretos, para que possam ser habilitadas, substituídas ou
testadas isoladamente.
| Papel | Adapter |
| --- | --- |
| Extrair frames | `ExtratorDeQuadrosOpenCV` |
| Medir qualidade | `AnalisadorDeQualidadeOpenCV` |
| Rosto e olhos visíveis | `AnalisadorDeRostosOpenCV` |
| Composição e área para legendas | `AnalisadorDeComposicaoOpenCV` |
| Tremor/movimento de câmera | `AnalisadorDeTremorOpenCV` |
| Continuidade e frame congelado | `AnalisadorDeContinuidadeOpenCV` |
| Detectar objetos | `AnalisadorDeObjetosONNX` |
| Detectar pose e mãos | `AnalisadorDePoseMediaPipe` |
| Reconhecer a mesma pessoa entre tomadas (assinatura facial) | `AnalisadorDeRostosInsightFace` |
| OCR e faces macOS | `AnalisadorAppleVision` |
| Vision + Apple Intelligence (Swift isolado) | `AnalisadorAppleVisionNativo` |
| Similaridade temporal por feature print | `AnalisadorSequenciaAppleVisionNativo` |
| Extrair frames para Vision sem OpenCV | `ExtratorDeQuadrosFFmpeg` |
| Detectar cenas | `DetectorDeCenasPySceneDetect` |
`AnalisadorDeObjetosONNX` exige dois adapters específicos do modelo:
`preparar(imagem, entradas)` e `decodificar(saidas, quadro)`. Isso mantém os
detalhes de cada arquivo ONNX fora do Scanner e permite trocar de modelo sem
alterar a interface do domínio.
`AnalisadorDePoseMediaPipe` recebe caminhos explícitos para os arquivos `.task`
de pose e mãos. Os modelos ficam em `/Volumes/Merongo/SISTEMAS/MODELOSIA/mediapipe/`
e não são acoplados ao pacote Python. Ele executa em subprocesso: falhas nativas
do MediaPipe são contidas e retornam como indisponibilidade do adapter, sem
encerrar o processo do Scanner.
`AnalisadorDeRostosOpenCV` usa os arquivos locais
`haarcascade_frontalface_default.xml` e `haarcascade_eye.xml`. Quando a
distribuição do OpenCV não os incluir, forneça `diretorio_de_modelos` apontando
para a pasta que os contém. Ele entra automaticamente no detector local
(`criar_detector_visual_local`) quando `"faces"` está em `recursos_vision`
(padrão do perfil).
`AnalisadorDeRostosInsightFace` resolve o que nem o OpenCV nem o Apple Vision
fazem: reconhecer que o rosto de um clipe é a mesma pessoa de outro clipe. Ele
devolve duas evidências por rosto — `rosto` (mesma forma de bounding box dos
outros adapters) e `identidade_facial` (com `assinatura_facial`, um vetor de
512 posições, mais `idade_aproximada`/`genero_aparente` quando o modelo os
estimar). Aceita tanto o frame decodificado em `quadro.imagem` (pipeline
OpenCV) quanto um frame persistido em `quadro.caminho` (pipeline Apple
Vision/FFmpeg), lendo o PNG com OpenCV nesse segundo caso. Por ser mais pesado
(baixa o modelo `buffalo_l` na primeira execução), só entra nos detectores
locais e no detector Apple Vision quando `perfil.identidade_facial=True` —
desligado por padrão.
`AnalisadorAppleVisionNativo` é a opção Apple recomendada. Seu runner Swift
executa faces/landmarks, qualidade facial, pessoas, pose, mãos, OCR,
classificação e estética de forma independente. A interpretação editorial pelo
`FoundationModels` só é criada a partir dessas evidências e é salva em separado.
Falhas nativas por recurso viram `diagnostico_apple_vision`, sem derrubar o
Scanner nem descartar os fatos que funcionaram.
Além de rostos, pessoas, pose, mãos, OCR, categorias e estética, o runner
Apple retorna códigos/QR, horizonte, retângulos, densidade de contornos,
ocupação da máscara de pessoas e similaridade visual entre frames. Os valores
são fatos normalizados; descrição, contexto e ação devem ser derivados depois,
a partir dessas evidências temporizadas.
## Montagem
```python
from engine.integracoes.visual import (
AnalisadorDeQualidadeOpenCV,
AnalisadorDeRostosOpenCV,
AnalisadorDeComposicaoOpenCV,
AnalisadorDeTremorOpenCV,
AnalisadorDeContinuidadeOpenCV,
DetectorDeCenasPySceneDetect,
ExtratorDeQuadrosOpenCV,
)
from engine.scanner.visual import DetectorDeCenas
detector = DetectorDeCenas(
ExtratorDeQuadrosOpenCV(intervalo_em_segundos=1.0, diretorio_de_cache=".frames"),
analisadores_de_frame=[
AnalisadorDeQualidadeOpenCV(), AnalisadorDeRostosOpenCV(),
AnalisadorDeComposicaoOpenCV(),
],
analisadores_de_sequencia=[
AnalisadorDeTremorOpenCV(), AnalisadorDeContinuidadeOpenCV(),
],
detectores_de_intervalo=[DetectorDeCenasPySceneDetect()],
)
```
Depois, passe esse `DetectorDeCenas` para `AnaliseVisualDaTimeline` ao montar o
`PipelineDoScanner`.
Para o caminho local padrão, a montagem pode ser reduzida a:
```python
from engine.scanner import AnaliseVisualDaTimeline, PipelineDoScanner, criar_detector_visual_local
pipeline = PipelineDoScanner([AnaliseVisualDaTimeline(criar_detector_visual_local())])
contexto = pipeline.executar(contexto)
```
O resultado fica em `contexto.caracteristicas_visuais` (por clipe),
`contexto.cenas_visuais` (cenas com observações) e `contexto.avisos`.
Quando OpenCV/FFmpeg ou outro adapter opcional não estiver disponível, o clipe
é marcado com `disponivel=False` e os demais continuam sendo processados.
## Montagem recomendada para Apple Vision
```python
from engine.scanner import AnaliseVisualDaTimeline, PipelineDoScanner, criar_detector_apple_vision
pipeline = PipelineDoScanner([
AnaliseVisualDaTimeline(criar_detector_apple_vision(intervalo_em_segundos=1.0)),
])
```
Esse detector extrai PNGs do arquivo original com FFmpeg, usando o intervalo
`inPoint`/`outPoint` do clipe, e não exporta imagens renderizadas pelo Premiere.
Ele também recua a amostra no fim de vídeos muito curtos quando não há um frame
decodificável exatamente no timestamp solicitado.
Os analyzers de sequência não tentam concluir a intenção de uma pessoa. Eles
retornam indícios temporais (`possivel_tremor`, `possivel_descontinuidade` e
`possivel_frame_congelado`) para que a camada editorial decida como tratá-los.