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:
@@ -0,0 +1,682 @@
|
||||
Sim. **O ideal é tratar o MCP como um módulo completo de integração com o Premiere**, e não como uma única classe responsável por tudo.
|
||||
|
||||
O MCP será utilizado para várias finalidades:
|
||||
|
||||
* Ler a timeline ativa;
|
||||
* Ler sequências, faixas e clipes;
|
||||
* Obter propriedades dos clipes;
|
||||
* Criar, mover, cortar ou excluir elementos;
|
||||
* Aplicar alterações na timeline;
|
||||
* Executar comandos no Premiere;
|
||||
* Consultar o estado atual do projeto;
|
||||
* Validar se uma operação foi executada corretamente.
|
||||
|
||||
Por isso, uma única classe como `ClienteMCP` ficaria sobrecarregada rapidamente.
|
||||
|
||||
## Estrutura recomendada
|
||||
|
||||
```text
|
||||
integracoes/
|
||||
└── premiere/
|
||||
├── __init__.py
|
||||
│
|
||||
├── cliente_mcp.py
|
||||
├── sessao_mcp.py
|
||||
├── erros_mcp.py
|
||||
│
|
||||
├── leitura/
|
||||
│ ├── acesso_a_timeline.py
|
||||
│ ├── acesso_a_sequencia.py
|
||||
│ ├── acesso_a_faixas.py
|
||||
│ └── acesso_a_clipes.py
|
||||
│
|
||||
├── escrita/
|
||||
│ ├── executor_de_comandos.py
|
||||
│ ├── manipulador_de_clipes.py
|
||||
│ ├── manipulador_de_timeline.py
|
||||
│ └── aplicador_de_operacoes.py
|
||||
│
|
||||
├── conversores/
|
||||
│ ├── conversor_de_timeline.py
|
||||
│ ├── conversor_de_clipes.py
|
||||
│ └── conversor_de_respostas.py
|
||||
│
|
||||
└── contratos/
|
||||
├── acesso_ao_editor.py
|
||||
└── executor_do_editor.py
|
||||
```
|
||||
|
||||
A ideia principal é separar:
|
||||
|
||||
> **Comunicação com o MCP**, **leitura do Premiere**, **execução de comandos** e **conversão dos dados**.
|
||||
|
||||
---
|
||||
|
||||
# 1. `ClienteMCP`
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/cliente_mcp.py
|
||||
```
|
||||
|
||||
Classe:
|
||||
|
||||
```python
|
||||
class ClienteMCP:
|
||||
"""Responsável pela comunicação técnica com o servidor MCP do Premiere."""
|
||||
```
|
||||
|
||||
Essa classe deve cuidar somente da comunicação.
|
||||
|
||||
Responsabilidades:
|
||||
|
||||
* Abrir conexão;
|
||||
* Encerrar conexão;
|
||||
* Enviar uma chamada;
|
||||
* Receber a resposta;
|
||||
* Controlar timeout;
|
||||
* Tratar erros de comunicação;
|
||||
* Registrar logs;
|
||||
* Identificar falhas de conexão;
|
||||
* Possivelmente reconectar.
|
||||
|
||||
Exemplo conceitual:
|
||||
|
||||
```python
|
||||
class ClienteMCP:
|
||||
"""Executa chamadas técnicas contra o servidor MCP."""
|
||||
|
||||
def conectar(self) -> None:
|
||||
"""Estabelece a conexão com o MCP."""
|
||||
|
||||
def desconectar(self) -> None:
|
||||
"""Encerra a conexão com o MCP."""
|
||||
|
||||
def chamar(self, nome_da_ferramenta: str, argumentos: dict) -> dict:
|
||||
"""Executa uma ferramenta MCP e retorna sua resposta."""
|
||||
```
|
||||
|
||||
Ele **não deve saber o que é uma timeline, um clipe ou um retake**.
|
||||
|
||||
Para ele, existe apenas:
|
||||
|
||||
```text
|
||||
chamar ferramenta → receber resposta
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 2. `SessaoMCP`
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/sessao_mcp.py
|
||||
```
|
||||
|
||||
Classe:
|
||||
|
||||
```python
|
||||
class SessaoMCP:
|
||||
"""Controla o estado de uma sessão de comunicação com o Premiere."""
|
||||
```
|
||||
|
||||
Pode ser útil para armazenar:
|
||||
|
||||
* Identificação da sessão;
|
||||
* Estado da conexão;
|
||||
* Projeto atual;
|
||||
* Sequência ativa;
|
||||
* Última operação executada;
|
||||
* Ferramentas disponíveis;
|
||||
* Informações de capacidade do MCP.
|
||||
|
||||
Exemplo:
|
||||
|
||||
```python
|
||||
class SessaoMCP:
|
||||
"""Representa o estado atual da integração com o Premiere."""
|
||||
|
||||
def __init__(self):
|
||||
self.conectado = False
|
||||
self.projeto_atual = None
|
||||
self.sequencia_ativa = None
|
||||
```
|
||||
|
||||
Essa classe não é obrigatória na primeira versão, mas será útil quando a integração crescer.
|
||||
|
||||
---
|
||||
|
||||
# 3. Módulo de leitura
|
||||
|
||||
O módulo de leitura seria responsável por transformar comandos técnicos do MCP em operações compreensíveis pelo sistema.
|
||||
|
||||
## `AcessoATimeline`
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/leitura/acesso_a_timeline.py
|
||||
```
|
||||
|
||||
Classe:
|
||||
|
||||
```python
|
||||
class AcessoATimeline:
|
||||
"""Fornece operações de leitura da timeline do Premiere."""
|
||||
```
|
||||
|
||||
Métodos possíveis:
|
||||
|
||||
```python
|
||||
class AcessoATimeline:
|
||||
"""Lê a estrutura da timeline ativa."""
|
||||
|
||||
def obter_timeline_ativa(self):
|
||||
"""Retorna os dados da timeline ativa."""
|
||||
|
||||
def obter_sequencia_ativa(self):
|
||||
"""Retorna a sequência atualmente selecionada."""
|
||||
|
||||
def obter_faixas(self):
|
||||
"""Retorna as faixas de vídeo e áudio."""
|
||||
|
||||
def obter_clipes(self):
|
||||
"""Retorna os clipes presentes na timeline."""
|
||||
|
||||
def obter_detalhes_do_clipe(self, identificador_do_clipe):
|
||||
"""Retorna os detalhes de um clipe específico."""
|
||||
```
|
||||
|
||||
O fluxo seria:
|
||||
|
||||
```text
|
||||
AcessoATimeline
|
||||
↓
|
||||
ClienteMCP
|
||||
↓
|
||||
MCP do Premiere
|
||||
```
|
||||
|
||||
O scanner chamaria:
|
||||
|
||||
```python
|
||||
timeline = acesso_a_timeline.obter_timeline_ativa()
|
||||
```
|
||||
|
||||
E não:
|
||||
|
||||
```python
|
||||
cliente_mcp.chamar("alguma_ferramenta_interna", {...})
|
||||
```
|
||||
|
||||
Isso é importante porque o restante do sistema não deve conhecer os detalhes do MCP.
|
||||
|
||||
---
|
||||
|
||||
## Outras classes de leitura
|
||||
|
||||
Podemos dividir conforme a complexidade:
|
||||
|
||||
```text
|
||||
leitura/
|
||||
├── acesso_a_timeline.py
|
||||
├── acesso_a_sequencia.py
|
||||
├── acesso_a_faixas.py
|
||||
├── acesso_a_clipes.py
|
||||
├── acesso_a_projeto.py
|
||||
└── acesso_a_itens_de_midia.py
|
||||
```
|
||||
|
||||
Entretanto, no início, não é necessário criar todas imediatamente.
|
||||
|
||||
Podemos começar com:
|
||||
|
||||
```text
|
||||
AcessoAoEditor
|
||||
```
|
||||
|
||||
e depois dividir quando a classe crescer demais.
|
||||
|
||||
---
|
||||
|
||||
# 4. `AcessoAoEditor`
|
||||
|
||||
Eu recomendaria inicialmente uma classe de fachada chamada `AcessoAoEditor`.
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/acesso_ao_editor.py
|
||||
```
|
||||
|
||||
Classe:
|
||||
|
||||
```python
|
||||
class AcessoAoEditor:
|
||||
"""Oferece uma interface simplificada para consultar o Premiere."""
|
||||
```
|
||||
|
||||
Ela funcionaria como uma porta de entrada para as operações de leitura:
|
||||
|
||||
```python
|
||||
class AcessoAoEditor:
|
||||
"""Centraliza o acesso estruturado aos dados do Premiere."""
|
||||
|
||||
def __init__(self, acesso_a_timeline, acesso_a_clipes):
|
||||
self.acesso_a_timeline = acesso_a_timeline
|
||||
self.acesso_a_clipes = acesso_a_clipes
|
||||
|
||||
def obter_timeline_ativa(self):
|
||||
"""Obtém a timeline ativa."""
|
||||
|
||||
return self.acesso_a_timeline.obter_timeline_ativa()
|
||||
|
||||
def obter_clipes(self):
|
||||
"""Obtém os clipes da timeline ativa."""
|
||||
|
||||
return self.acesso_a_clipes.obter_clipes()
|
||||
```
|
||||
|
||||
Assim, o scanner dependeria de:
|
||||
|
||||
```python
|
||||
AcessoAoEditor
|
||||
```
|
||||
|
||||
e não diretamente de:
|
||||
|
||||
```python
|
||||
ClienteMCP
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Módulo de escrita
|
||||
|
||||
A leitura e a escrita devem ser separadas.
|
||||
|
||||
```text
|
||||
integracoes/premiere/
|
||||
├── leitura/
|
||||
└── escrita/
|
||||
```
|
||||
|
||||
Isso evita misturar:
|
||||
|
||||
* Consultar dados;
|
||||
* Alterar dados;
|
||||
* Executar comandos destrutivos.
|
||||
|
||||
## `ExecutorDeComandos`
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/escrita/executor_de_comandos.py
|
||||
```
|
||||
|
||||
Classe:
|
||||
|
||||
```python
|
||||
class ExecutorDeComandos:
|
||||
"""Executa comandos de alteração no Premiere por meio do MCP."""
|
||||
```
|
||||
|
||||
Responsabilidades:
|
||||
|
||||
* Executar uma operação;
|
||||
* Enviar parâmetros;
|
||||
* Receber resultado;
|
||||
* Identificar falhas;
|
||||
* Retornar confirmação da operação.
|
||||
|
||||
Exemplo:
|
||||
|
||||
```python
|
||||
class ExecutorDeComandos:
|
||||
"""Executa comandos no editor."""
|
||||
|
||||
def executar(self, nome_do_comando: str, argumentos: dict):
|
||||
"""Executa um comando no Premiere."""
|
||||
```
|
||||
|
||||
Mas essa classe não deveria decidir **qual comando deve ser executado**. Ela apenas executa o comando que recebeu.
|
||||
|
||||
---
|
||||
|
||||
## `AplicadorDeOperacoes`
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/escrita/aplicador_de_operacoes.py
|
||||
```
|
||||
|
||||
Classe:
|
||||
|
||||
```python
|
||||
class AplicadorDeOperacoes:
|
||||
"""Aplica operações de edição estruturadas na timeline."""
|
||||
```
|
||||
|
||||
Essa classe recebe operações já definidas pelo plano de edição:
|
||||
|
||||
```python
|
||||
class AplicadorDeOperacoes:
|
||||
"""Aplica operações de edição no Premiere."""
|
||||
|
||||
def aplicar_corte(self, operacao):
|
||||
"""Aplica uma operação de corte."""
|
||||
|
||||
def mover_clipe(self, operacao):
|
||||
"""Move um clipe na timeline."""
|
||||
|
||||
def excluir_clipe(self, operacao):
|
||||
"""Exclui um clipe da timeline."""
|
||||
|
||||
def aplicar_plano(self, plano):
|
||||
"""Aplica todas as operações de um plano de edição."""
|
||||
```
|
||||
|
||||
O fluxo seria:
|
||||
|
||||
```text
|
||||
AplicadorDeOperacoes
|
||||
↓
|
||||
ExecutorDeComandos
|
||||
↓
|
||||
ClienteMCP
|
||||
↓
|
||||
MCP do Premiere
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 6. `ConversorDeTimeline`
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/conversores/conversor_de_timeline.py
|
||||
```
|
||||
|
||||
Classe:
|
||||
|
||||
```python
|
||||
class ConversorDeTimeline:
|
||||
"""Converte os dados brutos do Premiere para o modelo interno do sistema."""
|
||||
```
|
||||
|
||||
Essa classe é muito importante.
|
||||
|
||||
O MCP pode retornar dados em um formato específico, por exemplo:
|
||||
|
||||
```json
|
||||
{
|
||||
"sequence": {
|
||||
"name": "Sequência 01",
|
||||
"timebase": 25
|
||||
},
|
||||
"tracks": [],
|
||||
"clips": []
|
||||
}
|
||||
```
|
||||
|
||||
Mas o sistema não deveria depender diretamente desse formato.
|
||||
|
||||
O conversor transforma isso em objetos próprios:
|
||||
|
||||
```python
|
||||
class ConversorDeTimeline:
|
||||
"""Converte uma resposta do Premiere para o domínio interno."""
|
||||
|
||||
def converter(self, dados_brutos):
|
||||
"""Converte os dados brutos em uma timeline do sistema."""
|
||||
```
|
||||
|
||||
Assim, se futuramente o MCP mudar, somente a integração e os conversores precisarão ser ajustados.
|
||||
|
||||
O restante do sistema continua funcionando.
|
||||
|
||||
---
|
||||
|
||||
# 7. Contratos para desacoplar o sistema
|
||||
|
||||
O ideal é criar contratos para que o scanner não dependa de uma implementação específica.
|
||||
|
||||
## `AcessoAoEditor`
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
integracoes/premiere/contratos/acesso_ao_editor.py
|
||||
```
|
||||
|
||||
Exemplo:
|
||||
|
||||
```python
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class AcessoAoEditor(ABC):
|
||||
"""Define as operações de leitura necessárias para acessar um editor."""
|
||||
|
||||
@abstractmethod
|
||||
def obter_timeline_ativa(self):
|
||||
"""Obtém a timeline ativa do editor."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def obter_clipes(self):
|
||||
"""Obtém os clipes da timeline."""
|
||||
raise NotImplementedError
|
||||
```
|
||||
|
||||
Depois podemos ter:
|
||||
|
||||
```text
|
||||
AcessoAoEditor
|
||||
├── AcessoAoPremiere
|
||||
├── AcessoAoOpenCut
|
||||
└── AcessoAoEditorSimulado
|
||||
```
|
||||
|
||||
O último é especialmente útil para testes.
|
||||
|
||||
Por exemplo:
|
||||
|
||||
```python
|
||||
class AcessoAoEditorSimulado(AcessoAoEditor):
|
||||
"""Fornece dados fictícios para testes sem abrir o Premiere."""
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 8. Como o scanner usaria isso
|
||||
|
||||
A classe `DescobertaDaTimeline` não deveria conhecer MCP.
|
||||
|
||||
Ela deveria conhecer apenas uma interface de acesso ao editor.
|
||||
|
||||
```python
|
||||
class DescobertaDaTimeline:
|
||||
"""Descobre a estrutura da timeline a partir do editor."""
|
||||
|
||||
def __init__(self, acesso_ao_editor):
|
||||
self.acesso_ao_editor = acesso_ao_editor
|
||||
|
||||
def executar(self, contexto):
|
||||
"""Lê a timeline e armazena os dados no contexto."""
|
||||
|
||||
timeline = self.acesso_ao_editor.obter_timeline_ativa()
|
||||
|
||||
contexto.timeline = timeline
|
||||
|
||||
return contexto
|
||||
```
|
||||
|
||||
O encadeamento seria:
|
||||
|
||||
```text
|
||||
DescobertaDaTimeline
|
||||
↓
|
||||
AcessoAoPremiere
|
||||
↓
|
||||
AcessoATimeline
|
||||
↓
|
||||
ClienteMCP
|
||||
↓
|
||||
MCP do Premiere
|
||||
```
|
||||
|
||||
Ou, usando uma fachada:
|
||||
|
||||
```text
|
||||
DescobertaDaTimeline
|
||||
↓
|
||||
AcessoAoEditor
|
||||
↓
|
||||
ClienteMCP
|
||||
↓
|
||||
MCP do Premiere
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 9. Arquitetura completa recomendada
|
||||
|
||||
```text
|
||||
projeto/
|
||||
│
|
||||
├── scanner/
|
||||
│ ├── coordenacao/
|
||||
│ │ ├── analisador_de_timeline.py
|
||||
│ │ ├── pipeline_do_scanner.py
|
||||
│ │ └── contexto_de_analise.py
|
||||
│ │
|
||||
│ ├── descoberta/
|
||||
│ │ ├── descoberta_da_timeline.py
|
||||
│ │ ├── descoberta_de_clipes.py
|
||||
│ │ └── descoberta_de_arquivos.py
|
||||
│ │
|
||||
│ ├── metadados/
|
||||
│ ├── audio/
|
||||
│ ├── transcricao/
|
||||
│ ├── visual/
|
||||
│ ├── cenas/
|
||||
│ └── retakes/
|
||||
│
|
||||
├── providers/
|
||||
│ ├── transcricao/
|
||||
│ ├── analise_visual/
|
||||
│ ├── deteccao_de_cenas/
|
||||
│ └── analise_de_audio/
|
||||
│
|
||||
├── integracoes/
|
||||
│ └── premiere/
|
||||
│ ├── cliente_mcp.py
|
||||
│ ├── sessao_mcp.py
|
||||
│ ├── erros_mcp.py
|
||||
│ │
|
||||
│ ├── leitura/
|
||||
│ │ ├── acesso_a_timeline.py
|
||||
│ │ ├── acesso_a_sequencia.py
|
||||
│ │ ├── acesso_a_faixas.py
|
||||
│ │ └── acesso_a_clipes.py
|
||||
│ │
|
||||
│ ├── escrita/
|
||||
│ │ ├── executor_de_comandos.py
|
||||
│ │ ├── aplicador_de_operacoes.py
|
||||
│ │ └── manipulador_de_timeline.py
|
||||
│ │
|
||||
│ ├── conversores/
|
||||
│ │ ├── conversor_de_timeline.py
|
||||
│ │ ├── conversor_de_clipes.py
|
||||
│ │ └── conversor_de_respostas.py
|
||||
│ │
|
||||
│ └── contratos/
|
||||
│ ├── acesso_ao_editor.py
|
||||
│ └── executor_do_editor.py
|
||||
│
|
||||
├── dominio/
|
||||
├── configuracao/
|
||||
├── persistencia/
|
||||
└── testes/
|
||||
```
|
||||
|
||||
## Minha recomendação prática
|
||||
|
||||
Para a primeira versão, não criaria todas as classes imediatamente. Começaria assim:
|
||||
|
||||
```text
|
||||
integracoes/
|
||||
└── premiere/
|
||||
├── cliente_mcp.py
|
||||
├── acesso_ao_editor.py
|
||||
├── executor_de_comandos.py
|
||||
├── conversor_de_timeline.py
|
||||
└── erros_mcp.py
|
||||
```
|
||||
|
||||
Depois, quando as responsabilidades crescerem:
|
||||
|
||||
```text
|
||||
acesso_ao_editor.py
|
||||
```
|
||||
|
||||
poderá ser dividido em:
|
||||
|
||||
```text
|
||||
leitura/
|
||||
├── acesso_a_timeline.py
|
||||
├── acesso_a_clipes.py
|
||||
└── acesso_a_projeto.py
|
||||
```
|
||||
|
||||
E:
|
||||
|
||||
```text
|
||||
executor_de_comandos.py
|
||||
```
|
||||
|
||||
poderá ser dividido em:
|
||||
|
||||
```text
|
||||
escrita/
|
||||
├── aplicador_de_operacoes.py
|
||||
├── manipulador_de_clipes.py
|
||||
└── manipulador_de_timeline.py
|
||||
```
|
||||
|
||||
## Regra central
|
||||
|
||||
A arquitetura deve seguir esta separação:
|
||||
|
||||
```text
|
||||
Scanner
|
||||
define o que precisa ser analisado
|
||||
|
||||
Integração com o Premiere
|
||||
acessa e altera o editor
|
||||
|
||||
Cliente MCP
|
||||
faz a comunicação técnica
|
||||
|
||||
Conversores
|
||||
transformam dados externos em dados internos
|
||||
|
||||
Providers
|
||||
executam análises usando tecnologias específicas
|
||||
|
||||
Motor de decisão
|
||||
decide o que fazer com os resultados
|
||||
|
||||
Aplicador de plano
|
||||
transforma decisões em operações no editor
|
||||
```
|
||||
|
||||
Portanto, a resposta direta é:
|
||||
|
||||
> **MCP deve ser um módulo de integração completo, com `ClienteMCP` como classe de comunicação central, classes especializadas de leitura e escrita, conversores e contratos.** Ele não deve ser uma única classe gigante nem ficar misturado dentro do scanner.
|
||||
Reference in New Issue
Block a user