Files
jhonny-editor/code/engine/arquitetura/leitura-da-timeline-via-mcp.md
T
João Henrique b541f502ba 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
2026-09-08 09:59:31 -04:00

38 KiB

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:

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:

cliente_mcp.chamar(
    "get_active_sequence",
    {}
)

Ele deve fazer isto:

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 é:

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:

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

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

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:

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

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:

integracoes/premiere/erros_mcp.py

Responsabilidade

Centralizar os erros relacionados à integração com o MCP.

Classes sugeridas

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:

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:

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:

obter_timeline_ativa()
obter_sequencia_ativa()
obter_faixas()
obter_clipes()
obter_detalhes_do_clipe()

Interface conceitual

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:

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

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

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:

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

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:

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

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

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:

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

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:

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:

integracoes/premiere/conversores/conversor_de_clipes.py

Responsabilidade

Converter cada clipe externo em uma entidade Clipe.

Interface conceitual

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

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:

dominio/entidades/projeto.py

Responsabilidade

Representar o projeto de edição.

Campos iniciais

  • Identificador;
  • Nome;
  • Caminho;
  • Sequências;
  • Data de leitura;
  • Metadados adicionais.

Exemplo

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:

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

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:

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

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:

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

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:

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

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:

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

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

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:

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

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:

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:

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

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:

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

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:

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:

DescobertaDaTimeline

Posteriormente, serão adicionadas:

DescobertaDeClipes
DescobertaDeArquivos
ExtracaoDeMetadados
ExtracaoDeAudio
TranscricaoDeAudio
AnaliseVisual
DeteccaoDeCenas
DeteccaoDeRetakes

Exemplo

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:

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

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:

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:

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:

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:

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:

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:

{
  "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:

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:

Sequência encontrada, mas sem clipes.

Isso pode ser um resultado válido.

O sistema deverá diferenciar:

Falha de comunicação

de:

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:

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.

Início: 30 segundos
Fim: 45 segundos

Intervalo na mídia original

Qual trecho do arquivo de origem está sendo utilizado.

Início: 120 segundos
Fim: 135 segundos

Esses intervalos não devem ser misturados.

O modelo deverá representar ambos:

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:

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:

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

Conectando ao MCP do Premiere
Conexão estabelecida
Conexão encerrada

Leitura

Consultando sequência ativa
Consultando faixas
Consultando clipes

Conversão

Convertendo timeline
Convertendo faixa video_1
Convertendo clipe clip_001

Erros

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:

testes/fakes/acesso_ao_editor_simulado.py

Exemplo:

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:

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:

integracoes/premiere/
dominio/
scanner/
testes/

Fase 2 — Cliente MCP

Implementar:

ClienteMCP
SessaoMCP
ErrosMCP

Fase 3 — Descoberta da API

  • Listar ferramentas;
  • Identificar nomes;
  • Identificar argumentos;
  • Capturar respostas reais.

Fase 4 — Leitura técnica

Implementar:

AcessoATimeline
AcessoAClipes
AcessoAoEditor

Fase 5 — Modelos de domínio

Implementar:

Projeto
Sequencia
Timeline
Faixa
Clipe
IntervaloDeTempo

Fase 6 — Conversores

Implementar:

ConversorDeTimeline
ConversorDeFaixas
ConversorDeClipes

Fase 7 — Scanner

Implementar:

ContextoDeAnalise
DescobertaDaTimeline
PipelineDoScanner
AnalisadorDeTimeline

Fase 8 — Testes

Criar fixtures com respostas reais e testes simulados.

Fase 9 — Integração

Executar o fluxo completo:

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:

resultado = analisador_de_timeline.analisar()

E obter uma estrutura como:

resultado.timeline
resultado.timeline.nome
resultado.timeline.duracao
resultado.timeline.faixas
resultado.timeline.clipes

Por exemplo:

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:

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 é:

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.