import unittest from engine.dominio import IntervaloDeTempo from engine.integracoes.premiere.conversores import ConversorDeTimeline from engine.scanner import ErroDeAnalise from engine.scanner.analise import AnaliseVisual, DeteccaoDeCenas, TranscricaoDeAudio from engine.scanner.modelos import SegmentoDeTranscricao from engine.scanner.coordenacao import AnalisadorDeTimeline, PipelineDoScanner from engine.scanner.descoberta import DescobertaDaTimeline class AcessoAoEditorSimulado: nome = "acesso_ao_editor_simulado" def obter_timeline_ativa(self): return {"id": "seq-1", "name": "Principal", "duration": 10.0, "video_tracks": [{"id": "v1", "name": "V1", "clips": [{"id": "c1", "name": "Camera", "timeline_start": 0.0, "timeline_end": 10.0}]}], "audio_tracks": []} class TestePrimeiraEtapa(unittest.TestCase): def test_intervalo_rejeita_fim_anterior_ao_inicio(self): with self.assertRaises(ValueError): IntervaloDeTempo(2, 1) def test_scanner_descobre_timeline_simulada(self): etapa = DescobertaDaTimeline(AcessoAoEditorSimulado(), ConversorDeTimeline()) contexto = AnalisadorDeTimeline(PipelineDoScanner([etapa])).analisar() self.assertEqual(contexto.timeline.nome, "Principal") self.assertEqual(contexto.timeline.faixas[0].clipes[0].identificador, "c1") self.assertEqual(contexto.analises_concluidas, ["descoberta_da_timeline"]) def test_converte_formato_real_da_timeline_do_premiere(self): dados = {"id": "seq-1", "name": "Principal", "frameSizeHorizontal": 3840, "frameSizeVertical": 2160, "end": 196.66, "videoTracks": [{"index": 0, "name": "Vídeo 1", "clips": [ {"nodeId": "clip-1", "name": "camera.mp4", "start": 0, "end": 196.66, "inPoint": 0, "outPoint": 196.66}]}], "audioTracks": [{"index": 0, "name": "Áudio 1", "clips": []}]} timeline = ConversorDeTimeline().converter(dados) self.assertEqual((timeline.largura, timeline.altura), (3840, 2160)) self.assertEqual(timeline.faixas[0].clipes[0].identificador, "clip-1") self.assertEqual(timeline.faixas[0].clipes[0].intervalo_na_origem.fim, 196.66) def test_preserva_midia_offline_sem_interromper_a_timeline(self): dados = {"id": "seq-1", "videoTracks": [{"clips": [ {"id": "c1", "name": "offline.mov", "start": 0, "end": 2, "offline": True} ]}]} clipe = ConversorDeTimeline().converter(dados).faixas[0].clipes[0] self.assertTrue(clipe.offline) self.assertIsNone(clipe.intervalo_na_origem) def test_resposta_incompleta_produz_erro_estruturado(self): with self.assertRaises(ErroDeAnalise) as contexto: ConversorDeTimeline().converter({"id": "seq-1", "videoTracks": [{"clips": [{"id": "c1"}]}]}) self.assertEqual(contexto.exception.codigo, "resposta_incompleta") self.assertEqual(contexto.exception.caminho, "clipes[0]") def test_transcreve_clipes_e_consolida_cenas(self): class TranscritorSimulado: def transcrever(self, clipe): return [SegmentoDeTranscricao(0, clipe.intervalo_na_timeline.duracao, "Olá", 0.98)] class VisaoSimulada: def analisar(self, clipe, quadros=None): return {"confianca": 0.91, "foco": 0.88} etapa = DescobertaDaTimeline(AcessoAoEditorSimulado(), ConversorDeTimeline()) pipeline = PipelineDoScanner([etapa, TranscricaoDeAudio(TranscritorSimulado()), AnaliseVisual(VisaoSimulada()), DeteccaoDeCenas()]) contexto = AnalisadorDeTimeline(pipeline).analisar() self.assertEqual(contexto.transcricoes["c1"][0].texto, "Olá") self.assertEqual(len(contexto.cenas), 1) self.assertEqual(contexto.cenas[0].confianca, 0.91) if __name__ == "__main__": unittest.main()