Skip to main content
Glama
README.md
# ae-channel

**让 AI 客户端直接读写你的 After Effects 工程。** 一个 CEP 面板(装在 AE 里)+ 一个 MCP
服务器(跑在 Python 里),合起来把 AE 变成一个可被脚本调用的编辑器:建合成、加层、打关键帧、
套预设、渲染、QC、检查点回滚,都能用一条工具调用完成。

> 中文就是本文件;English: [`README.en.md`](README.en.md)。
> 108 个工具的完整清单在 [`docs/tool-reference.md`](docs/tool-reference.md),
> 2026-11-05 之前的工程记录(实测数据、判据、踩坑史)在
> [`docs/README-engineering.md`](docs/README-engineering.md)。

---

## 30 秒判断要不要用

适合你,如果:你在 DSH(或别的 MCP 客户端)里用自然语言驱动 AE ——「把这个 comp 的所有文字层
字号加 4,再导出三帧给我看」。

不适合你,如果:你只想要一个能对话的 AE 面板、或者想在没有 AE 的机器上渲染(面板需要本机 AE;
序列渲染走 `aerender`,也要求 `.aep` 已保存到磁盘)。

**当前形态**:模型通过 **108 个 MCP 工具**(32 读 + 76 写,命名前缀 `mcp__ae__`)操作当前 AE 项目。

---

## 你需要什么

| 需要 | 说明 |
|---|---|
| Windows + Adobe After Effects 2025(25.x) | 面板是 CEP 扩展;工具面按 AE 25.2x131 实测校准 |
| Python 3.11+ | 依赖见 `server/requirements.txt`(`mcp` / `pillow` / `numpy`) |
| 一个 MCP 客户端 | DSH 最省事;其它客户端只要能配 stdio MCP 就行 |
| 一个已保存的 `.aep` 工程 | 面板要挂在工程窗口上;序列渲染要求先存盘 |

装依赖(如果不用 DSH 一键装):

```
python -m pip install -r server\requirements.txt
```

---

## 第一部分:用 AE 的人(三步上手)

### 1. 装面板

```
powershell -NoProfile -ExecutionPolicy Bypass -File cep\update.ps1
```

脚本把扩展复制到 `%APPDATA%\Adobe\CEP\extensions\com.dsh.aechannel`,并打开 CEP 的调试签名。
**装完必须重启 AE**,然后 **窗口 > 扩展 > ae-channel**。

> 面板只在**有工程打开**时出现在工作区里。停在 AE 首页时找不到它,先新建/打开一个工程。
> 打开面板后**正常退出 AE**(文件 > 退出,或 `app.quit()`)——用 `taskkill` 关掉会让 AE
> 跳过工作区保存,下次面板可能被藏进锁定的标签页。

### 2. 让客户端连上

MCP 服务器是本项目里的一个 Python 子进程,DSH 里加一段配置(其它客户端同理):

```json
{
  "mcpServers": {
    "ae": {
      "command": "<python>\\python.exe",
      "args": ["C:\\path\\to\\ae-channel\\server\\ae_channel\\__main__.py", "mcp"],
      "env": { "DSH_AE_ENABLE_WRITE": "1", "DSH_AE_TOOL_PROFILE": "read" }
    }
  }
}
```

- 上面 `args` 的路径换成**你这份仓库**里 `server\ae_channel\__main__.py` 的绝对路径,`command` 换成你的 Python 3.11+。
- `DSH_AE_ENABLE_WRITE=1` 是**写闸**:不设它,所有写工具都回 `writes_disabled`。先只读跑通,再开写。
- `DSH_AE_TOOL_PROFILE=read` 只是建议初学者从这里起步(见下面的「档位」)。

### 3. 第一次成功

在客户端里依次说:

1. **自检**:「跑一下 `ae_system_check`」→ 应回 `build …-cep`、`engineVersion`、`engineTools`。
2. **只读一次**:「用 `ae_system_report` 看看我现在打开的项目里有哪些 comp」。
3. **写一次**(确认写闸已开):「用 `ae_comp_add` 建一个 1920×1080 的 comp,名字叫测试」,再
   「用 `ae_layer_add` 在里面加一个文本层,写上 hello」。

三条都通了,说明面板、桥、MCP、AE 四段链路都是活的。

> ⚠️ **默认档是 `idle`,只有 2 个工具**(`ae_system_profile_set` + `ae_system_tool_search`)。
> 这是刻意的:一个刚起的会话不该背 108 个工具的声明。第一句话通常是
> 「`ae_system_profile_set(profile="read")`」,要写字幕/批次时再放宽到 `authoring` 或 `full`。

---

## 第二部分:接 MCP 的人

### 传输与并发

- **stdio**:每个客户端拉一个自己的 `python … server\ae_channel\__main__.py mcp` 进程;面板通过
  WebSocket 拨到 `127.0.0.1:38941`(`DSH_AE_PORT` 可改)。
- **一次只能有一路连 AE**:第二个进程会发现端口已被占用并拒绝启动,而不是把面板抢走。
  要多路并用就换 `DSH_AE_PORT`,并在 AE 侧用对应端口的面板。

### 档位(工具暴露面)

| 档位 | 工具数 | 用途 |
|---|---|---|
| `idle`(默认) | 2 | 刚开会话,只有两个元工具 |
| `read` | 33 | 只读探查:看结构、属性、关键帧 |
| `qc` / `audit` | 25 / 6 | 质检与审计场景 |
| `start` | 44 | 起步批次 |
| `authoring` | 83 | 日常编辑(不含少数重工具) |
| `full` | 108 | 全部:宏、渲染、预览、检查点 |

会话内切换:`ae_system_profile_set(profile="read")`(默认只影响本会话)。进程级默认:环境变量
`DSH_AE_TOOL_PROFILE`。

### 状态与产物(`~/.dsh/ae-state`,可用 `DSH_AE_STATE_ROOT` 改)

```
jobs/        长任务的作业记录(ae_job_get 读它)
checkpoints/ 检查点(ae_checkpoint_save / restore)
captures/    预览对比用的 PNG
renders/     aerender 的产物与日志
recovery/    失败信封的恢复记录(ae_checkpoint_recover 读它)
```

### 三件常见的工程事

- **批量**:`ae_keyframe_add` / `ae_layer_set` / `ae_text_style_set` 等 22 个工具接受
  `targets=[{layer, …}, …]`:一次调用、**一个 Undo 组**,顶层参数是默认值,坏条目进 `results[]`。
- **渲染**:`ae_render_start` 走外部 `aerender`(要求 `.aep` **已保存**且工程不脏);单帧预览用
  `ae_render_frame_run`(回一张 PNG)。
- **找工具**:`ae_system_tool_search(query="keyframe")` 按名字/描述查;`ae_system_tool_report` 还能
  告诉你哪些工具常被连着调用。

---

## 工具一览(按任务,不是全表)

| 我想… | 先看这些 |
|---|---|
| 看工程 / 找项 / 看层 | `ae_system_report`、`ae_comp_get`、`ae_layer_get`、`ae_item_search` |
| 建与改结构 | `ae_comp_add`、`ae_layer_add`、`ae_layer_set`、`ae_item_structure_set` |
| 关键帧与缓动 | `ae_keyframe_add`、`ae_keyframe_easing_set`、`ae_keyframe_retime`、`ae_keyframe_bake` |
| 文字与文本动画 | `ae_text_set`、`ae_text_style_set`、`ae_text_animator_set` |
| 效果 / 预设 / 图层样式 | `ae_effect_add`、`ae_effect_set`、`ae_preset_apply`、`ae_layer_style_set` |
| 渲染与对比 | `ae_render_frame_run`、`ae_render_start`、`ae_preview_compare`、`ae_preview_sheet_export` |
| 质检 | `ae_qc_comp_check`、`ae_qc_project_check`、`ae_qc_timing_report` |
| 批量与复用 | 任一写工具的 `targets=`、`ae_macro_save` / `ae_macro_run` |
| 安全网 | `ae_checkpoint_save`、`ae_checkpoint_restore`、`ae_checkpoint_recover` |

完整签名(参数表 + 每个工具的一行说明)在 **[`docs/tool-reference.md`](docs/tool-reference.md)**。

---

## 五条安全须知

1. **写闸默认关**:没有 `DSH_AE_ENABLE_WRITE=1`,写工具一律 `writes_disabled`(连 dry-run 也一样)。
2. **破坏性工具要 `confirm=true`**:删层、删项、修剪合成、覆盖保存、恢复检查点。不给就拒,
   并在拒绝里列出会发生什么。
3. **回包说三态**:`outcome` = `succeeded` / `failed` / `unknown`。`unknown` 不是失败——先看
   `recoveryId` 和 `ae_job_get`,别盲目重试。
4. **有命名的陷阱**:套缺效果的预设还传 `allowMissing=true`、回滚一个已经脏了的工程,会先被
   `trap_refused` 挡下,要你明确 `acknowledge_trap=true` 才继续。
5. **一次调用 = 一个 Undo 组**(批量也一样),但删整个文件夹会带走子树、回滚会清空 Undo 历史——
   这两条的后果写在工具说明里,别靠记忆。

---

## 常见问题

**「AE bridge is not connected」**
AE 没开,或面板没开。检查:AE 里有工程;窗口 > 扩展 > ae-channel 已打开;面板没有显示「断开」。

**面板在「窗口 > 扩展」里点了没反应 / 找不到**
确认用 `cep\update.ps1 -Force` 重装过并**重启了 AE**;面板只在有工程时进入工作区。

**「bridge port 127.0.0.1:38941 is already owned」**
已经有一路连着 AE(DSH 或别的会话)。关掉那一侧,或给新的一侧换 `DSH_AE_PORT`。

**「我只看到 2 个工具」**
默认档是 `idle`。说「`ae_system_profile_set(profile="read")`」,或把 `DSH_AE_TOOL_PROFILE` 设成
`read` / `authoring` / `full`。

**「写到一半超时了」**
默认等待 35 s(面板轮询窗口 31.5 s 之上)。长任务用 `wait_seconds` 变成作业,再用 `ae_job_get` 收结果。

**「`ae_render_start` 说工程是脏的」**
`aerender` 渲的是**磁盘上的 `.aep`**。先 `ae_system_save`(覆盖已有文件要 `confirm=true`),再渲染。

**「`ae_layer_style_set(action="apply")` 拒绝了」**
应用图层样式走的是 AE 菜单命令,且有宿主前提:在「刚启动、从未交互打开过工程」的 AE 上会失败
(实测),先手动打开一次工程、建一个 comp 再试。

**「文字/中文乱码」**
多半是终端编码,不是数据:回包是 UTF-8 JSON(`\u8f89\u5149` = 辉光)。看原始 JSON,不看控制台渲染。

---

## 自检与回归

```
python server\ae_channel\__main__.py client doctor   # 不需要 AE:协议 / 工具面 / 写闸 / 端口
python scripts\run_regression.py                 # 全量离线回归(当前 67 项)
```

`doctor` 结尾应是 `TOOL SURFACE OK, LIVE CHAIN BLOCKED (AE handshake …)` 且**退出码 0**——
它需要 AE 的那一项是 `[BLOCKED]`,不是 FAIL。

给测试者用的冻结包说明在 [`docs/TEST-KIT.md`](docs/TEST-KIT.md)。

---

## 想再深入

| 文件 | 内容 |
|---|---|
| [`docs/QUICKSTART.md`](docs/QUICKSTART.md) | 更细的安装 / 首次运行走查 |
| [`docs/tool-reference.md`](docs/tool-reference.md) | 108 个工具的参数与逐条说明 |
| [`docs/README-engineering.md`](docs/README-engineering.md) | 旧版 README:实测数据、判据、踩坑史 |
| [`CONTEXT.md`](CONTEXT.md) | 交接状态:最近每批改了什么、为什么、还剩什么 |
| [`ROADMAP.md`](ROADMAP.md) | 已完成 / 未完成的批次与裁定 |
| [`docs/rulings.md`](docs/rulings.md) | 人拍板过的决定(含出处) |
| [`docs/design-architecture-review.md`](docs/design-architecture-review.md) | 架构审查与工具面收口的账 |

## 许可

本项目的代码是 **MIT**,见 [`LICENSE`](LICENSE)。一个例外写在 [`THIRD-PARTY.md`](THIRD-PARTY.md):`cep/extension/js/CSInterface.js` 是 Adobe 随 CEP 框架分发的桥接文件(文件头为 *All Rights Reserved*),按 CEP 扩展的惯例随包携带、头部原样不动,**不受本项目 MIT 覆盖**;若你需要零第三方文件,删掉它并让使用者从 Adobe 的 CEP 资源自行放回同一路径即可。

TDQS

A4.6/5.0

Scored across 2 tools

Disambiguation4/5

One tool changes the exposure profile, the other searches the currently exposed catalogue, so purposes are distinct in principle. There is mild overlap in that `ae_system_profile_set` also 'inspects' the profile while `ae_system_tool_search` lists the active profile's tools, which could cause a model to pick either when it just wants to know what is available.

Naming Consistency5/5

Both names follow the identical `ae_system_<noun>_<verb>` pattern (`ae_system_profile_set`, `ae_system_tool_search`), with consistent snake_case and shared namespace prefix. No deviations.

Tool Count4/5

Two tools is below the typical 3-15 range, but the thinness is deliberate and justified: this server is a minimal meta control plane whose whole point is to avoid paying for a large prompt. Each tool earns its place, though there is no dedicated read-only 'current profile' introspection tool.

Completeness4/5

The pair covers the full widen-inspect-switch loop: search at three detail levels, switch profile with session/process scope, and switch back. Minor gaps exist — no explicit tool to enumerate all available profile names or to read the current profile state without invoking the setter.

Maintenance

ActivityActive
ResponsivenessNo recent community issues