feat: initial commit - Jhonny Editor

- Adicionado estrutura completa do projeto
- Configurado MCP server para Premiere Pro
- Adicionado documentação e skills
- Configurado Gitignore para o projeto
This commit is contained in:
João Henrique
2026-09-08 09:59:31 -04:00
commit b541f502ba
1507 changed files with 387650 additions and 0 deletions
View File
@@ -0,0 +1,27 @@
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
from engine.integracoes.midia import ExtracaoDeAudio
class TesteExtracaoDeAudio(unittest.TestCase):
def test_rejeita_arquivo_inexistente(self):
with self.assertRaises(FileNotFoundError):
ExtracaoDeAudio().extrair("/arquivo/inexistente.mp4", "/tmp/audio")
@patch("engine.integracoes.midia.extracao_de_audio.subprocess.run")
def test_prepara_audio_mono_16khz_e_divide_em_partes(self, executar):
executar.side_effect = [type("R", (), {"stdout": "12.0\n"})(), None, None]
with tempfile.TemporaryDirectory() as pasta:
video = Path(pasta) / "video.mp4"
video.write_bytes(b"video")
partes = ExtracaoDeAudio(duracao_da_parte=10).extrair(video, Path(pasta) / "audio")
self.assertEqual([(p.inicio, p.fim) for p in partes], [(0.0, 10.0), (10.0, 12.0)])
comando = executar.call_args_list[1].args[0]
self.assertIn("-ac", comando)
self.assertIn("1", comando)
self.assertIn("-ar", comando)
self.assertIn("16000", comando)
+76
View File
@@ -0,0 +1,76 @@
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()