269 lines
12 KiB
Markdown
269 lines
12 KiB
Markdown
# G-ART — Engine Overview
|
||
|
||
Este documento descreve a arquitetura interna do **G-ART / fcp-mcp-server**
|
||
(repositório `G-ART`), uma aplicação **MCP (Model Context Protocol) server em
|
||
Python** que lê, analisa e reescreve arquivos **FCPXML** do Final Cut Pro —
|
||
a ponte entre o Final Cut Pro e IA.
|
||
|
||
Diferente do CommandPost (automação de GUI via Lua/Hammerspoon), este projeto
|
||
opera **fora** do Final Cut Pro: você exporta o XML, o servidor processa o
|
||
documento como dados estruturados e devolve um XML modificado para importação.
|
||
Nada é patcheado, nenhuma API privada é usada.
|
||
|
||
Toda a análise foi feita a partir do código-fonte em `server.py` e `fcpxml/`.
|
||
|
||
> **Guia rápido:** [01 Arquitetura](docs/01_ARCHITECTURE.md) ·
|
||
> [02 Módulos](docs/02_MODULES.md) · [03 Server/Tools](docs/03_SERVER_TOOLS.md) ·
|
||
> [04 Testes & Workflow](docs/04_TESTS_AND_WORKFLOW.md) ·
|
||
> [05 Experiências](docs/05_EXPERIENCIAS.md) · [06 Boas Práticas](docs/06_BOAS_PRATICAS.md)
|
||
|
||
---
|
||
|
||
## 1. O que o programa faz
|
||
|
||
1. **Um motor de parse/serialização FCPXML** — transforma timelines do Final
|
||
Cut Pro (XML v1.8–v1.14, flat `.fcpxml` e bundles `.fcpxmld`) em objetos
|
||
Python, e reescreve de volta sem perda de sidecars (object tracking,
|
||
Cinematic).
|
||
|
||
2. **Uma camada MCP de 62 ferramentas** — expõe análise, edição em lote, QC,
|
||
geração, exportação cross-NLE, inteligência de mídia (silêncio/beats) e
|
||
edição baseada em transcrição, tudo acessível por um cliente MCP (Claude).
|
||
|
||
3. **Modo Live (macOS)** — faz *push* de um FCPXML direto para o Final Cut Pro
|
||
em execução via Apple events oficiais (Open Document), sem re-importação
|
||
manual. Leitura de bibliotecas abertas via dicionário AppleScript read-only.
|
||
|
||
---
|
||
|
||
## 2. Pilha tecnológica
|
||
|
||
| Camada | Tecnologia |
|
||
|--------|-----------|
|
||
| Linguagem | **Python 3.10+** (~7.1k linhas em `server.py` + `fcpxml/`) |
|
||
| Protocolo MCP | **mcp** (`mcp` SDK), servidor por stdio |
|
||
| Parsing XML | **defusedxml** em todos os 4 entry points + `lxml`/`ElementTree` |
|
||
| Tempo racional | frações `numerador/denominador` no formato `"600/2400s"` |
|
||
| Análise de mídia | **ffmpeg** `silencedetect` (opcional) e **librosa** (extra `[intelligence]`) |
|
||
| Transcrição | **Whisper** local (extra `[transcribe]`) |
|
||
| Controle Live | **osascript** / Apple events para o bundle `com.apple.FinalCut` |
|
||
| Validação | **xmllint** contra os DTDs oficiais do bundle do Final Cut Pro |
|
||
| Licença | MIT |
|
||
|
||
---
|
||
|
||
## 3. Estrutura geral do repositório
|
||
|
||
```
|
||
G-ART/
|
||
├── server.py # MCP server — 62 tools, prompts, resources, dispatch
|
||
├── fcpxml/ # "Engine" — biblioteca Python de núcleo
|
||
│ ├── models.py # TimeValue, Timecode, Clip, Timeline, enums, QC models
|
||
│ ├── parser.py # FCPXML → objetos Python (spine, connected clips, roles)
|
||
│ ├── writer.py # Modifica e grava FCPXML (markers, trim, gaps, speed)
|
||
│ ├── rough_cut.py # Gera timelines novas (rough cuts, montages, A/B)
|
||
│ ├── diff.py # Motor de comparação de timelines
|
||
│ ├── export.py # Export DaVinci Resolve v1.9 + FCP7 XMEML v5
|
||
│ ├── media_intel.py # Detecção real de silêncio (ffmpeg) e beats (librosa)
|
||
│ ├── transcribe.py # Transcrição Whisper local + edição por transcrição
|
||
│ ├── templates.py # Templates de timeline (intro/outro, lower thirds)
|
||
│ ├── live.py # Modo Live — push_to_fcp / list_fcp_libraries
|
||
│ ├── safe_xml.py # Wrappers defusedxml + serialize_xml()
|
||
│ └── dtd.py # Validação contra DTDs oficiais da Apple
|
||
├── Engine/ # Esta documentação da arquitetura
|
||
├── admin/ # Scripts de manutenção (graphify.sh, graphify.md)
|
||
├── docs/ # WORKFLOWS, CAPABILITY-AUDIT, specs
|
||
├── examples/ # Fixture de teste (sample.fcpxml)
|
||
├── tests/ # 1032 testes / 24 suítes
|
||
└── tools/ # Pacote Python (__init__)
|
||
```
|
||
|
||
---
|
||
|
||
## 4. O "Engine": a biblioteca `fcpxml/`
|
||
|
||
É o núcleo desacoplado do MCP. Não conhece o protocolo MCP nem os argumentos
|
||
das ferramentas — trabalha apenas com objetos Python e XML. `server.py` atua
|
||
como *camada de transporte/adaptação* que chama este núcleo.
|
||
|
||
### 4.1 Fundamentos de tempo — `models.TimeValue`
|
||
|
||
Toda hora é uma fração racional, nunca float. Isso elimina erro de arredondamento
|
||
em trim/split/speed em qualquer frame rate:
|
||
|
||
```python
|
||
TimeValue(600, 2400) # "600/2400s" == 0.25s
|
||
```
|
||
|
||
- Comparações por **multiplicação cruzada** (`a/b < c/d` → `a*d < c*b`),
|
||
permanecendo sempre em inteiros.
|
||
- Denominadores normalizados para positivos na construção — o sinal vive no
|
||
numerador.
|
||
- Soma/subtração compartilham um único caminho `_binop()` (fast-path de mesmo
|
||
denominador + alinhamento por LCM).
|
||
|
||
### 4.2 Modelos principais — `models.py`
|
||
|
||
| Classe | Função |
|
||
|--------|--------|
|
||
| `TimeValue`, `Timecode` | Tempo racional e formatação/parse de timecode |
|
||
| `Clip`, `VideoClip`, `AudioClip` | Clips da timeline (offset, start, duration, markers) |
|
||
| `ConnectedClip` | Clips com atributo `lane` (acima/abaixo da espinha) |
|
||
| `CompoundClip` | Clips compostos |
|
||
| `Timeline`, `Project` | Contêineres de espinha + connected clips |
|
||
| `Marker`, `MarkerType`, `MarkerColor` | Marcadores; `INCOMPLETE` é canônico, `TODO` é alias |
|
||
| `SilenceCandidate`, `FlashFrame`, `GapInfo`, `DuplicateGroup` | Resultados de QC |
|
||
| `ValidationIssue`, `ValidationResult` | Resultados de validação |
|
||
| `SegmentSpec`, `PacingConfig`, `MontageConfig` | Parâmetros de geração |
|
||
|
||
**Single source of truth**: `MarkerType` enum é dono da serialização —
|
||
`from_string()` para entrada, `from_xml_element()` para parse, `xml_attrs` para
|
||
escrita. `from_xml_element` faz match estrito do atributo `completed`
|
||
(`'0'`/`'1'` apenas), rejeitando valores com padding de espaço.
|
||
|
||
### 4.3 Subsistemas
|
||
|
||
| Subsistema | Módulo | Função |
|
||
|-----------|--------|--------|
|
||
| Parser | `parser.py` | FCPXML → objetos Python: espinha, connected clips, secondary storylines, roles |
|
||
| Modifier | `writer.FCPXMLModifier` | Edição index-based (clips/resources/formats dicts) do documento existente |
|
||
| Writer | `writer.FCPXMLWriter` | Gera FCPXML novo a partir de objetos Python |
|
||
| Rough cut | `rough_cut.py` | Gera timelines (rough cuts, montages, A/B roll) |
|
||
| Diff | `diff.py` | Compara timelines — detecta added/removed/moved/trimmed |
|
||
| Export | `export.py` | DaVinci Resolve v1.9 + FCP7 XMEML v5 |
|
||
| Media intel | `media_intel.py` | Detecção real de silêncio (ffmpeg) e beats (librosa, lazy) |
|
||
| Transcript | `transcribe.py` | Whisper local + edição por transcrição |
|
||
| Templates | `templates.py` | Estruturas pré-prontas (intro/outro, lower thirds, music video) |
|
||
| Live | `live.py` | push_to_fcp (Apple event) e list_fcp_libraries (AppleScript) |
|
||
| Segurança XML | `safe_xml.py` | Wrappers defusedxml centralizados + `serialize_xml()` |
|
||
| DTD | `dtd.py` | Valida output contra DTDs oficiais no bundle do FCP |
|
||
|
||
---
|
||
|
||
## 5. A camada MCP — `server.py`
|
||
|
||
### 5.1 Padrão de dispatch
|
||
|
||
Não há cadeias gigantes de `if/elif`. Um dicionário mapeia nome → handler
|
||
assíncrono:
|
||
|
||
```python
|
||
TOOL_HANDLERS = {
|
||
"analyze_timeline": handle_analyze_timeline,
|
||
"list_clips": handle_list_clips,
|
||
# ... 62 tools
|
||
}
|
||
```
|
||
|
||
Cada ferramenta tem seu `async def handle_<name>(arguments: dict)`. Todas
|
||
retornam via `_text_result(text)`, que envolve strings no `TextContent` MCP.
|
||
|
||
### 5.2 Helpers centrais
|
||
|
||
| Helper | Linha | Função |
|
||
|--------|-------|--------|
|
||
| `_parse_project()` | `server.py:319` | Parseia FCPXML → `(tree, timeline, project)`; a maioria dos handlers começa aqui |
|
||
| `_resolve_io_paths()` | `server.py:357` | Consolida validação de caminho de entrada/saída |
|
||
| `_setup_modifier()` / `_setup_generator()` | `server.py:390` / `:414` | Preparam modifier/generator com validação |
|
||
| `_format_clip_table()` / `_markdown_table()` | `server.py:245` / `:259` | Renderização de tabelas |
|
||
| `_parse_timestamp_parts()` | `server.py:433` | Parse de timestamps (min:seg, H:MM:SS, SMPTE) |
|
||
| `_detect_flash_frames()` / `_detect_gaps()` / `_detect_duplicate_groups()` | `server.py:1667+` | Detectores de QC |
|
||
| `_validate_filepath()` / `_validate_output_path()` | `server.py:103` / `:149` | Sandbox de I/O |
|
||
| `_check_json_depth()` | `server.py:83` | Rejeita payloads aninhados além de 50 níveis |
|
||
|
||
### 5.3 Modo Live — `fcpxml/live.py`
|
||
|
||
Rode apenas as superfícies sancionadas da Apple — sem patch de binário, sem
|
||
APIs privadas, sem acessibilidade:
|
||
|
||
- **push_to_fcp** — import FCPXML via Apple event *Open Document*. Injeta um
|
||
`<import-options>` no documento (local da biblioteca, copy/link assets,
|
||
suprimir avisos). Requer um caminho `.fcpbundle` para *zero-click* de verdade;
|
||
sem ele, o FCP abre um modal "Open Library" que bloqueia até resposta humana.
|
||
- **list_fcp_libraries** — enumera bibliotecas → eventos → projetos via o
|
||
dicionário AppleScript read-only (suite `com.apple.FinalCut.library.inspection`).
|
||
|
||
**A assimetria estrutural**: import é scriptable, mas a Apple não oferece export
|
||
programático — para puxar a timeline atual de volta, você ainda roda
|
||
`File > Export XML`. O modo Live *empurra*; round-trips voltam pelas ferramentas
|
||
XML.
|
||
|
||
---
|
||
|
||
## 6. Fluxo de um pedido
|
||
|
||
```
|
||
Cliente MCP (Claude)
|
||
│ JSON-RPC (stdio)
|
||
▼
|
||
server.py ── dispatcher (TOOL_HANDLERS)
|
||
│
|
||
├── handle_* (valida caminho, _parse_project, opera)
|
||
│
|
||
├── fcpxml/parser.py (XML → objetos)
|
||
├── fcpxml/writer.py (edita / grava)
|
||
├── fcpxml/rough_cut.py (gera novas timelines)
|
||
├── fcpxml/export.py (cross-NLE)
|
||
│
|
||
▼
|
||
output_<suffix>.fcpxml (original nunca é sobrescrito)
|
||
│
|
||
▼
|
||
Final Cut Pro: File → Import → XML (ou push_to_fcp, sem cliques)
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Validação padrão pós-correção (é obrigatório)
|
||
|
||
Regra do padrão do sistema: **sempre após concluir qualquer correção de
|
||
código, o sistema é automaticamente executado/validado.**
|
||
|
||
O gatilho é o script `[Engine/run_after_fix.sh](run_after_fix.sh)`. Toda vez
|
||
que você terminar uma correção, acione-o:
|
||
|
||
```bash
|
||
./Engine/run_after_fix.sh
|
||
```
|
||
|
||
Ele roda (a partir de qualquer diretório) e falha (`set -e`) se algo não
|
||
passar:
|
||
|
||
1. **`uv run ruff check . --exclude docs/`** — lint com zero erros.
|
||
2. **`uv run pytest tests/ -v`** — toda a suíte de testes passa.
|
||
|
||
Se falhar, corrija antes de prosseguir. Esta validação é o mesmo critério já
|
||
descrito em `CLAUDE.md` (Pre-Commit) — a diferença é que agora há um comando
|
||
único padronizado que garante a execução automática do sistema após cada
|
||
correção, sem depender de lembrar dos dois comandos no pre-commit.
|
||
|
||
---
|
||
|
||
## 8. Como navegar a documentação
|
||
|
||
> Esta pasta `Engine/` é o **hub da documentação**. Comece por aqui.
|
||
|
||
### Documentação padrão (leia nesta ordem)
|
||
- [docs/01_ARCHITECTURE.md](docs/01_ARCHITECTURE.md) — como o sistema é dividido
|
||
(camadas: admin → server → fcpxml/) e como se conectam. **Leia antes de qualquer mudança.**
|
||
- [docs/02_MODULES.md](docs/02_MODULES.md) — guia módulo a módulo do `fcpxml/`
|
||
(responsabilidade, tamanho, APIs públicas).
|
||
- [docs/03_SERVER_TOOLS.md](docs/03_SERVER_TOOLS.md) — a camada MCP `server.py`,
|
||
62 ferramentas, helpers e o padrão de handler.
|
||
- [docs/04_TESTS_AND_WORKFLOW.md](docs/04_TESTS_AND_WORKFLOW.md) — suíte de testes,
|
||
fluxo de trabalho (lint + pytest), execução e estado atual do sistema.
|
||
- [docs/05_EXPERIENCIAS.md](docs/05_EXPERIENCIAS.md) — **memória de projeto**:
|
||
registro cumulativo de problemas estruturais, erros recorrentes e decisões.
|
||
**Atualize sempre que um problema for detectado/corrigido.**
|
||
- [docs/06_BOAS_PRATICAS.md](docs/06_BOAS_PRATICAS.md) — **boas práticas de
|
||
programação** a aplicar em toda alteração/correção; inclui checklist final.
|
||
|
||
### Outros documentos
|
||
- [../CLAUDE.md](../CLAUDE.md) — visão geral, key patterns, execução e pre-commit.
|
||
- [../docs/CAPABILITY-AUDIT-2026-06.md](../docs/CAPABILITY-AUDIT-2026-06.md) —
|
||
auditoria do ecossistema e roadmap dual-mode (XML + Live).
|
||
- [../docs/WORKFLOWS.md](../docs/WORKFLOWS.md) — 8 receitas de workflow de produção.
|
||
- [../docs/specs/](../docs/specs/) — schemas de tools, estrutura FCPXML, pseudocódigo
|
||
do writer, algoritmo de rough cut, implementação do server, roadmap, modelos.
|
||
- [../admin/graphify.md](../admin/graphify.md) — pipeline de graphify do código.
|