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
@@ -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.