A seguir está um documento-base completo para orientar o desenvolvimento do **primeiro módulo funcional do sistema: leitura da timeline do Premiere por meio do MCP**. Ele foi estruturado para servir como especificação técnica, guia de implementação e referência para os próximos módulos. # Módulo de leitura da timeline do Premiere via MCP ## 1. Objetivo do módulo O objetivo deste primeiro módulo é permitir que o sistema consiga: 1. Conectar-se ao MCP responsável pela integração com o Premiere; 2. Identificar se o Premiere está acessível; 3. Consultar a sequência ativa; 4. Ler as faixas de vídeo e áudio; 5. Ler os clipes presentes na timeline; 6. Obter as propriedades relevantes de cada clipe; 7. Converter a resposta bruta do MCP para objetos internos do sistema; 8. Validar os dados recebidos; 9. Armazenar o resultado em um modelo de domínio; 10. Disponibilizar essa informação para os próximos módulos do scanner. Este módulo **não deverá realizar cortes, mover clipes, excluir elementos ou tomar decisões de edição**. Ele terá somente a responsabilidade de **ler e representar a timeline atual**. --- # 2. Princípio arquitetural O módulo deverá seguir esta separação: ```text Premiere Pro ↓ MCP do Premiere ↓ ClienteMCP ↓ AcessoAoEditor ↓ ConversorDeTimeline ↓ Modelos do domínio ↓ DescobertaDaTimeline ↓ ContextoDeAnalise ``` Cada camada possui uma responsabilidade específica. | Camada | Responsabilidade | | ---------------------- | ---------------------------------------------------------- | | MCP | Disponibilizar ferramentas para comunicação com o Premiere | | `ClienteMCP` | Executar chamadas técnicas ao MCP | | `AcessoAoEditor` | Expor operações compreensíveis de leitura | | `ConversorDeTimeline` | Converter respostas externas em objetos internos | | Domínio | Representar projeto, sequência, faixas e clipes | | `DescobertaDaTimeline` | Orquestrar a descoberta da timeline | | `ContextoDeAnalise` | Armazenar os dados obtidos pelo scanner | A regra fundamental é: > Nenhuma classe do scanner deverá chamar diretamente uma ferramenta MCP pelo nome técnico. Por exemplo, o scanner não deve fazer isto: ```python cliente_mcp.chamar( "get_active_sequence", {} ) ``` Ele deve fazer isto: ```python timeline = acesso_ao_editor.obter_timeline_ativa() ``` Assim, o scanner não fica dependente da implementação específica do MCP. --- # 3. Escopo da primeira versão A primeira versão deverá implementar somente a leitura. ## Incluído * Conexão com o MCP; * Teste de conectividade; * Leitura da sequência ativa; * Leitura das faixas; * Leitura dos clipes; * Leitura dos dados básicos dos clipes; * Conversão dos dados; * Validação; * Registro de erros; * Retorno estruturado; * Testes com dados simulados. ## Não incluído inicialmente * Corte de clipes; * Exclusão de clipes; * Movimentação de clipes; * Aplicação de plano de edição; * Transcrição; * Análise visual; * Detecção de cenas; * Detecção de retakes; * Análise de áudio; * Decisão automática; * Alteração da timeline; * Execução de comandos destrutivos. Essas funcionalidades serão adicionadas posteriormente. --- # 4. Estrutura inicial de pastas A estrutura inicial recomendada é: ```text projeto/ │ ├── integracoes/ │ └── premiere/ │ ├── __init__.py │ │ │ ├── cliente_mcp.py │ ├── sessao_mcp.py │ ├── erros_mcp.py │ │ │ ├── leitura/ │ │ ├── __init__.py │ │ ├── acesso_ao_editor.py │ │ ├── acesso_a_timeline.py │ │ └── acesso_a_clipes.py │ │ │ ├── conversores/ │ │ ├── __init__.py │ │ ├── conversor_de_timeline.py │ │ ├── conversor_de_faixas.py │ │ └── conversor_de_clipes.py │ │ │ └── contratos/ │ ├── __init__.py │ └── contrato_de_acesso_ao_editor.py │ ├── dominio/ │ ├── __init__.py │ │ │ ├── entidades/ │ │ ├── projeto.py │ │ ├── sequencia.py │ │ ├── timeline.py │ │ ├── faixa.py │ │ └── clipe.py │ │ │ └── objetos_de_valor/ │ ├── intervalo_de_tempo.py │ ├── tipo_de_midia.py │ └── identificador_de_midia.py │ ├── scanner/ │ ├── __init__.py │ │ │ ├── coordenacao/ │ │ ├── analisador_de_timeline.py │ │ ├── pipeline_do_scanner.py │ │ └── contexto_de_analise.py │ │ │ └── descoberta/ │ └── descoberta_da_timeline.py │ ├── configuracao/ │ └── configuracao_do_scanner.py │ └── testes/ ├── integracoes/ ├── dominio/ └── scanner/ ``` Essa é uma estrutura inicial. Ela poderá ser expandida quando o projeto crescer. --- # 5. Classe `ClienteMCP` Arquivo: ```text integracoes/premiere/cliente_mcp.py ``` ## Responsabilidade A classe `ClienteMCP` será responsável exclusivamente pela comunicação técnica com o servidor MCP. Ela deverá: * Estabelecer conexão; * Encerrar conexão; * Executar chamadas; * Enviar argumentos; * Receber respostas; * Controlar timeout; * Detectar erros de comunicação; * Registrar informações técnicas; * Retornar respostas brutas. Ela não deverá: * Interpretar clipes; * Criar objetos de domínio; * Saber o que é uma cena; * Saber o que é um retake; * Decidir qual ferramenta deve ser usada para descobrir a timeline; * Executar regras de negócio. ## Interface conceitual ```python class ClienteMCP: """Responsável pela comunicação técnica com o servidor MCP.""" def conectar(self) -> None: """Estabelece conexão com o servidor MCP.""" def desconectar(self) -> None: """Encerra a conexão com o servidor MCP.""" def esta_conectado(self) -> bool: """Informa se existe uma conexão ativa.""" def chamar( self, nome_da_ferramenta: str, argumentos: dict | None = None, ) -> dict: """Executa uma ferramenta MCP e retorna a resposta bruta.""" ``` ## Exemplo de comportamento ```python cliente = ClienteMCP() cliente.conectar() resposta = cliente.chamar( nome_da_ferramenta="get_active_sequence", argumentos={}, ) cliente.desconectar() ``` O nome `get_active_sequence` é apenas ilustrativo. O nome real deverá ser descoberto a partir das ferramentas efetivamente disponíveis no MCP utilizado. ## Regras 1. Não colocar lógica de conversão nessa classe. 2. Não colocar lógica de domínio nessa classe. 3. Não colocar lógica de scanner nessa classe. 4. Não criar métodos como `detectar_retake()` ou `obter_cenas()`. 5. Não misturar leitura e escrita nessa primeira versão. 6. Centralizar aqui o tratamento técnico de erros MCP. --- # 6. Classe `SessaoMCP` Arquivo: ```text integracoes/premiere/sessao_mcp.py ``` ## Responsabilidade A classe `SessaoMCP` representará o estado da integração com o Premiere. Ela poderá armazenar: * Estado da conexão; * Data da última conexão; * Projeto identificado; * Sequência ativa; * Ferramentas disponíveis; * Última chamada executada; * Último erro ocorrido. ## Interface conceitual ```python class SessaoMCP: """Representa o estado atual da comunicação com o Premiere.""" def __init__(self): self.conectado = False self.projeto_atual = None self.sequencia_ativa = None self.ultima_ferramenta_executada = None self.ultimo_erro = None ``` ## Observação Na primeira implementação, essa classe pode ser simples. Ela não precisa controlar toda a conexão sozinha. Sua função é evitar que informações de estado fiquem espalhadas em várias classes. --- # 7. Classe `ErrosMCP` Arquivo: ```text integracoes/premiere/erros_mcp.py ``` ## Responsabilidade Centralizar os erros relacionados à integração com o MCP. ## Classes sugeridas ```python class ErroMCP(Exception): """Erro genérico relacionado à comunicação com o MCP.""" class ErroDeConexaoMCP(ErroMCP): """Erro ao conectar ou manter conexão com o MCP.""" class ErroDeFerramentaMCP(ErroMCP): """Erro ao executar uma ferramenta MCP.""" class ErroDeRespostaMCP(ErroMCP): """Erro quando a resposta do MCP é inválida ou incompleta.""" class FerramentaMCPNaoEncontrada(ErroMCP): """Erro quando a ferramenta solicitada não está disponível.""" ``` ## Por que isso é importante? Sem erros específicos, o sistema teria apenas: ```python raise Exception("Erro") ``` Com erros específicos, podemos distinguir: * MCP indisponível; * Ferramenta inexistente; * Resposta inválida; * Falta de sequência ativa; * Permissão insuficiente; * Timeout; * Erro interno do Premiere. Isso será importante para o scanner decidir se deve: * Interromper a execução; * Tentar novamente; * Ignorar uma etapa; * Registrar um aviso. --- # 8. Classe `AcessoAoEditor` Arquivo: ```text integracoes/premiere/leitura/acesso_ao_editor.py ``` ## Responsabilidade A classe `AcessoAoEditor` será a principal porta de entrada para as operações de leitura do Premiere. Ela deverá esconder os detalhes do MCP. O restante do sistema deverá trabalhar com métodos de alto nível, como: ```python obter_timeline_ativa() obter_sequencia_ativa() obter_faixas() obter_clipes() obter_detalhes_do_clipe() ``` ## Interface conceitual ```python class AcessoAoEditor: """Fornece operações estruturadas de leitura do editor.""" def obter_timeline_ativa(self): """Obtém os dados da timeline ativa.""" def obter_sequencia_ativa(self): """Obtém os dados da sequência ativa.""" def obter_faixas(self): """Obtém as faixas da sequência ativa.""" def obter_clipes(self): """Obtém os clipes presentes na timeline.""" def obter_detalhes_do_clipe( self, identificador_do_clipe: str, ): """Obtém detalhes de um clipe específico.""" ``` ## O que essa classe não deve fazer Ela não deve: * Converter diretamente para todos os objetos de domínio; * Fazer transcrição; * Detectar cenas; * Executar cortes; * Gerar plano de edição; * Tomar decisões sobre retakes. Sua responsabilidade é fornecer dados de leitura de maneira organizada. --- # 9. Classe `AcessoATimeline` Arquivo: ```text integracoes/premiere/leitura/acesso_a_timeline.py ``` ## Responsabilidade Especializar o acesso à estrutura da timeline. Ela poderá: * Obter a sequência ativa; * Obter informações gerais da timeline; * Obter duração; * Obter taxa de quadros; * Obter resolução; * Obter faixas; * Obter elementos posicionados na timeline. ## Interface conceitual ```python class AcessoATimeline: """Realiza operações de leitura relacionadas à timeline.""" def __init__(self, cliente_mcp): self.cliente_mcp = cliente_mcp def obter_timeline_ativa(self): """Consulta a timeline ativa no Premiere.""" def obter_sequencia_ativa(self): """Consulta a sequência ativa.""" def obter_faixas(self): """Consulta as faixas da sequência ativa.""" ``` ## Exemplo conceitual ```python class AcessoATimeline: """Realiza consultas estruturadas da timeline.""" def __init__(self, cliente_mcp): self.cliente_mcp = cliente_mcp def obter_sequencia_ativa(self): """Obtém a sequência ativa por meio do MCP.""" resposta = self.cliente_mcp.chamar( nome_da_ferramenta="get_active_sequence", argumentos={}, ) return resposta ``` O nome da ferramenta deverá ser substituído pelo nome real fornecido pelo MCP. --- # 10. Classe `AcessoAClipes` Arquivo: ```text integracoes/premiere/leitura/acesso_a_clipes.py ``` ## Responsabilidade Ler os clipes presentes na timeline. Ela deverá obter informações como: * Identificador; * Nome; * Nome do arquivo; * Caminho do arquivo; * Faixa; * Início na timeline; * Fim na timeline; * Duração; * Início utilizado no arquivo original; * Fim utilizado no arquivo original; * Tipo de mídia; * Estado offline; * Velocidade; * Opacidade; * Volume; * Informações de vínculo; * Informações de origem. ## Interface conceitual ```python class AcessoAClipes: """Realiza operações de leitura dos clipes da timeline.""" def __init__(self, cliente_mcp): self.cliente_mcp = cliente_mcp def obter_clipes(self): """Obtém todos os clipes da timeline ativa.""" def obter_detalhes_do_clipe( self, identificador_do_clipe: str, ): """Obtém os detalhes de um clipe específico.""" ``` ## Regra importante A classe deverá retornar dados brutos ou estruturas intermediárias. A conversão para objetos como `Clipe` deverá ser feita pelo conversor. --- # 11. Classe `ConversorDeTimeline` Arquivo: ```text integracoes/premiere/conversores/conversor_de_timeline.py ``` ## Responsabilidade Converter a resposta do MCP para o modelo interno de `Timeline`. O MCP pode retornar nomes e estruturas específicas. O sistema não deve depender diretamente delas. ## Interface conceitual ```python class ConversorDeTimeline: """Converte dados brutos do Premiere em uma timeline do domínio.""" def converter(self, dados_brutos): """Converte os dados externos em uma entidade Timeline.""" ``` ## Exemplo ```python class ConversorDeTimeline: """Converte uma resposta externa em uma Timeline interna.""" def converter(self, dados_brutos): """Cria uma Timeline a partir dos dados recebidos.""" timeline = Timeline( identificador=dados_brutos["id"], nome=dados_brutos["name"], ) return timeline ``` ## Responsabilidades adicionais * Normalizar nomes de campos; * Converter tempos; * Converter identificadores; * Garantir tipos corretos; * Aplicar valores padrão; * Validar campos obrigatórios; * Ignorar campos desconhecidos; * Registrar campos ausentes. --- # 12. Classe `ConversorDeFaixas` Arquivo: ```text integracoes/premiere/conversores/conversor_de_faixas.py ``` ## Responsabilidade Converter as faixas retornadas pelo MCP em objetos `Faixa`. ## Informações esperadas * Identificador; * Nome; * Tipo da faixa; * Índice; * Ordem; * Clipes pertencentes; * Estado de bloqueio; * Estado de visibilidade; * Estado de ativação. ## Interface conceitual ```python class ConversorDeFaixas: """Converte faixas externas em entidades do domínio.""" def converter(self, dados_brutos): """Converte os dados de uma faixa.""" ``` ## Tipos de faixa O domínio deverá distinguir, pelo menos: ```python class TipoDeFaixa(Enum): VIDEO = "video" AUDIO = "audio" DESCONHECIDA = "desconhecida" ``` O tipo real deverá ser ajustado conforme os dados retornados pelo MCP. --- # 13. Classe `ConversorDeClipes` Arquivo: ```text integracoes/premiere/conversores/conversor_de_clipes.py ``` ## Responsabilidade Converter cada clipe externo em uma entidade `Clipe`. ## Interface conceitual ```python class ConversorDeClipes: """Converte dados externos de clipes em entidades do domínio.""" def converter(self, dados_brutos): """Converte um clipe externo em um Clipe.""" ``` ## Exemplo de campos normalizados ```python clipe = Clipe( identificador="clip_001", nome="Camera A", arquivo="video_001.mov", intervalo_na_timeline=IntervaloDeTempo( inicio=10.0, fim=25.0, ), intervalo_na_origem=IntervaloDeTempo( inicio=120.0, fim=135.0, ), identificador_da_faixa="video_1", ) ``` O modelo real deverá ser definido depois de observar uma resposta verdadeira do MCP. --- # 14. Classe `Projeto` Arquivo: ```text dominio/entidades/projeto.py ``` ## Responsabilidade Representar o projeto de edição. ## Campos iniciais * Identificador; * Nome; * Caminho; * Sequências; * Data de leitura; * Metadados adicionais. ## Exemplo ```python class Projeto: """Representa um projeto de edição.""" def __init__( self, identificador, nome, caminho=None, ): self.identificador = identificador self.nome = nome self.caminho = caminho self.sequencias = [] ``` --- # 15. Classe `Sequencia` Arquivo: ```text dominio/entidades/sequencia.py ``` ## Responsabilidade Representar uma sequência de edição. ## Campos iniciais * Identificador; * Nome; * Duração; * Taxa de quadros; * Resolução; * Áudio; * Faixas; * Marcadores; * Metadados. ## Exemplo ```python class Sequencia: """Representa uma sequência de edição.""" def __init__( self, identificador, nome, duracao=None, taxa_de_quadros=None, ): self.identificador = identificador self.nome = nome self.duracao = duracao self.taxa_de_quadros = taxa_de_quadros self.faixas = [] ``` --- # 16. Classe `Timeline` Arquivo: ```text dominio/entidades/timeline.py ``` ## Responsabilidade Representar a estrutura completa da timeline que será analisada. ## Campos iniciais * Identificador; * Nome; * Sequência; * Faixas; * Clipes; * Duração; * Taxa de quadros; * Resolução; * Metadados; * Data da leitura; * Origem dos dados. ## Exemplo ```python class Timeline: """Representa uma timeline de edição.""" def __init__( self, identificador, nome, ): self.identificador = identificador self.nome = nome self.faixas = [] self.clipes = [] self.metadados = {} ``` ## Regras A `Timeline` não deve: * Consultar o MCP; * Ler arquivos; * Executar comandos; * Fazer análise de áudio; * Detectar retakes. Ela apenas representa os dados. --- # 17. Classe `Faixa` Arquivo: ```text dominio/entidades/faixa.py ``` ## Responsabilidade Representar uma faixa de vídeo ou áudio. ## Campos iniciais * Identificador; * Nome; * Tipo; * Índice; * Clipes; * Estado de bloqueio; * Estado de visibilidade; * Estado de ativação. ## Exemplo ```python class Faixa: """Representa uma faixa de vídeo ou áudio.""" def __init__( self, identificador, nome, tipo, indice, ): self.identificador = identificador self.nome = nome self.tipo = tipo self.indice = indice self.clipes = [] ``` --- # 18. Classe `Clipe` Arquivo: ```text dominio/entidades/clipe.py ``` ## Responsabilidade Representar um clipe de mídia presente na timeline. ## Campos iniciais * Identificador; * Nome; * Arquivo de origem; * Caminho do arquivo; * Tipo de mídia; * Faixa; * Intervalo na timeline; * Intervalo na origem; * Duração; * Estado offline; * Velocidade; * Opacidade; * Volume; * Dados de vínculo; * Metadados; * Informações de origem. ## Exemplo ```python class Clipe: """Representa um clipe de mídia na timeline.""" def __init__( self, identificador, nome, intervalo_na_timeline, intervalo_na_origem=None, arquivo=None, identificador_da_faixa=None, ): self.identificador = identificador self.nome = nome self.intervalo_na_timeline = intervalo_na_timeline self.intervalo_na_origem = intervalo_na_origem self.arquivo = arquivo self.identificador_da_faixa = identificador_da_faixa self.metadados = {} ``` --- # 19. Classe `IntervaloDeTempo` Arquivo: ```text dominio/objetos_de_valor/intervalo_de_tempo.py ``` ## Responsabilidade Representar um intervalo temporal válido. Ele será utilizado para: * Posição de clipes; * Duração; * Trechos de áudio; * Segmentos de transcrição; * Cenas; * Retakes; * Operações de corte. ## Exemplo ```python class IntervaloDeTempo: """Representa um intervalo temporal.""" def __init__(self, inicio, fim): if inicio < 0: raise ValueError( "O início não pode ser negativo." ) if fim < inicio: raise ValueError( "O fim não pode ser anterior ao início." ) self.inicio = inicio self.fim = fim @property def duracao(self): """Retorna a duração do intervalo.""" return self.fim - self.inicio ``` ## Métodos futuros ```python def contem(self, instante): """Verifica se um instante está dentro do intervalo.""" def sobrepoe(self, outro): """Verifica se dois intervalos se sobrepõem.""" def intersecao(self, outro): """Retorna a interseção entre dois intervalos.""" ``` --- # 20. Contrato `ContratoDeAcessoAoEditor` Arquivo: ```text integracoes/premiere/contratos/contrato_de_acesso_ao_editor.py ``` ## Responsabilidade Definir o contrato que qualquer integração de editor deverá cumprir. Isso permitirá futuramente utilizar: * Premiere; * OpenCut; * DaVinci Resolve; * Outro editor; * Simulador para testes. ## Exemplo ```python from abc import ABC, abstractmethod class ContratoDeAcessoAoEditor(ABC): """Define operações mínimas de leitura de um editor.""" @abstractmethod def obter_timeline_ativa(self): """Obtém a timeline ativa.""" raise NotImplementedError @abstractmethod def obter_clipes(self): """Obtém os clipes da timeline.""" raise NotImplementedError @abstractmethod def obter_faixas(self): """Obtém as faixas da timeline.""" raise NotImplementedError ``` ## Benefício A classe `DescobertaDaTimeline` poderá depender desse contrato: ```python class DescobertaDaTimeline: """Descobre a timeline por meio de uma integração de editor.""" def __init__(self, acesso_ao_editor): self.acesso_ao_editor = acesso_ao_editor ``` Assim, ela não saberá se os dados vieram do Premiere ou de um simulador. --- # 21. Classe `DescobertaDaTimeline` Arquivo: ```text scanner/descoberta/descoberta_da_timeline.py ``` ## Responsabilidade Orquestrar a descoberta da timeline. Ela deverá: 1. Solicitar a timeline ao acesso do editor; 2. Receber os dados externos; 3. Converter os dados; 4. Validar o resultado; 5. Armazenar a timeline no contexto; 6. Retornar o contexto atualizado. ## Ela não deverá * Chamar diretamente o MCP; * Saber o nome das ferramentas MCP; * Fazer transcrição; * Fazer análise visual; * Detectar retakes; * Aplicar cortes; * Gerar plano de edição. ## Exemplo ```python class DescobertaDaTimeline: """Descobre a estrutura da timeline do editor.""" def __init__( self, acesso_ao_editor, conversor_de_timeline, ): self.acesso_ao_editor = acesso_ao_editor self.conversor_de_timeline = conversor_de_timeline def executar(self, contexto): """Obtém, converte e armazena a timeline.""" dados_brutos = ( self.acesso_ao_editor.obter_timeline_ativa() ) timeline = ( self.conversor_de_timeline.converter( dados_brutos ) ) contexto.timeline = timeline return contexto ``` --- # 22. Classe `ContextoDeAnalise` Arquivo: ```text scanner/coordenacao/contexto_de_analise.py ``` ## Responsabilidade Transportar os dados durante o processo de análise. Ele deverá armazenar: * Timeline; * Projeto; * Sequência; * Clipes; * Faixas; * Arquivos; * Metadados; * Áudios; * Transcrições; * Cenas; * Eventos; * Retakes; * Avisos; * Erros; * Status; * Informações de execução. ## Exemplo ```python class ContextoDeAnalise: """Armazena os dados produzidos durante a análise.""" def __init__(self): self.projeto = None self.timeline = None self.clipes = [] self.faixas = [] self.metadados = {} self.avisos = [] self.erros = [] ``` ## Regra O contexto não deve executar análises. Ele apenas transporta e armazena informações. --- # 23. Classe `PipelineDoScanner` Arquivo: ```text scanner/coordenacao/pipeline_do_scanner.py ``` ## Responsabilidade Executar as etapas de análise na ordem definida. Na primeira versão, o pipeline poderá conter apenas: ```text DescobertaDaTimeline ``` Posteriormente, serão adicionadas: ```text DescobertaDeClipes DescobertaDeArquivos ExtracaoDeMetadados ExtracaoDeAudio TranscricaoDeAudio AnaliseVisual DeteccaoDeCenas DeteccaoDeRetakes ``` ## Exemplo ```python class PipelineDoScanner: """Coordena a execução das etapas do scanner.""" def __init__(self, etapas): self.etapas = etapas def executar(self, contexto): """Executa todas as etapas na ordem definida.""" for etapa in self.etapas: contexto = etapa.executar(contexto) return contexto ``` ## Regra O pipeline não deve: * Conhecer detalhes do MCP; * Conhecer nomes de ferramentas externas; * Implementar transcrição; * Implementar análise visual; * Tomar decisões de edição. Ele apenas coordena as etapas. --- # 24. Classe `AnalisadorDeTimeline` Arquivo: ```text scanner/coordenacao/analisador_de_timeline.py ``` ## Responsabilidade Ser o ponto de entrada do processo de análise. Ela deverá: 1. Receber a configuração; 2. Criar o contexto; 3. Iniciar o pipeline; 4. Retornar o resultado. ## Exemplo ```python class AnalisadorDeTimeline: """Coordena o processo completo de análise da timeline.""" def __init__(self, pipeline): self.pipeline = pipeline def analisar(self): """Executa o processo de análise.""" contexto = ContextoDeAnalise() return self.pipeline.executar(contexto) ``` ## Regra Essa classe não deverá implementar as análises diretamente. Ela apenas inicia o processo. --- # 25. Fluxo completo da primeira versão O fluxo deverá ser: ```text AnalisadorDeTimeline ↓ Cria ContextoDeAnalise ↓ PipelineDoScanner ↓ DescobertaDaTimeline ↓ AcessoAoEditor ↓ AcessoATimeline ↓ ClienteMCP ↓ MCP do Premiere ↓ Resposta bruta ↓ ConversorDeTimeline ↓ Timeline do domínio ↓ ContextoDeAnalise ↓ Resultado final ``` --- # 26. Exemplo de montagem dos componentes A composição inicial poderá ser semelhante a: ```python cliente_mcp = ClienteMCP() acesso_a_timeline = AcessoATimeline( cliente_mcp=cliente_mcp, ) acesso_ao_editor = AcessoAoEditor( acesso_a_timeline=acesso_a_timeline, ) conversor_de_timeline = ConversorDeTimeline() descoberta_da_timeline = DescobertaDaTimeline( acesso_ao_editor=acesso_ao_editor, conversor_de_timeline=conversor_de_timeline, ) pipeline = PipelineDoScanner( etapas=[ descoberta_da_timeline, ], ) analisador = AnalisadorDeTimeline( pipeline=pipeline, ) resultado = analisador.analisar() ``` A forma exata dependerá da implementação real do cliente MCP. --- # 27. Primeira etapa prática: descobrir as ferramentas do MCP Antes de escrever a integração definitiva, será necessário identificar exatamente: 1. Como o MCP é iniciado; 2. Como o cliente se conecta; 3. Quais ferramentas estão disponíveis; 4. Como consultar a sequência ativa; 5. Como consultar as faixas; 6. Como consultar os clipes; 7. Como obter detalhes de um clipe; 8. Qual é o formato de resposta; 9. Como os tempos são representados; 10. Como os identificadores são representados; 11. Como erros são retornados; 12. Se o MCP permite chamadas encadeadas; 13. Se existe necessidade de manter sessão; 14. Se as respostas são síncronas ou assíncronas. Não se deve inventar os nomes das ferramentas. Os nomes usados no código deverão ser baseados na implementação real do MCP disponível no ambiente. --- # 28. Estratégia para descobrir a API real O desenvolvimento deverá seguir esta ordem: ## Passo 1 — Verificar conexão Criar um teste mínimo que confirme: ```text O cliente consegue se conectar? ``` ## Passo 2 — Listar ferramentas Obter a lista de ferramentas disponíveis no MCP. Registrar: * Nome; * Descrição; * Argumentos; * Tipos; * Retorno; * Erros possíveis. ## Passo 3 — Executar uma consulta simples Por exemplo: ```text Obter informações do projeto atual ``` ## Passo 4 — Consultar a sequência ativa Identificar: * Nome; * ID; * Duração; * FPS; * Resolução; * Número de faixas. ## Passo 5 — Consultar as faixas Identificar: * Faixas de vídeo; * Faixas de áudio; * Ordem; * Índices; * IDs. ## Passo 6 — Consultar os clipes Identificar todos os campos retornados. ## Passo 7 — Salvar uma resposta real As respostas reais deverão ser armazenadas em arquivos de teste, por exemplo: ```text testes/fixtures/ ├── projeto.json ├── sequencia.json ├── faixas.json └── clipes.json ``` Esses arquivos serão usados para testar os conversores sem precisar abrir o Premiere em todos os testes. --- # 29. Modelo de resposta bruta O formato abaixo é apenas um exemplo conceitual: ```json { "id": "sequence_001", "name": "Sequência principal", "duration": 120.5, "frame_rate": 29.97, "width": 1920, "height": 1080, "video_tracks": [ { "id": "video_1", "name": "V1", "index": 1, "clips": [ { "id": "clip_001", "name": "Camera A", "source_file": "/videos/camera_a.mov", "timeline_start": 0.0, "timeline_end": 12.5, "source_start": 35.2, "source_end": 47.7 } ] } ], "audio_tracks": [] } ``` Esse formato não deve ser considerado definitivo. O formato definitivo deverá ser obtido diretamente do MCP real. --- # 30. Validação dos dados recebidos Antes de converter os dados, o sistema deverá verificar: ## Timeline * Existe identificador? * Existe nome? * A duração é válida? * A taxa de quadros é válida? * A resolução é válida? ## Faixas * Existe identificador? * Existe tipo? * Existe índice? * A lista de clipes é válida? ## Clipes * Existe identificador? * Existe posição inicial? * Existe posição final? * O fim é maior que o início? * O arquivo de origem foi informado? * O clipe está offline? * A faixa existe? ## Erros de validação A validação não deve simplesmente gerar um erro genérico. Deverá registrar informações como: ```text Campo ausente: timeline.id Clipe inválido: clip_004 Intervalo inválido: início maior que fim Faixa desconhecida: audio_99 Arquivo de origem não encontrado ``` --- # 31. Tratamento de timeline vazia O sistema deverá tratar corretamente situações como: * Nenhuma sequência ativa; * Sequência sem clipes; * Sequência sem faixas; * Timeline vazia; * Projeto recém-criado; * Projeto com mídia offline. Essas situações não devem necessariamente ser consideradas falhas técnicas. Por exemplo: ```text Sequência encontrada, mas sem clipes. ``` Isso pode ser um resultado válido. O sistema deverá diferenciar: ```text Falha de comunicação ``` de: ```text Timeline válida, porém vazia ``` --- # 32. Tratamento de mídia offline Um clipe offline não deve impedir a leitura completa da timeline. O objeto `Clipe` deverá conter algo como: ```python clipe.offline = True ``` O sistema deverá manter: * ID do clipe; * Nome; * Posição na timeline; * Duração; * Faixa; * Caminho informado; * Estado offline. A análise do arquivo físico poderá ser realizada posteriormente pelo módulo de descoberta de arquivos. --- # 33. Separação entre posição na timeline e posição na origem Esse é um ponto fundamental. Um clipe possui pelo menos dois intervalos: ## Intervalo na timeline Onde o clipe está colocado na sequência. ```text Início: 30 segundos Fim: 45 segundos ``` ## Intervalo na mídia original Qual trecho do arquivo de origem está sendo utilizado. ```text Início: 120 segundos Fim: 135 segundos ``` Esses intervalos não devem ser misturados. O modelo deverá representar ambos: ```python clipe.intervalo_na_timeline clipe.intervalo_na_origem ``` Essa distinção será essencial para: * Detectar retakes; * Encontrar repetições; * Comparar trechos; * Reconstruir a origem; * Criar cortes; * Validar operações; * Relacionar clipes com arquivos originais. --- # 34. Identificadores O sistema deverá preservar os identificadores externos, mas também poderá criar identificadores internos. Exemplo: ```python clipe.identificador_externo clipe.identificador_interno ``` O identificador externo será usado para conversar novamente com o Premiere. O identificador interno será usado pelo domínio e pelos módulos internos. Não se deve presumir que o nome do clipe seja único. O nome: ```text Camera A ``` pode aparecer várias vezes. A identificação deverá utilizar IDs sempre que possível. --- # 35. Registro de logs O módulo deverá registrar logs em pontos importantes: ## Conexão ```text Conectando ao MCP do Premiere Conexão estabelecida Conexão encerrada ``` ## Leitura ```text Consultando sequência ativa Consultando faixas Consultando clipes ``` ## Conversão ```text Convertendo timeline Convertendo faixa video_1 Convertendo clipe clip_001 ``` ## Erros ```text Falha ao consultar clipes Resposta MCP inválida Campo obrigatório ausente ``` Os logs não devem registrar informações sensíveis desnecessárias. --- # 36. Testes necessários ## Testes do `ClienteMCP` * Conecta corretamente; * Desconecta corretamente; * Executa uma chamada; * Trata timeout; * Trata ferramenta inexistente; * Trata resposta inválida; * Trata conexão indisponível. ## Testes do `AcessoATimeline` * Obtém sequência ativa; * Obtém faixas; * Obtém timeline vazia; * Trata ausência de sequência; * Encaminha corretamente a chamada ao cliente MCP. ## Testes dos conversores * Converte timeline válida; * Converte faixa válida; * Converte clipe válido; * Trata campo ausente; * Trata intervalo inválido; * Trata tipo desconhecido; * Trata lista vazia; * Trata campos adicionais. ## Testes do domínio * Cria intervalo válido; * Rejeita intervalo inválido; * Calcula duração; * Cria clipe; * Cria faixa; * Cria timeline. ## Testes do scanner * Executa a descoberta; * Armazena a timeline no contexto; * Propaga erros; * Retorna contexto atualizado; * Funciona com integração simulada. --- # 37. Integração simulada para testes Deverá existir uma implementação simulada do acesso ao editor. Arquivo sugerido: ```text testes/fakes/acesso_ao_editor_simulado.py ``` Exemplo: ```python class AcessoAoEditorSimulado: """Fornece dados fictícios de uma timeline para testes.""" def __init__(self, dados_da_timeline): self.dados_da_timeline = dados_da_timeline def obter_timeline_ativa(self): """Retorna uma timeline simulada.""" return self.dados_da_timeline ``` Isso permite testar: ```text Scanner ↓ Acesso simulado ↓ Dados JSON ``` sem depender do Premiere. --- # 38. Critérios de conclusão da primeira versão O módulo será considerado concluído quando conseguir: * Conectar ao MCP real; * Identificar as ferramentas disponíveis; * Consultar a sequência ativa; * Consultar as faixas; * Consultar os clipes; * Retornar dados sem depender do formato bruto do MCP; * Converter os dados para objetos de domínio; * Identificar clipes offline; * Diferenciar intervalo da timeline e intervalo da origem; * Tratar timeline vazia; * Tratar erros de conexão; * Tratar respostas incompletas; * Executar testes automatizados; * Produzir logs; * Ser utilizado pelo `Scanner`; * Não executar nenhuma alteração na timeline. --- # 39. Ordem recomendada de implementação A implementação deverá ocorrer nesta ordem: ## Fase 1 — Estrutura Criar: ```text integracoes/premiere/ dominio/ scanner/ testes/ ``` ## Fase 2 — Cliente MCP Implementar: ```text ClienteMCP SessaoMCP ErrosMCP ``` ## Fase 3 — Descoberta da API * Listar ferramentas; * Identificar nomes; * Identificar argumentos; * Capturar respostas reais. ## Fase 4 — Leitura técnica Implementar: ```text AcessoATimeline AcessoAClipes AcessoAoEditor ``` ## Fase 5 — Modelos de domínio Implementar: ```text Projeto Sequencia Timeline Faixa Clipe IntervaloDeTempo ``` ## Fase 6 — Conversores Implementar: ```text ConversorDeTimeline ConversorDeFaixas ConversorDeClipes ``` ## Fase 7 — Scanner Implementar: ```text ContextoDeAnalise DescobertaDaTimeline PipelineDoScanner AnalisadorDeTimeline ``` ## Fase 8 — Testes Criar fixtures com respostas reais e testes simulados. ## Fase 9 — Integração Executar o fluxo completo: ```text Premiere ↓ MCP ↓ ClienteMCP ↓ AcessoAoEditor ↓ Conversores ↓ Domínio ↓ Scanner ``` --- # 40. Resultado esperado Ao final da primeira versão, deverá ser possível executar algo conceitualmente semelhante a: ```python resultado = analisador_de_timeline.analisar() ``` E obter uma estrutura como: ```python resultado.timeline resultado.timeline.nome resultado.timeline.duracao resultado.timeline.faixas resultado.timeline.clipes ``` Por exemplo: ```python for faixa in resultado.timeline.faixas: print(faixa.nome) for clipe in faixa.clipes: print( clipe.nome, clipe.intervalo_na_timeline.inicio, clipe.intervalo_na_timeline.fim, ) ``` O resultado não será ainda um plano de edição. Será a **representação estruturada e confiável da timeline atual**. Essa representação será a base para todos os próximos módulos: ```text Leitura da timeline ↓ Descoberta de arquivos ↓ Metadados ↓ Áudio ↓ Transcrição ↓ Análise visual ↓ Detecção de cenas ↓ Detecção de retakes ↓ Motor de decisão ↓ Plano JSON ↓ Aplicação no Premiere ``` # 41. Regra final de arquitetura O primeiro módulo deverá respeitar esta regra: > O MCP não é o scanner. O MCP é apenas o mecanismo de comunicação com o editor. A divisão correta é: ```text ClienteMCP comunica AcessoAoEditor organiza as consultas Conversores transformam respostas Domínio representa os dados DescobertaDaTimeline executa a descoberta PipelineDoScanner coordena as etapas AnalisadorDeTimeline inicia o processo ``` Essa separação permitirá que o sistema cresça sem transformar o código em uma única classe gigante e difícil de manter. A próxima etapa prática deve ser **inspecionar as ferramentas reais disponíveis no MCP do Premiere**, porque os nomes das chamadas, os argumentos e o formato das respostas precisam ser confirmados antes de implementar definitivamente o `ClienteMCP` e os conversores.