feat: criado repositório jhonny-editor no Gitea
criado repositório jhonny-editor no Gitea adicionado script admin/deploy.command com commit automático atualizado admin/DEV-NOTES.md com template limpo Resumo: - 32 arquivos alterados - 16 novos - 15 modificados - 0 removidos 16 files changed, 638 insertions(+), 61 deletions(-) Arquivos: - code/engine/skills/boas-praticas-oo.md -> .agents/skills/boas-praticas-oo/SKILL.md - AGENTS.md - code/cep-plugin/index.html - code/cep-plugin/main.js - code/cep-plugin/styles.css - code/engine/integracoes/visual/apple_vision.py - code/engine/integracoes/visual/apple_vision_runner.swift - code/engine/integracoes/visual/extrator_ffmpeg.py - code/engine/scanner/__init__.py - code/engine/scanner/configuracao_visual.py - code/engine/scanner/coordenacao/__init__.py - code/engine/scanner/retakes/adaptador_de_falas.py - code/engine/scanner/retakes/agrupador_de_takes.py - code/engine/scanner/retakes/detector_de_reinicios.py - code/engine/scanner/retakes/modelos_de_retakes.py - code/engine/scanner/visual.py - .jhonny/ - .retakes/ - CODING_STANDARDS.md - code/engine/executar_retakes.py - code/engine/persistencia/ - code/engine/scanner/retakes/__init__.py - code/engine/scanner/retakes/carregador_de_artefatos.py - code/engine/scanner/retakes/classificador_de_retakes.py - code/engine/scanner/retakes/coordenador_de_retakes.py - code/engine/scanner/retakes/deteccao_de_retakes.py - code/engine/scanner/retakes/gerador_de_evidencias.py - code/engine/scanner/retakes/repositorio_de_retakes.py - code/engine/testes/test_consultas_de_persistencia.py - code/engine/testes/test_deteccao_de_retakes.py - code/engine/testes/test_persistencia_sqlite.py - code/relatorios/audio/arquivos/92f97877259a86a8095b1eecafdefe357212a12247d04b78df60e0c0ae38b2ea/
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import threading
|
||||
from collections.abc import Callable
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from ..dominio import Clipe
|
||||
@@ -27,12 +29,14 @@ class DetectorDeCenas:
|
||||
analisadores_de_frame: list[AnalisadorDeFrame] | None = None,
|
||||
detectores_de_intervalo: list[DetectorDeIntervalosDeCena] | None = None,
|
||||
analisadores_de_sequencia: list[AnalisadorDeSequenciaDeQuadros] | None = None,
|
||||
ao_progresso: Callable[[int, int], None] | None = None) -> None:
|
||||
ao_progresso: Callable[[int, int], None] | None = None,
|
||||
trabalhadores_em_paralelo: int = 4) -> None:
|
||||
self.extrator = extrator
|
||||
self.analisadores_de_frame = analisadores_de_frame or []
|
||||
self.analisadores_de_sequencia = analisadores_de_sequencia or []
|
||||
self.detectores_de_intervalo = detectores_de_intervalo or []
|
||||
self.ao_progresso = ao_progresso
|
||||
self.trabalhadores_em_paralelo = max(1, trabalhadores_em_paralelo)
|
||||
|
||||
def detectar(self, clipe: Clipe) -> ResultadoVisualDoClipe:
|
||||
quadros = self.extrator.extrair(clipe)
|
||||
@@ -49,12 +53,24 @@ class DetectorDeCenas:
|
||||
|
||||
def _analisar_quadros(self, quadros: list[QuadroDeVideo], progresso: list[int] | None = None,
|
||||
total: int = 0) -> list[EvidenciaVisual]:
|
||||
resultado: list[EvidenciaVisual] = []
|
||||
for quadro in quadros:
|
||||
for analisador in self.analisadores_de_frame:
|
||||
resultado.extend(analisador.analisar(quadro))
|
||||
if not self.analisadores_de_frame or not quadros:
|
||||
return []
|
||||
tarefas = [(quadro, analisador) for quadro in quadros for analisador in self.analisadores_de_frame]
|
||||
travamento = threading.Lock()
|
||||
|
||||
def processar(tarefa: tuple[QuadroDeVideo, AnalisadorDeFrame]) -> list[EvidenciaVisual]:
|
||||
quadro, analisador = tarefa
|
||||
evidencias = analisador.analisar(quadro)
|
||||
with travamento:
|
||||
self._avancar_progresso(progresso, total)
|
||||
return resultado
|
||||
return evidencias
|
||||
|
||||
if self.trabalhadores_em_paralelo == 1 or len(tarefas) == 1:
|
||||
resultados = [processar(tarefa) for tarefa in tarefas]
|
||||
else:
|
||||
with ThreadPoolExecutor(max_workers=self.trabalhadores_em_paralelo) as executor:
|
||||
resultados = list(executor.map(processar, tarefas))
|
||||
return [evidencia for lista in resultados for evidencia in lista]
|
||||
|
||||
def _analisar_sequencia(self, quadros: list[QuadroDeVideo], progresso: list[int] | None = None,
|
||||
total: int = 0) -> list[EvidenciaVisual]:
|
||||
@@ -134,11 +150,28 @@ class AnaliseVisualDaTimeline:
|
||||
return contexto
|
||||
|
||||
|
||||
def _detectores_de_cena_do_perfil(perfil: ConfiguracaoVisualDoScanner) -> list:
|
||||
"""Monta os detectores de intervalo de cena ativos para o perfil.
|
||||
|
||||
A análise visual auxiliar (PySceneDetect) é opcional. Só entra como um
|
||||
``DetectorDeIntervalosDeCena`` quando a configuração a ativa — e nunca
|
||||
decide sozinho se há retake.
|
||||
"""
|
||||
from ..integracoes.visual import DetectorDeCenasPySceneDetect
|
||||
|
||||
detectores: list = []
|
||||
if getattr(perfil, "usar_analise_visual", False) and getattr(perfil, "detectar_cortes", True):
|
||||
detectores.append(DetectorDeCenasPySceneDetect(limiar=perfil.limiar_de_corte))
|
||||
return detectores
|
||||
|
||||
|
||||
def criar_detector_visual_local(
|
||||
diretorio_de_cache: str | None = ".frames",
|
||||
intervalo_em_segundos: float = 1.0,
|
||||
configuracao: ConfiguracaoVisualDoScanner | None = None,
|
||||
) -> DetectorDeCenas:
|
||||
"""Monta o detector local padrão com uma interface curta para o Scanner."""
|
||||
from .configuracao_visual import ConfiguracaoVisualDoScanner
|
||||
from ..integracoes.visual import (
|
||||
AnalisadorDeComposicaoOpenCV,
|
||||
AnalisadorDeContinuidadeOpenCV,
|
||||
@@ -146,9 +179,11 @@ def criar_detector_visual_local(
|
||||
ExtratorDeQuadrosOpenCV,
|
||||
)
|
||||
|
||||
perfil = configuracao or ConfiguracaoVisualDoScanner(intervalo_em_segundos=intervalo_em_segundos)
|
||||
|
||||
return DetectorDeCenas(
|
||||
ExtratorDeQuadrosOpenCV(
|
||||
intervalo_em_segundos=intervalo_em_segundos,
|
||||
intervalo_em_segundos=perfil.intervalo_em_segundos,
|
||||
diretorio_de_cache=diretorio_de_cache,
|
||||
),
|
||||
analisadores_de_frame=[
|
||||
@@ -156,6 +191,7 @@ def criar_detector_visual_local(
|
||||
AnalisadorDeComposicaoOpenCV(),
|
||||
],
|
||||
analisadores_de_sequencia=[AnalisadorDeContinuidadeOpenCV()],
|
||||
detectores_de_intervalo=_detectores_de_cena_do_perfil(perfil),
|
||||
)
|
||||
|
||||
|
||||
@@ -174,11 +210,13 @@ def criar_detector_apple_vision(
|
||||
|
||||
return DetectorDeCenas(
|
||||
ExtratorDeQuadrosFFmpeg(intervalo_em_segundos=perfil.intervalo_em_segundos,
|
||||
diretorio_de_cache=diretorio_de_cache or ".frames"),
|
||||
diretorio_de_cache=diretorio_de_cache or ".frames",
|
||||
resolucao_maxima=perfil.resolucao_maxima),
|
||||
analisadores_de_frame=[AnalisadorAppleVisionNativo(
|
||||
recursos=tuple(sorted(perfil.recursos_vision)),
|
||||
interpretar_com_apple_intelligence=perfil.interpretar_cena,
|
||||
)],
|
||||
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