Marcus Vinicius Zerbini Canhaço
feat: versão inicial limpa
8fb6272
raw
history blame
7.12 kB
from dataclasses import dataclass
from typing import Optional, Dict, Any
from ...domain.interfaces.detector import DetectorInterface
from ...domain.interfaces.notification import NotificationFactory
from ...domain.entities.detection import DetectionResult
import logging
logger = logging.getLogger(__name__)
@dataclass
class ProcessVideoRequest:
"""DTO para requisição de processamento de vídeo."""
video_path: str
threshold: float = 0.5
fps: Optional[int] = None
resolution: Optional[int] = None
notification_type: Optional[str] = None
notification_target: Optional[str] = None
@dataclass
class ProcessVideoResponse:
"""DTO para resposta do processamento de vídeo."""
status_message: str
detection_result: DetectionResult
memory_info: str
device_info: str
cache_stats: Optional[Dict[str, Any]] = None
class ProcessVideoUseCase:
"""Caso de uso para processamento de vídeo e notificação."""
def __init__(
self,
detector: DetectorInterface,
notification_factory: NotificationFactory,
default_fps: int,
default_resolution: int
):
self.detector = detector
self.notification_factory = notification_factory
self.default_fps = default_fps
self.default_resolution = default_resolution
def execute(self, request: ProcessVideoRequest) -> ProcessVideoResponse:
"""Executa o processamento do vídeo e envia notificações se necessário."""
try:
# Usar valores padrão se não especificados
fps = request.fps or self.default_fps
resolution = request.resolution or self.default_resolution
# Processar vídeo
output_path, result = self.detector.process_video(
request.video_path,
fps=fps,
threshold=request.threshold,
resolution=resolution
)
# Enviar notificação se houver detecções e destino configurado
if result.detections and request.notification_type and request.notification_target:
notification_service = self.notification_factory.create_service(request.notification_type)
if notification_service:
detection_data = {
'detections': [
{
'label': det.label,
'confidence': det.confidence,
'box': det.box,
'timestamp': det.timestamp
} for det in result.detections
],
'technical': {
'threshold': request.threshold,
'fps': fps,
'resolution': resolution
}
}
notification_service.send_notification(detection_data, request.notification_target)
# Formatar mensagem de status
status_msg = self._format_status_message(result)
# Obter informações do sistema de forma segura
try:
device_info = self.detector.get_device_info() if hasattr(self.detector, 'get_device_info') else {}
except Exception as e:
logger.error(f"Erro ao obter informações do dispositivo: {str(e)}")
device_info = {}
try:
cache_stats = self.detector.get_cache_stats() if hasattr(self.detector, 'get_cache_stats') else {}
except Exception as e:
logger.error(f"Erro ao obter estatísticas do cache: {str(e)}")
cache_stats = {}
# Limpar memória
try:
self.detector.clean_memory()
except Exception as e:
logger.error(f"Erro ao limpar memória: {str(e)}")
return ProcessVideoResponse(
status_message=status_msg,
detection_result=result,
memory_info=self._format_memory_info(device_info),
device_info=self._format_device_info(device_info),
cache_stats=cache_stats
)
except Exception as e:
logger.error(f"Erro ao executar caso de uso: {str(e)}")
# Criar um resultado vazio em caso de erro
empty_result = DetectionResult(
video_path=request.video_path,
detections=[],
frames_analyzed=0,
total_time=0.0,
device_type="Unknown",
frame_extraction_time=0.0,
analysis_time=0.0
)
return ProcessVideoResponse(
status_message="Erro ao processar o vídeo. Por favor, tente novamente.",
detection_result=empty_result,
memory_info="N/A",
device_info="N/A",
cache_stats={}
)
def _format_status_message(self, result: DetectionResult) -> str:
"""Formata a mensagem de status do processamento."""
try:
status = "⚠️ RISCO DETECTADO" if result.detections else "✅ SEGURO"
message = f"""Processamento concluído! ({result.device_type})
Status: {status}
Detecções: {len(result.detections)}
Frames analisados: {result.frames_analyzed}
Tempo total: {result.total_time:.2f}s
Tempo de extração: {result.frame_extraction_time:.2f}s
Tempo de análise: {result.analysis_time:.2f}s"""
# Adicionar detalhes das detecções se houver
if result.detections:
message += "\n\nDetecções encontradas:"
for i, det in enumerate(result.detections[:3], 1): # Mostrar até 3 detecções
message += f"\n{i}. {det.label} (Confiança: {det.confidence:.1%}, Frame: {det.frame})"
if len(result.detections) > 3:
message += f"\n... e mais {len(result.detections) - 3} detecção(ões)"
return message
except Exception as e:
logger.error(f"Erro ao formatar mensagem de status: {str(e)}")
return "Erro ao processar o vídeo. Por favor, tente novamente."
def _format_memory_info(self, device_info: Dict[str, Any]) -> str:
if device_info.get('type') == 'GPU':
return f"GPU: {device_info.get('memory_used', 0) / 1024**2:.1f}MB / {device_info.get('memory_total', 0) / 1024**2:.1f}MB"
else:
return f"RAM: {device_info.get('memory_used', 0) / 1024**2:.1f}MB / {device_info.get('memory_total', 0) / 1024**2:.1f}MB"
def _format_device_info(self, device_info: Dict[str, Any]) -> str:
if device_info.get('type') == 'GPU':
return f"GPU: {device_info.get('name', 'Unknown')}"
else:
return f"CPU Threads: {device_info.get('threads', 'N/A')}"