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
This commit is contained in:
@@ -56,6 +56,10 @@ class ConfiguracaoVisualDoScanner:
|
||||
# Limita quantos frames por clipe recebem a interpretação editorial da Apple
|
||||
# Intelligence (Foundation Models) — a etapa mais cara. None interpreta todos.
|
||||
maximo_de_frames_interpretados: int | None = None
|
||||
# Assinatura facial (InsightFace) — desligada por padrão. Nem o OpenCV nem
|
||||
# o Apple Vision reconhecem que o mesmo rosto aparece em clipes diferentes;
|
||||
# esse recurso existe só para isso, então fica fora do custo padrão.
|
||||
identidade_facial: bool = False
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.modo_de_analise not in {"som", "imagem", "ambos"}:
|
||||
@@ -100,6 +104,7 @@ class ConfiguracaoVisualDoScanner:
|
||||
usar_proxy=bool(dados.get("usar_proxy", True)),
|
||||
resolucao_do_proxy=int(dados.get("resolucao_do_proxy", RESOLUCAO_PADRAO_DO_PROXY)),
|
||||
maximo_de_frames_interpretados=_inteiro_ou_nulo(dados.get("maximo_de_frames_interpretados", None)),
|
||||
identidade_facial=bool(dados.get("identidade_facial", False)),
|
||||
)
|
||||
|
||||
def para_dict(self) -> dict[str, Any]:
|
||||
@@ -122,4 +127,5 @@ class ConfiguracaoVisualDoScanner:
|
||||
"usar_proxy": self.usar_proxy,
|
||||
"resolucao_do_proxy": self.resolucao_do_proxy,
|
||||
"maximo_de_frames_interpretados": self.maximo_de_frames_interpretados,
|
||||
"identidade_facial": self.identidade_facial,
|
||||
}
|
||||
|
||||
@@ -190,25 +190,39 @@ def criar_detector_visual_local(
|
||||
AnalisadorDeComposicaoOpenCV,
|
||||
AnalisadorDeContinuidadeOpenCV,
|
||||
AnalisadorDeQualidadeOpenCV,
|
||||
AnalisadorDeRostosOpenCV,
|
||||
ExtratorDeQuadrosOpenCV,
|
||||
)
|
||||
|
||||
perfil = configuracao or ConfiguracaoVisualDoScanner(intervalo_em_segundos=intervalo_em_segundos)
|
||||
|
||||
analisadores_de_frame: list = [
|
||||
AnalisadorDeQualidadeOpenCV(),
|
||||
AnalisadorDeComposicaoOpenCV(),
|
||||
]
|
||||
if "faces" in perfil.recursos_vision:
|
||||
analisadores_de_frame.append(AnalisadorDeRostosOpenCV())
|
||||
if perfil.identidade_facial:
|
||||
analisadores_de_frame.append(_analisador_de_identidade_facial())
|
||||
|
||||
return DetectorDeCenas(
|
||||
ExtratorDeQuadrosOpenCV(
|
||||
intervalo_em_segundos=perfil.intervalo_em_segundos,
|
||||
diretorio_de_cache=diretorio_de_cache,
|
||||
),
|
||||
analisadores_de_frame=[
|
||||
AnalisadorDeQualidadeOpenCV(),
|
||||
AnalisadorDeComposicaoOpenCV(),
|
||||
],
|
||||
analisadores_de_frame=analisadores_de_frame,
|
||||
analisadores_de_sequencia=[AnalisadorDeContinuidadeOpenCV()],
|
||||
detectores_de_intervalo=_detectores_de_cena_do_perfil(perfil),
|
||||
)
|
||||
|
||||
|
||||
def _analisador_de_identidade_facial():
|
||||
"""Monta o analisador InsightFace, compartilhado pelos dois detectores locais."""
|
||||
from ..integracoes.visual import AnalisadorDeRostosInsightFace
|
||||
|
||||
return AnalisadorDeRostosInsightFace()
|
||||
|
||||
|
||||
def criar_detector_apple_vision(
|
||||
diretorio_de_cache: str | None = ".frames",
|
||||
intervalo_em_segundos: float = 1.0,
|
||||
@@ -239,13 +253,17 @@ def criar_detector_apple_vision(
|
||||
extrator, CompactadorDeProxy(), largura_maxima=perfil.resolucao_do_proxy
|
||||
)
|
||||
|
||||
analisadores_de_frame: list = [AnalisadorAppleVisionNativo(
|
||||
recursos=tuple(sorted(perfil.recursos_vision)),
|
||||
interpretar_com_apple_intelligence=perfil.interpretar_cena,
|
||||
maximo_de_frames_interpretados=perfil.maximo_de_frames_interpretados,
|
||||
)]
|
||||
if perfil.identidade_facial:
|
||||
analisadores_de_frame.append(_analisador_de_identidade_facial())
|
||||
|
||||
return DetectorDeCenas(
|
||||
extrator,
|
||||
analisadores_de_frame=[AnalisadorAppleVisionNativo(
|
||||
recursos=tuple(sorted(perfil.recursos_vision)),
|
||||
interpretar_com_apple_intelligence=perfil.interpretar_cena,
|
||||
maximo_de_frames_interpretados=perfil.maximo_de_frames_interpretados,
|
||||
)],
|
||||
analisadores_de_frame=analisadores_de_frame,
|
||||
analisadores_de_sequencia=[AnalisadorSequenciaAppleVisionNativo()]
|
||||
if perfil.analisar_continuidade else [],
|
||||
detectores_de_intervalo=_detectores_de_cena_do_perfil(perfil),
|
||||
|
||||
Reference in New Issue
Block a user