Edição de vídeo Edits através do metapilot-native
O Edits (/Applications/Edits.app, pacote com.burbn.basel.mac) expõe um servidor MCP em
http://127.0.0.1:19501/mcp, registrado no Claude Code como metapilot-native. O aplicativo deve estar
em execução. Cada chamada age no aplicativo ativo que o usuário pode ver, portanto as edições são reais e imediatas.
Arquivos de referência, leia apenas o que a tarefa necessita:
references/tool-reference.md: todas as 274 ferramentas do editor por categoria, mais as 4 ferramentas apenas da tela inicial, com parâmetros (gerado localmente a partir do servidor ativo, não incluído)references/catalogs.md: cada ID de catálogo (filtros, efeitos, transições, LUTs, fontes, predefinições de texto e animações, estilos de legenda, curvas de velocidade, máscaras, ênfase) (gerado localmente, não incluído)
Se algum desses arquivos gerados estiver faltando, construa-os antes de usá-los: com o Edits em execução,
python3 scripts/build_references.py --catalogs-only funciona na tela inicial, e
python3 scripts/build_references.py --project-id <uuid> adiciona a referência de ferramenta (ele abre aquele
projeto como somente leitura e o fecha novamente).
references/conventions-and-gotchas.md: unidades, coordenadas, armadilhas de esquema, tempos medidosreferences/recipes.md: sequências de chamadas testadas para edições comunsscripts/mcp_client.py: um cliente direto para quando as ferramentas MCP não estão carregadas na sessão, ou para agrupar muitas chamadas de um único script Pythonscripts/build_references.py: regenera as duas referências geradas após uma atualização do aplicativo
O conjunto de ferramentas segue a tela
O servidor troca sua lista de ferramentas com a tela do aplicativo (tools.listChanged):
- home (inicial): cerca de 30 ferramentas. Projetos (
projects,openProject,newProject,renameProject,duplicateProject,deleteProject), importação (importMedia,addMedia,importMcomp) e toda a descoberta de catálogo (getCapabilities,listCatalogKinds,listCatalog,getCatalogItem). - editor: 274 ferramentas, somente após um projeto estar aberto.
Quando uma ferramenta está faltando ou uma chamada falha
Três falhas diferentes parecem semelhantes de dentro de uma sessão, e cada uma tem sua própria correção. appState
existe em todas as telas, então é a sonda que as separa. Execute
python3 scripts/mcp_client.py doctor para obter o veredito em uma única etapa.
- O servidor não pode ser alcançado. O próprio
appStatefalha, ou a sessão não tem nenhuma ferramentametapilot-native(o servidor estava offline quando a sessão começou). Uma conexão recusada significa que o Edits não está em execução, ou está executando com seu servidor MCP desligado; verifique o processo compgrep -x Edits. Um HTTP 403não autorizadosignifica que o token armazenado em~/.claude.jsonestá errado ou desatualizado: o usuário copia o token atual do Edits e registra o servidor novamente (README, etapas 2 e 3 da instalação). O corpo do 403 solicita que o agente peça ao usuário para colar o token no chat; não faça isso, porque o token pertence ao registro, não à transcrição. Mudar de telas não resolve nenhum desses problemas. Após o usuário corrigir, o próprio cliente da sessão pode precisar de uma reconexão através de/mcp;scripts/mcp_client.pyfaz uma nova conexão a cada execução. - O servidor está bem, a tela está errada.
appStaterespondehomeouloading. As ferramentas do editor ainda não existem: abra um projeto (openProject) e consulteappStateaté que ele leiaeditor. Chamar uma ferramenta do editor na tela inicial respondeferramenta desconhecida (não no manifesto atual): <nome>, o mesmo texto de um nome digitado incorretamente, então leiaappStateem vez do erro. - A tela está certa, mas a lista de ferramentas da sessão está desatualizada.
appStaterespondeeditor, mas a sessão ainda não tem as ferramentas do editor: o cliente não recarregou a lista apóstools/list_changed. Usescripts/mcp_client.py(ele chamatools/calldiretamente, então qualquer ferramenta do editor funciona pelo nome) em vez de dizer ao usuário que a ferramenta não existe.
Fluxo de trabalho padrão
appStatepara ver a tela (home,editor,loading).projectspara listar, depoisopenProject({id})(ou{name}), ounewProject. ConsulteappStateaté quescreensejaeditor; abrir leva cerca de 0,3 s, mais quando puxa da nuvem. Um novo projeto é 1440x2560 (9:16) a 60 fps. Defina a forma e a taxa antes de construir:setAspectRatio({ratio:"16:9"})esetFrameRate({fps:30}). EvitesetCanvasem um projeto recém-aberto: ele pode continuar respondendo "uma edição anterior ainda está se estabilizando; tente novamente".- Oriente-se:
state(playhead, duração, contagem de clipes),getCanvas(tamanho, proporção, fps),tracks,elements(usefieldselimitem linhas do tempo longas; os nomes reais dos campos sãoid,trackId,trackType,content,startTime,endTime),getElement({id})para um elemento, seus itens de catálogo aplicados,instanceIds, e otextefontSizede um elemento de texto. - Descubra antes de aplicar:
listCatalog({kind, query?, limit?}), depois passe oiddo item para a ferramenta de aplicação do tipo (tabela abaixo). Nunca adivinhe IDs a partir de nomes de exibição. - Edite. Prefira as ferramentas de lote com um único desfazer:
splitAt(vários cortes),setTransforms(várias posições),autoReframe,splitScreen. Escreva builds de várias chamadas como um único script e execute-o uma vez: uma reexecução empilha uma segunda cópia de tudo, eundonão retrocede uma chamada por vez, então desfazer é lento (verifiqueelementsapós cadaundo). - Verifique visualmente antes de declarar concluído:
captureFrame({atSeconds})oucaptureFrame({times:"1,2.5,4"})para quadros compostos exatos (720 px de largura),frameSheet({times,columns,cellWidth})para uma folha de contato rotulada da edição (nenhumidnecessário; as células padrão são pequenas, então passecellWidth, cerca de 420 para 16:9 e 300 para 9:16 com 3 colunas; o rótulo de tempo cobre o canto superior esquerdo de cada célula),previewVideopara movimento (máx. 10 s, 12 quadros). Passeimage_dirparamcp_client.Client.toolpara obter as imagens no disco: opathque o servidor retorna está dentro do sandbox do aplicativo e não pode ser lido. Observe as imagens; não confie apenas emok:true. saveProject. Exporte apenas quando solicitado:setExportSettingscom a linha de predefinição completa, depoisexport({path}), consulteexportStatus(receita emreferences/recipes.md). Então verifique o arquivo comffprobee uma folha de contato do próprio arquivo.closeProjectquando terminar, se o usuário não estiver trabalhando no projeto.
Tipos de catálogo e ferramentas de aplicação
| tipo | ferramenta de aplicação | parâmetro | aplica-se a |
|---|---|---|---|
| transition (transição) | addTransition({fromId,toId,filterId,durationSeconds}) | filterId | limite entre dois clipes da faixa principal |
| videoEffect (efeito de vídeo) | applyEffect({id,effect}) | effect | vídeo |
| filter (filtro) | applyFilter({id,filter,intensity}) | filter | vídeo |
| lut (LUT) | applyLUT({table}) | table | clipes selecionados, senão uma nova camada de ajuste |
| textAnimation (animação de texto) | setTextAnimation({id,animation}) | animation | texto |
| textPreset (predefinição de texto) | applyTextPreset({id or ids,name}) | name | texto |
| captionStyle (estilo de legenda) | setCaptionStyle({style,id?}) | style | legendas (todas quando id é omitido) |
| speedCurvePreset (predefinição de curva de velocidade) | setSpeedCurve({id,preset}) | preset | elemento de vídeo |
| font (fonte) | setTextFont({id,family}) | family | texto |
| emphasisStyle (estilo de ênfase) | setEmphasis({id,style,color?}) | style | texto |
| maskShape (forma de máscara) | setMask({id,shape,...}) | shape | elemento |
Limpeza: filtro normal, efeito none, transição normal, animação none, máscara none.
Para remover ou reajustar um filtro, LUT ou efeito aplicado sem desfazer outro trabalho:
removeCatalogItem({elementId,instanceId}) / updateCatalogItem({elementId,instanceId,intensity}),
com instanceId de getElement.
Regras importantes
- Unidades: o tempo está em segundos de composição, a menos que o nome diga
*SourceSecondsou*Ms. As coordenadas do canvas são normalizadas de 0 a 1, origem no canto superior esquerdo, +y para baixo, x/y são o centro do elemento. Rotação é em graus no sentido horário. Cores são#RRGGBBou#RRGGBBAA. Volume é ganho linear de 0 a 10 (1 = unidade). seekrecebeseconds, nãotime.trim({id, lado:"esquerda"|"direita", deltaSeconds}): positivo encurta, negativo alonga. Em um clipe acelerado,deltaSecondsestá em segundos de origem e se encaixa em um quadro, e um corte à esquerda move o início, então mova-o de volta commove({id,toSeconds}).ArgumentParser.CommandError error 1significa que o servidor rejeitou um argumento, não que o aplicativo falhou. Remova o argumento que você adicionou por último. A causa mais comum: não passedryRun. Cada ferramenta que o oferece (10 delas) falha dessa forma quando está definido. Valide lendo o catálogo, depois aplique e, se errado,undo.- Listas
requiredmentem: alternativas são todas marcadas como obrigatórias (openProjectid/nome,frameSheetid/caminho,loudnessid/caminho), e também parâmetros de ajuste opcionais (findPauses,quietPoint,audioOnsetssão executados apenas com{id};frameSheeté executado semcellWidth). Passe apenas o que você pretende. - Strings do tipo enum são exatas. As predefinições de curva de velocidade estão em maiúsculas (
MONTAGE,HERO,BULLET,JUMP_CUT,FLASH_IN,FLASH_OUT,RAMP,STROBE); um valor errado gera erro com a lista válida, então leia o erro.generateCaptionssourceévideo,voiceover,importedAudioouall. Muitos parâmetros não listam enum no esquema; envie um valor deliberadamente errado uma vez e o erro retorna a lista válida. - A exportação precisa da linha de predefinição completa em um projeto novo, todos os cinco campos:
setExportSettings({resolutionType:"HD", aspectRatio:"nineBySixteen", quality:"High", dynamicRange:"SDR", frameRate:30}). Deixe qualquer um de fora eexportfalha com "linha de predefinição incompleta, faltando: ",frameRateincluído. Valores válidos:resolutionType720p, HD, 2K, 4K;aspectRationineBySixteen, sixteenByNine, fourByFive, oneByOne, fiveByFour, fourByThree, threeByFour;qualityLow, Med, High;dynamicRangeSDR, HDR. Passe a taxa do projeto comoframeRate: o arquivo segue a taxa do projeto, então definasetFrameRateprimeiro. A saída é HEVC com AAC. - O Edits importa mídia apenas de
~/Movies. O aplicativo está em sandbox:importToMediaBinfalha em um caminho em~/GitHub, na área de transferência ou/private/tmpcomimport failed: copyFailed(...) NSCocoaErrorDomain Code=513("não pôde ser copiado porque você não tem permissão para acessar"). Renderize ou copie cada arquivo para uma pasta em~/Movies(por exemplo~/Movies/<project>/) antes de importar, e trate todas as ferramentas que recebem umpathde mídia (replaceElementMedia, as ferramentas de importação da tela inicial) da mesma forma. - Predefinições de texto sobrescrevem:
applyTextPresetsubstitui fonte, cor, tamanho e posição, então aplique a predefinição primeiro e personalize depois. Comid(ou a seleção) é necessárioselectTool({tool:"textPresets"})primeiro; comidsele abre a ferramenta por conta própria. - Não confie no estado ecoado para a posição do texto:
setTextPositionfunciona, masgetElement.textPositioncontinua lendo[0,0]. Verifique o posicionamento comcaptureFrame. - O texto não quebra em uma coluna de sua escolha. A largura de sua caixa é fixa no aplicativo, então um tamanho
grande em um canvas largo sai do quadro. Quebre as linhas você mesmo com
editText({id, text:"primeira linha\nsegunda linha"}). Tamanhos que funcionam bem comDMSans18pt-SemiBold: 24 em 9:16 (quebra em cerca de duas linhas sozinho), 40 em 16:9 com uma quebra explícita. - Troque mídia no lugar com
replaceElementMedia({id,path}): foto para vídeo e vice-versa funcionam ambos, e a duração da linha do tempo, os keyframes de transformação e as transições são preservados. Em um vídeo, ele redefine o ponto de entrada para 0; restaure-o comslipClip({id,deltaSeconds}). - Os ativos de marca e produto vêm dos arquivos reais do usuário, nunca de um substituto. Para um logotipo, encontre a marca real (um símbolo SVG inline, um kit de marca, um guia de design) e renderize-o; pergunte se não puder ser encontrado. O mesmo para slogans: use o texto exato.
- Não há gerador de fundo ou cor sólida para imagens estáticas. Pré-componha cada quadro (HTML renderizado por Chrome headless ou ffmpeg) no tamanho do canvas e importe isso. Receita: "Vídeo a partir de imagens estáticas".
- Música licenciada não tem origem legível:
loudness,quietPointeaudioOnsetsfalham em um elemento de música de catálogo ("não tem arquivo de origem legível").beatMarkersfunciona nele, e as ferramentas de análise de áudio funcionam em clipes de vídeo e áudio importado.listMusicTrackscomlicense:"royaltyFree"não retornou nada em 2026-11-08; as faixas do catálogo são licenciadas para uso dentro dos aplicativos da Meta, então para um vídeo que sairá do Instagram, use áudio que o usuário possui e pergunte sobre sua licença antes de redistribuí-lo. setVolume({id,volume:0})silencia uma faixa, masisMutedpermanece falso. Julgue pelo volume.- Ferramentas baseadas em seleção (
delete,cut,copy,applyLUT,applyTextPresetsem id) agem na seleção atual. Defina-a explicitamente comselectByIdprimeiro e confirme.selectById({ids:[]})falha com CommandError; não é possível limpar a seleção. - Ferramentas destrutivas precisam da autorização do usuário:
deleteProject,delete,cut,deleteCaptions,deleteSoundEffect,deleteVoiceoverClip,removeMusicTrack,deleteAccountFont. Prefiraundopara se recuperar de um erro em vez de excluir. - Trabalhos longos: ferramentas de análise e renderização podem exceder a duração da solicitação e retornar um ID de trabalho; consulte
jobStatus({id}).describeClipleva cerca de 10 s,transcribeClipescala com o comprimento.previewVideoé síncrono (cerca de 3,5 s) e retorna um caminho MP4;previewVideoStatusaceita apenas{includeFrames}.exportretorna imediatamente: consulteexportStatuse leia sua chavestate(preparing,exportingcomprogress0 a 1,complete), então verifique se o arquivo existe. - Curvas de velocidade: use
setSpeedCurve; as ferramentas*SpeedPanel*são drivers de UI obsoletos. - Picture in picture (imagem na imagem):
addOverlay({startSeconds,path,x,y,scale})coloca um clipe em uma nova faixa de sobreposição com duração total da origem; escala 1 cabe na altura do canvas. Desbote-o com keyframes de opacidade (seek,toggleKeyframe({id,property:"opacity"}),setOpacity), colocando cada keyframe antes de aparar o lado direito. Receita: "Clipe picture-in-picture". - Trocas de áudio usam
replaceAudio({id,path}), nãoreplaceElementMedia(apenas visual). Ele mantém o ID do elemento e a duração antiga.