feat: sincronizado o estado de transcrição, métricas e diarização
- sincronizado o estado de transcrição, métricas e diarização entre SQLite, Scanner e Editar vídeo Resumo: - 6 arquivos alterados - 1 novos - 5 modificados - 0 removidos 5 files changed, 181 insertions(+), 12 deletions(-) Arquivos: - code/cep-plugin/index.html - code/cep-plugin/main.js - code/cep-plugin/styles.css - code/engine/persistencia/consultas.py - code/engine/testes/test_consultas_de_persistencia.py - code/engine/consultar_status_da_analise.py
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
"""Consulta o estado editorial persistido de uma análise do Scanner."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
CAMINHO_DO_CODIGO = Path(__file__).resolve().parent.parent
|
||||
if str(CAMINHO_DO_CODIGO) not in sys.path:
|
||||
sys.path.insert(0, str(CAMINHO_DO_CODIGO))
|
||||
|
||||
from engine.persistencia.consultas import ConsultasDeAnalises
|
||||
|
||||
|
||||
def executar(caminho_do_banco: Path, video_id: str) -> dict:
|
||||
"""Consulta o banco e devolve o estado da análise solicitada."""
|
||||
resultado = ConsultasDeAnalises(caminho_do_banco).consultar_status_da_analise(video_id)
|
||||
if resultado is None:
|
||||
raise ValueError(f"Vídeo não encontrado no banco: {video_id}")
|
||||
return resultado
|
||||
|
||||
|
||||
def principal() -> None:
|
||||
"""Executa a consulta pela linha de comando."""
|
||||
argumentos = argparse.ArgumentParser()
|
||||
argumentos.add_argument("video_id")
|
||||
argumentos.add_argument("--banco", type=Path, default=Path(".jhonny/analises.db"))
|
||||
opcoes = argumentos.parse_args()
|
||||
try:
|
||||
print(json.dumps(executar(opcoes.banco, opcoes.video_id), ensure_ascii=False))
|
||||
except (OSError, ValueError) as erro:
|
||||
print(json.dumps({"erro": str(erro)}, ensure_ascii=False))
|
||||
raise SystemExit(1) from erro
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
principal()
|
||||
@@ -96,6 +96,45 @@ class ConsultasDeAnalises:
|
||||
"total_cenas": contagens["cenas"],
|
||||
}
|
||||
|
||||
def consultar_status_da_analise(self, video_id: str) -> dict | None:
|
||||
"""Devolve o estado compacto das análises de áudio de um vídeo."""
|
||||
self._validar_texto_obrigatorio("video_id", video_id)
|
||||
resumo = self.consultar_resumo_do_video(video_id)
|
||||
if resumo is None:
|
||||
return None
|
||||
linha = self.conexao.execute(
|
||||
"""SELECT
|
||||
COUNT(*) AS falas,
|
||||
SUM(CASE WHEN falante IS NOT NULL AND TRIM(falante) <> '' THEN 1 ELSE 0 END) AS falas_com_falante,
|
||||
SUM(CASE WHEN caracteristicas_acusticas IS NOT NULL
|
||||
AND caracteristicas_acusticas <> '{}'
|
||||
THEN 1 ELSE 0 END) AS falas_com_metricas
|
||||
FROM segmentos_de_transcricao
|
||||
WHERE video_id = ?""",
|
||||
(video_id,),
|
||||
).fetchone()
|
||||
falantes = [
|
||||
item["falante"] for item in self.conexao.execute(
|
||||
"""SELECT DISTINCT falante
|
||||
FROM segmentos_de_transcricao
|
||||
WHERE video_id = ? AND falante IS NOT NULL AND TRIM(falante) <> ''
|
||||
ORDER BY falante""",
|
||||
(video_id,),
|
||||
).fetchall()
|
||||
]
|
||||
return {
|
||||
**resumo,
|
||||
"audio": {
|
||||
"transcricao_disponivel": bool(linha["falas"]),
|
||||
"total_falas": linha["falas"] or 0,
|
||||
"falas_com_falante": linha["falas_com_falante"] or 0,
|
||||
"falas_com_metricas": linha["falas_com_metricas"] or 0,
|
||||
"diarizacao_disponivel": bool(linha["falas_com_falante"]),
|
||||
"metricas_de_voz_disponiveis": bool(linha["falas_com_metricas"]),
|
||||
"falantes": falantes,
|
||||
},
|
||||
}
|
||||
|
||||
def listar_falas_no_intervalo(
|
||||
self,
|
||||
video_id: str,
|
||||
|
||||
@@ -95,6 +95,16 @@ class TesteConsultasDeAnalises(unittest.TestCase):
|
||||
with self.assertRaises(ErroDeConsultaInvalida):
|
||||
self.consultas.consultar_resumo_do_video("")
|
||||
|
||||
def test_consultar_status_da_analise_expoe_falantes_e_metricas(self) -> None:
|
||||
status = self.consultas.consultar_status_da_analise(VIDEO_ID)
|
||||
|
||||
self.assertEqual(status["audio"]["total_falas"], 1)
|
||||
self.assertEqual(status["audio"]["falas_com_falante"], 1)
|
||||
self.assertEqual(status["audio"]["falas_com_metricas"], 0)
|
||||
self.assertTrue(status["audio"]["diarizacao_disponivel"])
|
||||
self.assertFalse(status["audio"]["metricas_de_voz_disponiveis"])
|
||||
self.assertEqual(status["audio"]["falantes"], ["locutor"])
|
||||
|
||||
# --- listar_falas_no_intervalo ------------------------------------------------------
|
||||
|
||||
def test_listar_falas_no_intervalo_filtra_por_tempo_e_omite_palavras_por_padrao(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user