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:
@@ -13,7 +13,13 @@ import sqlite3
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
|
||||
from ..scanner.retakes.modelos_de_retakes import EvidenciaDeRetake, GrupoDeRetake, TomadaDeRetake
|
||||
from ..scanner.retakes.modelos_de_retakes import (
|
||||
STATUS_DE_REVISAO_VALIDOS,
|
||||
EvidenciaDeRetake,
|
||||
GrupoDeRetake,
|
||||
TomadaDeRetake,
|
||||
)
|
||||
from ..scanner.retakes.repositorio_de_retakes import GrupoDeRetakeInexistente
|
||||
from .conexao import abrir_banco
|
||||
|
||||
VERSAO_REGRA_FALAS = 1
|
||||
@@ -70,10 +76,10 @@ class RepositorioDeRetakesSQLite:
|
||||
for grupo in grupos:
|
||||
self.conexao.execute(
|
||||
"""INSERT INTO grupos_de_retake
|
||||
(id, video_id, faixa_id, tipo, confianca, criado_em)
|
||||
VALUES (?, ?, ?, ?, ?, ?)""",
|
||||
(id, video_id, faixa_id, tipo, confianca, criado_em, status_de_revisao)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)""",
|
||||
(grupo.id, grupo.video_id, grupo.faixa_id, grupo.tipo,
|
||||
grupo.confianca, grupo.criado_em),
|
||||
grupo.confianca, grupo.criado_em, grupo.status_de_revisao),
|
||||
)
|
||||
for tomada in grupo.tomadas:
|
||||
self.conexao.execute(
|
||||
@@ -143,5 +149,46 @@ class RepositorioDeRetakesSQLite:
|
||||
tomadas=tomadas,
|
||||
evidencias=evidencias,
|
||||
criado_em=linha["criado_em"],
|
||||
status_de_revisao=linha["status_de_revisao"],
|
||||
))
|
||||
return grupos
|
||||
|
||||
def atualizar_status_de_revisao(
|
||||
self, video_id: str, grupo_id: str, novo_status: str,
|
||||
) -> GrupoDeRetake:
|
||||
"""
|
||||
Registra a decisão manual do usuário sobre um grupo de retakes.
|
||||
|
||||
A revisão não altera a detecção automática: grava apenas o estado
|
||||
escolhido, preservando os demais grupos do vídeo.
|
||||
|
||||
Parâmetros:
|
||||
video_id: Vídeo dono do grupo revisado.
|
||||
grupo_id: Grupo que recebeu a decisão.
|
||||
novo_status: Estado escolhido pelo usuário.
|
||||
|
||||
Retorna:
|
||||
O grupo já com o novo status.
|
||||
|
||||
Pode gerar:
|
||||
ValueError: quando o status não é um dos válidos.
|
||||
GrupoDeRetakeInexistente: quando o grupo não existe no vídeo.
|
||||
"""
|
||||
if novo_status not in STATUS_DE_REVISAO_VALIDOS:
|
||||
validos = ", ".join(sorted(STATUS_DE_REVISAO_VALIDOS))
|
||||
raise ValueError(
|
||||
f"Status de revisão inválido: {novo_status!r}. Válidos: {validos}."
|
||||
)
|
||||
with self.conexao:
|
||||
cursor = self.conexao.execute(
|
||||
"""UPDATE grupos_de_retake SET status_de_revisao = ?
|
||||
WHERE video_id = ? AND id = ?""",
|
||||
(novo_status, video_id, grupo_id),
|
||||
)
|
||||
if cursor.rowcount == 0:
|
||||
raise GrupoDeRetakeInexistente(video_id, grupo_id)
|
||||
grupo = next(
|
||||
(item for item in self.carregar(video_id) if item.id == grupo_id), None)
|
||||
if grupo is None:
|
||||
raise GrupoDeRetakeInexistente(video_id, grupo_id)
|
||||
return grupo
|
||||
|
||||
Reference in New Issue
Block a user