Files
gart/code/Engine/README.md
T
João HenriqueandClaude Sonnet 5 7b5aed79ee feat(voz): legenda por ênfase, forced align, IA local e correções de zoom/revisão
Trabalho da branch feat/revisao-enfases: pipeline de edição por voz ganha
alinhamento forçado (whisperx), roteirização por LLM local (Ollama), e a
etapa 5 (revisão de frases) passa a refletir de verdade o que é aplicado.

- generate_subtitles_by_emphasis: legenda comum cobre o clipe inteiro,
  legenda dinâmica só nas frases de ênfase, e a comum é desativada
  (enabled="0") onde a dinâmica cobre, em vez de nunca ser gerada ali.
- validate_subtitle_layout ignora títulos com enabled="0" — corrige falso
  positivo de colisão contra o que está desativado no lugar dele.
- Corrige zoom/marcador sendo descartado quando a borda encosta exatamente
  no início de um corte.
- Etapa 5 do Assistente: recarrega quando as decisões da IA mudam (com
  fresh=true, ignorando a revisão salva antiga) — resolve a dessincronia
  entre "ativa" na tela e o que já foi cortado no FCPXML.
- Etapa "Processar" reaplica as decisões da revisão (_phrase_actions.json)
  antes da cadeia de remoção de silêncio/legendas — antes, desativar uma
  frase na etapa 5 não tinha efeito nenhum no vídeo final.
- Etapa "Concluído" fundida em "Processar" — abrir no Final Cut/Finder
  aparece assim que termina, sem slide extra.
- Palavra clicável na etapa 5 agora funciona como toggle (clique de novo
  desfaz) e mostra a própria ênfase (sublinhado colorido + peso da fonte).
- fcpxml/forced_align.py, fcpxml/llm_local.py, ai_edit.py: alinhamento
  fonético via whisperx e roteirização local via Ollama/Gemma.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 18:26:04 -04:00

13 KiB
Raw Blame History

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. Este README é a visão geral; o detalhe módulo a módulo mora em docs/02_MODULES.md, que é o documento a manter atualizado quando a estrutura mudar.

Começando agora? Leia 01 Arquitetura e depois 09 Manutenção — o primeiro diz como o sistema é dividido, o segundo diz por onde começar a mexer e o que está em aberto.

Guia completo: 01 Arquitetura · 02 Módulos · 03 Server/Tools · 04 Testes & Workflow · 05 Experiências · 06 Boas Práticas · 07 Projeto Ativo no FCP · 08 App macOS · 09 Manutenção


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 74 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+ (~13k linhas em server.py, server_tools/ e 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/
├── CLAUDE.md                 # Regras do projeto para o agente
├── admin/                    # Ponte com o app (fora de code/)
│   ├── models_api.py         # Entry point: docstring dos comandos + dispatch
│   └── api/                  # Os 37 comandos, um módulo por assunto
└── code/
    ├── server.py             # MCP entry point — só dispatch
    ├── server_tools/         # Handlers das 74 tools + _shared/
    ├── fcpxml/               # "Engine" — biblioteca Python de núcleo
    │   ├── writer/           # PACOTE: edição/escrita (mixins por assunto)
    │   ├── models/           # PACOTE: dados por família (timing, timeline…)
    │   ├── parser.py         # FCPXML → objetos Python
    │   ├── rough_cut.py      # Gera timelines novas
    │   ├── voice_*.py        # Pipeline de voz (features → timeline → actions)
    │   ├── phrase_review.py  # Revisão de frases da etapa 5
    │   ├── text_layout.py    # Diagramação das legendas
    │   ├── live.py           # Modo Live — push_to_fcp
    │   ├── safe_xml.py       # defusedxml + serialize_xml()
    │   └── dtd.py            # Validação contra DTDs da Apple
    ├── MacApp/Sources/       # App SwiftUI (compilado por swiftc)
    ├── Engine/               # Esta documentação
    ├── docs/                 # WORKFLOWS, CAPABILITY-AUDIT, specs
    ├── examples/             # Fixture de teste (sample.fcpxml)
    └── tests/                # 1.466 testes / 42 suítes

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:

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/

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/generator.py 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:

TOOL_HANDLERS = {
    "analyze_timeline": handle_analyze_timeline,
    "list_clips": handle_list_clips,
    # ... 74 tools, todos em server_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:

./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 — como o sistema é dividido (camadas: admin → server → fcpxml/) e como se conectam. Leia antes de qualquer mudança.
  • docs/02_MODULES.md — guia módulo a módulo do fcpxml/ (responsabilidade, tamanho, APIs públicas).
  • docs/03_SERVER_TOOLS.md — a camada MCP server.py, 74 ferramentas, helpers e o padrão de handler.
  • 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 — 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 — boas práticas de programação a aplicar em toda alteração/correção; inclui checklist final.

Outros documentos