ZenVFX CLI 是 AI 视频创作平台的命令行工具,通过画布(Canvas)中的节点(Node)+ 连线(Edge)构建 AI 生成任务。
zenvfx {"ok":true,"data":{...}} / {"ok":false,"error":{...}}),解析时用 2>/dev/null 过滤 stderrzenvfx-mcp,一律优先使用 zenvfx CLI,不要混用两者操作同一画布架构原则(v3):
canvas:run 默认异步,加 --wait 进入同步模式(daemon 内部轮询直到所有节点 completed/failed 才返回)。results 数组逐项标注状态。0.9.1@tencent/zenvfx-clihttps://mirrors.tencent.com/npm/(腾讯内网 npm 镜像)# 首次安装 或 升级到 registry 上的最新版(@latest 等价于不写 tag)
npm install -g @tencent/zenvfx-cli@latest --registry https://mirrors.tencent.com/npm/
# 升级到指定版本
npm install -g @tencent/zenvfx-cli@0.9.1 --registry https://mirrors.tencent.com/npm/
> 注意:必须带 --registry,公网 registry.npmjs.org 上没有这个包。
按下面三步对比,三个版本号一致即说明已装到最新:
# 1. 本地已安装版本
zenvfx --version
# 输出形如:@tencent/zenvfx-cli/0.9.1 linux-x64 node-v20.x
# 2. registry 上当前 latest 版本
npm view @tencent/zenvfx-cli version --registry=https://mirrors.tencent.com/npm/
# 输出形如:0.9.1
# 3. 全局安装包元信息(确认安装路径与版本,排除多版本污染)
npm ls -g @tencent/zenvfx-cli --registry=https://mirrors.tencent.com/npm/
若 zenvfx --version 比 npm view 拿到的版本旧,重新执行上面的 npm install -g ...@latest 即可;若 zenvfx 命令找不到,检查 npm config get prefix 下的 bin 是否在 PATH 里。
升级后建议再跑一次 zenvfx auth:verify ,确认本地配置仍然可用。
# 安装(详见上一节"版本与升级")
npm install -g @tencent/zenvfx-cli@latest --registry https://mirrors.tencent.com/npm/
# 认证(自动保存 mcpToken/defaultProject/defaultWorkspace 等配置)
zenvfx auth:login <token> # 可选 --host <host-url>
# 仅校验 token(不切换默认项目/workspace)
zenvfx auth:verify <token>
auth:login 返回 saved 字段标识各配置是否已自动设置。若 saved.defaultProject 或 saved.defaultWorkspace 为 false,需手动补全:
zenvfx project:list 2>/dev/null # 查看可用项目
zenvfx project:switch <project-id> # 一键切换项目(自动更新 workspace)
project:switch 自动解析 workspace 的规则(仅依赖 userId,不依赖 username,因为 username 是用户可自定义的别名):
/{projectId}/用户空间/ 下目录名以 _{userId} 结尾userIddefaultWorkspace,需手动设置也可手动设置:
zenvfx config:set defaultProject <project-id>
zenvfx config:set defaultWorkspace "/<project-id>/用户空间/xxx"
也可通过环境变量:ZENVFX_MCP_TOKEN、ZENVFX_PROJECT
| 命令 | 用途 |
|---|---|
| ------ | ------ |
auth:login | 一键认证,可选 --host |
auth:verify | 仅校验 token 合法性并写入 mcpToken,不切换项目/workspace |
config:set | 手动设置(key:host/wsHost/mcpToken/defaultProject/defaultUsername/defaultUserId/defaultWorkspace) |
config:get / config:list | 读取配置 |
project:list | 列出项目 |
project:switch | 切换项目(自动更新 defaultProject + defaultWorkspace,workspace 匹配仅依赖 userId,不依赖 username),可选 --no-workspace |
//目录/文件名 )| 命令 | 用途 |
|---|---|
| ------ | ------ |
file:stat --path | 文件/目录详情 |
file:readdir --path | 目录内容(不递归) |
file:mkdir --path | 创建目录(默认递归) |
file:rm --path | 删除文件/目录 |
file:tree --path | 目录树,可选 --max-depth |
file:path-to-id --path | 路径转内部 ID |
file:id-to-path --id | 内部 ID 转路径 |
file:upload --local-file <本地路径> --project-id | 上传本地文件到 COS 并注册素材;--file-path 可省略(仅上传不写 ZenFS) |
标注 [S] 的命令必须携带 --canvas 参数。系统会根据 --canvas 路径自动执行 canvas:open(如果尚未打开),无需手动调用。
> ⚠️ --data / --value-json 的 JSON 值直接裸写,不加单引号或双引号包裹。
> 命令解析器使用空格切分(split(/\s+/)),不支持引号转义。
> - ✅ --data [{"type":"image_generator"}]
> - ❌ --data '[{"type":"image_generator"}]'(单引号成为 JSON 值的一部分 → JSON 解析失败)
| 命令 | 用途 |
|---|---|
| ------ | ------ |
canvas:create --name <名称> | 创建画布,可选 --path(默认 defaultWorkspace) |
canvas:list | 列出画布(不递归),可选 --list-path |
canvas:open --canvas [S] | 显式打开画布(一般无需手动调用,其他 [S] 命令会自动触发) |
canvas:info --canvas [S] | 查看画布信息 |
canvas:save --canvas [S] | 保存画布(编辑命令已自动保存,通常不需要) |
canvas:run --ids [S] | 批量运行节点;默认异步立即返回 query_hint,加 --wait 进入同步模式 |
| 模式 | 触发 | 返回时机 | 适用场景 |
|---|---|---|---|
| ------ | ------ | ---------- | ---------- |
| 异步(默认) | canvas:run --ids ... | 立即返回,含 submitted/results[].taskId/query_hint | 长链路、并发多节点;调用方按 query_hint.command 自行轮询 |
| 同步 | canvas:run --ids ... --wait | 在 daemon 内部轮询直到全部 completed/failed 才返回最终结果(含 outputs[].url) | 单节点或短链路调试;脚本希望一次拿到结果 |
--timeout <秒> 仅在 --wait 时生效,默认 1800(30 分钟)。节点数 × 15s + 60s 自动放宽,最低 120s。```json
{
"submitted": true,
"mode": "sync",
"timedOut": false,
"elapsed": 62025,
"results": [
{ "taskId": "...", "status": "completed", "nodes": [{ "nodeId": "...", "status": "completed", "outputs": [...], "textOutputs": [] }] }
]
}
```
# 同步等待两个图片节点跑完
zenvfx canvas:run --ids image_generator-aaa,image_generator-bbb --wait --timeout 600 --canvas "$CANVAS_PATH"
# 异步触发,自己轮询
RUN=$(zenvfx canvas:run --ids node1,node2 --canvas "$CANVAS_PATH" 2>/dev/null)
# 取 query_hint.command 后定期 zenvfx task:status ...
[S]编辑类命令执行后自动保存画布。
> ⚠️ --canvas 是必填参数:所有标注 [S] 的命令都必须携带 --canvas 参数指定画布路径(或通过环境变量 ZENVFX_CANVAS 提供)。
| 命令 | 用途 |
|---|---|
| ------ | ------ |
canvas:node:list --canvas | 列出所有节点 |
canvas:node:info --ids | 批量查看节点详情(pins、options、taskId/taskStatus) |
canvas:node:add --data | 批量添加节点 |
canvas:node:remove --ids | 批量删除节点 |
canvas:node:set --data | 批量设置节点参数 |
canvas:node:set --id | 快捷模式:单节点单参数设置 |
canvas:node:move --data | 批量移动节点位置 |
canvas:node:move --id | 快捷模式:单节点移动 |
canvas:node:prompt --id | 解析 prompt 中的 @占位符(如 @首帧图1),可选 --model |
node:model | 查询节点支持的模型与参数枚举(支持逗号分隔多个类型) |
node:list | 列出所有可用节点类型定义(本地,不需网络) |
node:defs | 一站式返回所有节点完整定义(本地 schema + 后端模型/参数),AI Agent 加载节点知识首选 |
| 场景 | 错误信息 | 错误码 |
|---|---|---|
| ------ | ---------- | -------- |
--data JSON 解析失败 | --data JSON 解析失败,请检查格式: <原始输入> | INVALID_JSON |
--data 不是非空数组 | --data 必须是非空 JSON 数组 | INVALID_JSON |
node:add 缺少 type | 参数校验失败: data[N].type 是必填项 | MISSING_VALUE |
node:set 批量模式缺少 id | 参数校验失败: data[N].id 是必填项 | MISSING_VALUE |
node:set 批量模式 options 不是对象 | 参数校验失败: data[N].options 必须是对象 | MISSING_VALUE |
node:set 快捷模式缺少 --id | 参数校验失败: 必须提供 --data(批量模式)或 --id + --option + --value(快捷模式) | MISSING_VALUE |
node:set 快捷模式缺少 --option | 参数校验失败: 快捷模式需要 --option 指定选项名称 | MISSING_VALUE |
node:set 快捷模式缺少值 | 参数校验失败: 快捷模式必须提供 --value 或 --value-json | MISSING_VALUE |
--value-json JSON 解析失败 | --value-json JSON 解析失败,请检查格式: <原始输入> | INVALID_JSON |
node:info/remove --ids 为空 | 参数校验失败: --ids 至少需要包含一个节点 ID | MISSING_VALUE |
node:move 批量缺少 nodeId/position | 参数校验失败: data[N].nodeId 是必填项 / data[N].position 是必填项 | MISSING_VALUE |
node:move 快捷模式缺少 --id 或 --position | 参数校验失败: 快捷模式需要 --position 指定目标位置 | MISSING_VALUE |
[
{
"type": "string", // [必填] 节点类型,如 "image_generator", "normal_video_generator"
"name": "string", // [选填] 节点名称
"position": "string", // [选填] 坐标位置,如 "100,200",默认 "0,0"
"options": {} // [选填] 节点配置参数(如 prompt, model, clarity, ratio, duration 等),
// 创建后立即设置,无需再单独调用 canvas:node:set
}
]
示例:
# 基础:只创建节点
zenvfx canvas:node:add --data [{"type":"normal_video_generator","position":"0,0"},{"type":"image_input","position":"400,0","name":"首帧图"}] --canvas "$CANVAS_PATH"
# 带 options:创建并设置参数(省去 canvas:node:set)
zenvfx canvas:node:add --data [{"type":"normal_video_generator","name":"文生视频","position":"0,0","options":{"prompt":"傍晚海边小孩嬉戏","model":"kling","clarity":"RESOLUTION_720P","ratio":"16:9","duration":5}}] --canvas "$CANVAS_PATH"
模式 1 — 批量模式 --data(多节点多参数):
[
{
"id": "string", // [必填] 节点 ID
"options": { // [必填] 要设置的参数对象
"prompt": "赛博朋克",
"model": "kling-video-o1"
}
}
]
zenvfx canvas:node:set --data [{"id":"node1","options":{"prompt":"赛博朋克","model":"kling-video-o1"}}] --canvas "$CANVAS_PATH"
模式 2 — 快捷模式(单节点单参数,LLM 友好,无需构造 JSON):
zenvfx canvas:node:set --id node-abc --option prompt --value "一只银渐层胖猫咪" --canvas "$CANVAS_PATH"
# JSON 值使用 --value-json
zenvfx canvas:node:set --id node-abc --option config --value-json {"width":1024} --canvas "$CANVAS_PATH"
> ⚠️ --data 与 --id + --option + --value 互斥。传了 --data 则忽略快捷模式参数。
# 批量
zenvfx canvas:node:move --data [{"nodeId":"n1","position":"100,200"},{"nodeId":"n2","position":{"x":300,"y":400}}] --canvas "$CANVAS_PATH"
# 快捷
zenvfx canvas:node:move --id node-abc --position "100,200" --canvas "$CANVAS_PATH"
zenvfx canvas:node:move --id node-abc --position {"x":100,"y":200} --canvas "$CANVAS_PATH"
> 节点位置:添加多个节点时用 position 指定坐标,避免叠加。建议水平间隔 400px:"0,0"、"400,0"、"800,0"。
[S]> ⚠️ 同样必须携带 --canvas 参数。所有写操作执行后自动保存。
>
> 打组必须一次做到完整收尾:当用户要求"打组/分组/整理成组"时,优先只调用 canvas:node:group。该命令内部会自动完成:创建组 → 对新组/受影响父组执行组排序 → 检查顶层重叠 → 必要时整体平移避免重叠。不要在打组后停在"已创建组",需根据返回的 sortedGroups / overlapCheck 确认布局已收尾;只有用户明确要求重新排序某个已有组时,才额外调用 canvas:node:group:sort。
| 命令 | 用途 |
|---|---|
| ------ | ------ |
canvas:node:group --node-ids | 将一批节点打包为新组(自动剥离原父组成员、自动派生组的边/实体引用,并自动排序/检查重叠/必要时避让) |
canvas:node:ungroup --group-id | 解散组,成员上浮到父级 |
canvas:node:group:info --group-id | 查询组信息(id/name/members/color/bounds,只读) |
canvas:node:group:members --group-id | 全量替换组成员,自动重派生 edges/entities |
canvas:node:group:color --group-id | 修改组颜色标签,可选值:gray / red / orange / yellow / green / cyan / blue / purple / none(清除颜色) |
canvas:node:group:sort --group-id | 对组内节点执行依赖流自动排序布局(基于内部边自动调整位置) |
canvas:node:group:execute --group-id | 按依赖顺序执行组内所有可执行节点(异步触发,进度通过 task:status 查询) |
canvas:node:group:cancel --group-id | 取消组的按序执行(停止组内所有进行中或 pending 的子节点) |
示例:
# 1. 把 3 个节点打成一个组并命名(自动完成组排序 + 顶层重叠检查/避让)
zenvfx canvas:node:group --node-ids n1,n2,n3 --name "场景A" --canvas "$CANVAS_PATH"
# → { groupId: "group_xxx", status: "ok", sortedGroups: [...], overlapCheck: { checked, movedGroups, overlapsBefore, overlapsAfter } }
# 2. 查询组详情
zenvfx canvas:node:group:info --group-id group_xxx --canvas "$CANVAS_PATH"
# 3. 改颜色 / 清除颜色
zenvfx canvas:node:group:color --group-id group_xxx --color blue --canvas "$CANVAS_PATH"
zenvfx canvas:node:group:color --group-id group_xxx --color none --canvas "$CANVAS_PATH"
# 4. 改成员(全量替换)
zenvfx canvas:node:group:members --group-id group_xxx --node-ids n1,n4 --canvas "$CANVAS_PATH"
# 5. 组内自动排序
zenvfx canvas:node:group:sort --group-id group_xxx --canvas "$CANVAS_PATH"
# 6. 按依赖顺序执行组内节点(异步)
zenvfx canvas:node:group:execute --group-id group_xxx --canvas "$CANVAS_PATH"
# 查进度:zenvfx task:status --ids <taskIds> --canvas-id <canvasId>
# 7. 取消执行
zenvfx canvas:node:group:cancel --group-id group_xxx --canvas "$CANVAS_PATH"
# 8. 解散
zenvfx canvas:node:ungroup --group-id group_xxx --canvas "$CANVAS_PATH"
参数校验错误提示(打组命令):
| 场景 | 错误信息 | 错误码 |
|---|---|---|
| ------ | ---------- | -------- |
--node-ids 为空 | 参数校验失败: --node-ids 至少需要包含一个节点 ID | MISSING_VALUE |
| 任一 nodeId 不存在 | Node not found: | NODE_NOT_FOUND |
--group-id 对应节点不是 group 类型 | Node | NODE_VALIDATION_FAILED |
groupNodes 归一化后成员为空 | No valid nodes to group | NODE_VALIDATION_FAILED |
--color 取值非法 | 由 oclif options 拒绝并列出可选值 | — |
> 💡 打组语义提示:
> - canvas:node:group 的 --node-ids 可以混合普通节点和已有的组。当传入的节点是另一个组的成员时,工具会自动从原父组中剥离,避免重复归属。
> - canvas:node:group 默认会自动执行布局收尾:排序新组/受影响父组,并检查顶层重叠;若 overlapCheck.overlapsAfter > 0,需要继续使用 canvas:node:move 或再次组织布局,不能直接宣称布局完美。
> - canvas:node:group:members 是全量替换而非增量;想加成员请先 info 查出当前 members,合并后再传入。
> - canvas:node:group:sort 仅对组的直接成员做布局,不会递归子组内部;普通打组场景无需再额外调用,因为 canvas:node:group 已自动收尾。
[S]> ⚠️ 同样必须携带 --canvas 参数。
| 命令 | 用途 |
|---|---|
| ------ | ------ |
canvas:edge:list --canvas | 列出所有连线 |
canvas:edge:add --data | 批量连接节点 |
canvas:edge:remove --ids | 批量删除连线 |
[
{
"source": "string", // [必填] 源节点 ID
"sourceHandle": "string", // [必填] 源节点输出 handle(pinName)
"target": "string", // [必填] 目标节点 ID
"targetHandle": "string" // [必填] 目标节点输入 handle(pinName)
}
]
示例:
zenvfx canvas:edge:add --data [{"source":"n1","sourceHandle":"output","target":"n2","targetHandle":"ref_images"}] --canvas "$CANVAS_PATH"
参数校验错误提示(连线命令):
| 场景 | 错误信息 | 错误码 |
|---|---|---|
| ------ | ---------- | -------- |
edge:add JSON 解析失败 | --data JSON 解析失败,请检查格式: <原始输入> | INVALID_JSON |
edge:add 不是非空数组 | --data 必须是非空 JSON 数组 | INVALID_JSON |
edge:add 缺少必填字段 | 参数校验失败: data[N].source 是必填项 等 | MISSING_VALUE |
edge:remove --ids 为空 | 参数校验失败: --ids 至少需要包含一个边 ID | MISSING_VALUE |
| 命令 | 用途 |
|---|---|
| ------ | ------ |
task:status --ids | 批量查询任务状态(--ids 和 --canvas-id 均为必填) |
查询命令参数校验:
| 场景 | 错误信息 | 错误码 |
|---|---|---|
| ------ | ---------- | -------- |
node:model 未提供 nodeType | 参数校验失败: nodeTypes 是必填项,请提供至少一个节点类型 | MISSING_VALUE |
node:model 未知类型 | 未知的节点类型: (返回 validTypes 列表,不中断) | — |
task:status --ids 为空 | 参数校验失败: --ids 至少需要包含一个任务 ID | MISSING_VALUE |
task:status project 未配置 | 参数校验失败: project 未配置,请通过 auth:login 或 config:set defaultProject 设置 | MISSING_CONFIG |
canvas:run --ids 为空 | 参数校验失败: --ids 至少需要包含一个节点 ID | MISSING_VALUE |
| 命令 | 用途 |
|---|---|
| ------ | ------ |
daemon:ping / daemon:status / daemon:stop | 检测/查看/停止 daemon |
sourceHandle 和 targetHandle 必须用节点定义中的 pinName,不是后端 API 的 field_path。用错会导致连线保存成功但前端不显示。
通过 node:list 或 node:defs 查询正确的 pinName。常用速查:
| 节点类型 | 输入 pinName | 输出 pinName |
|---|---|---|
| ---------- | ------------- | ------------- |
image_generator | prompt, referenceImage | outputImage |
normal_video_generator | referenceImage, prompt | outputVideo |
composite_video_generator | inputVideo, inputImage, prompt | outputVideo |
first_to_last_video_generator | firstReferenceImage, lastReferenceImage, prompt | outputVideo |
comprehensive_reference_generator | inputVideo, inputImage, inputAudio, prompt | outputVideo |
canvas:node:add、canvas:node:remove、canvas:node:set、canvas:node:move、canvas:edge:add、canvas:edge:remove、canvas:node:group* 系列执行成功后自动保存画布,无需额外调用 canvas:save。
> 注:旧版的 canvas:node:props 已下线,统一通过 canvas:node:set 设置参数。
canvas:create 返回的 canvasPath 不含 .canvas 后缀,canvas 类命令带不带后缀均可。file:stat 等文件命令需要完整文件名(带 .canvas)。
所有 [S] 命令在执行时会自动按 --canvas 路径打开/复用 Session。只有在你需要显式预热 daemon、提前感知错误时才调用 canvas:open。
CLI 对"多个对象"的批量传参分两种风格,不混用:
| 风格 | 适用命令 | 用法 |
|---|---|---|
| ------ | ---------- | ------ |
--ids 逗号分隔 | canvas:run / canvas:node:remove / canvas:node:info / task:status 等"只需要 ID"的命令 | --ids "n1,n2,n3",逗号两侧空格会被 trim,空段会被过滤 |
--data JSON 数组 | canvas:node:add / canvas:node:set / canvas:edge:add / canvas:edge:remove 等"需要传字段"的命令 | --data '[{...},{...}]',每项校验必填字段,partial success |
> 升级 CLI 后建议 daemon:stop 一次,避免老 daemon 仍按旧协议解析参数(详见"已知问题 #1")。
0. auth:login <token> (一次性)
1. canvas:create --name "xxx" (自动使用 defaultWorkspace)
2. canvas:node:add --data [{"type":"normal_video_generator","position":"0,0","options":{"prompt":"...","model":"kling","clarity":"RESOLUTION_720P"}}] --canvas "${CANVAS_PATH}"
3. 选 A 或 B 运行:
A. 同步:canvas:run --ids $NODE_ID --wait --timeout 600 --canvas "${CANVAS_PATH}"
→ 阻塞返回最终 outputs,最简单
B. 异步:canvas:run --ids $NODE_ID --canvas "${CANVAS_PATH}"
→ 立即返回 query_hint,再用 task:status 轮询
| 场景 | 推荐 |
|---|---|
| ------ | ------ |
| 单节点 / 短链路 / 想"一行命令拿结果" | canvas:run --wait --timeout 600 |
| 多节点并发触发,调用方自己控制轮询节奏 | 默认异步 + task:status |
| LLM Agent 想避免长时间阻塞主进程 | 默认异步,把 query_hint 保存到任务上下文 |
| 在 shell 脚本里串联多个步骤 | --wait 更直观;超时按节点类型设置(图片 300s、视频 1800s) |
异步模式 canvas:run 立即返回,结果中包含 query_hint:
{
"submitted": true,
"mode": "async",
"results": [
{ "nodeId": "node1", "taskId": "abc1234", "status": "pending" }
],
"query_hint": {
"command": "task:status --ids abc1234 --canvas-id xxx",
"instruction": "请使用上述命令批量查询任务结果,建议间隔 15s"
}
}
轮询步骤:
canvas:run --ids — 立即返回 results 和 query_hintquery_hint.command(已自动拼接所有 taskId)task:status --ids --canvas-id status 为 completed / failed 时停止,最长 30 分钟> outputs 中有效 URL 在 url 字段(带 COS 签名),download_url 可能为空。
# 0. 认证
zenvfx auth:login <your-mcp-token>
# 1. 创建画布
CREATE_RESULT=$(zenvfx canvas:create --name "测试画布" 2>/dev/null)
CANVAS_PATH=$(echo $CREATE_RESULT | grep -o '"canvasPath":"[^"]*"' | sed 's/"canvasPath":"//;s/"$//')
# 2. 批量添加节点(canvas:open 自动执行,无需手动调用)
RESULT=$(zenvfx canvas:node:add --data [{"type":"normal_video_generator","name":"文生视频","position":"0,0","options":{"prompt":"傍晚的海边,小孩子嬉戏玩水","model":"kling","clarity":"RESOLUTION_720P","ratio":"16:9","duration":5}}] --canvas "${CANVAS_PATH}" 2>/dev/null)
NODE_ID=$(echo $RESULT | grep -o '"id":"[^"]*"' | head -1 | sed 's/"id":"//;s/"$//')
# 3. 同步运行(阻塞等待最终结果)
zenvfx canvas:run --ids $NODE_ID --wait --timeout 1200 --canvas "${CANVAS_PATH}"
# 1~2 同上
# 3. 异步运行
RUN_RESULT=$(zenvfx canvas:run --ids $NODE_ID --canvas "${CANVAS_PATH}" 2>/dev/null)
# 从 query_hint 获取轮询命令
QUERY_CMD=$(echo $RUN_RESULT | grep -o '"command":"[^"]*"' | head -1 | sed 's/"command":"//;s/"$//')
# 4. 轮询任务状态(每 15s 一次)
while true; do
STATUS=$(zenvfx $QUERY_CMD 2>/dev/null)
if echo "$STATUS" | grep -qE '"status":"(completed|failed)"'; then
echo "$STATUS"
break
fi
sleep 15
done
> 重要:model/clarity/ratio/duration 的值必须通过 node:model 或 node:defs 动态查询,不要硬编码。
> 视频节点建议:模型 kling + 分辨率 RESOLUTION_720P(比 1080P 快 2-3 倍)。
> node:model 支持批量查询:node:model normal_video_generator,image_generator 一次返回多个类型的模型列表。
> node:defs 一站式知识:node:defs 同时返回本地 schema(pin/option)+ 后端模型枚举/参数,AI Agent 启动期一次拉取即可,避免后续多次往返。
通过 --data 批量模式或 --option + --value 快捷模式传参:
| 参数 | 类型 | 说明 |
|---|---|---|
| ------ | ------ | ------ |
prompt | string | 提示词 |
model | string | 模型 ID(必须通过 node:model 查询) |
clarity | string | 分辨率枚举 |
ratio | string | 画幅比例 |
duration | number | 时长秒数(仅视频节点) |
节点类型(type 必须是下列英文 snake_case 枚举之一,写错会报 NODE_TYPE_INVALID):
type | 说明 |
|---|---|
| -------- | ------ |
text_input / image_input / video_input / audio_input | 输入节点(⚠️ 文本节点是 text_input,不是 text) |
image_generator | 文/图生图 |
normal_video_generator | 文/图生视频 |
first_to_last_video_generator | 首尾帧视频 |
composite_video_generator | 视频编辑 |
comprehensive_reference_generator | 全能参考生视频 |
llm | 大模型文本节点 |
group | 组节点 |
video_process | 视频处理(变速/帧率转换/冻帧延长/裁切) |
frame_extraction | 视频截帧 |
> 中文("提示词"、"文本")是节点 label,不是 type,传给 canvas:node:add 的 --data 中会直接失败。
Prompt 中可以用 @ 前缀引用上游节点通过连线传入的输入资源。占位符直接写在 canvas:node:set 的 prompt 值中即可,画布引擎运行时会自动解析。
支持的占位符(数字后缀可选,默认 1,如 @提示词 等价于 @提示词1):
| 占位符 | 含义 | 上游节点类型 |
|---|---|---|
| -------- | ------ | ------------ |
@提示词1、@提示词2… | 引用上游 文本节点 的文本内容 | text_input / llm |
@参考图、@参考图1… | 引用上游 图片节点 的图片 | image_input / image_generator |
@首帧图1、@首帧图2… | 引用首帧参考图 | image_input / image_generator |
@尾帧图1、@尾帧图2… | 引用尾帧参考图 | image_input / image_generator |
@参考视频、@参考视频1… | 引用上游 视频节点 的视频 | video_input / 视频生成节点 |
@参考音频、@参考音频1… | 引用上游 音频节点 的音频 | audio_input |
@提示词 引用上游文本节点(最常用):
用 text_input 节点写好提示词文本,连线到生成节点的"提示词"输入口,然后在 prompt 中用 @提示词1 引用。画布引擎运行时会直接替换为上游文本节点的文本内容。
# text_input 节点(id=text-001)prompt 值为 "傍晚海边小孩嬉戏"
# 连线:text-001 → video-001 的"提示词1"输入口
zenvfx canvas:node:set --id video-001 --option prompt --value "帮我生成一段视频:@提示词1" --canvas "$CANVAS_PATH"
图片/视频/音频占位符:
同样直接写在 prompt 中,画布引擎运行时会根据模型自动转换为对应格式。
zenvfx canvas:node:set --id $VIDEO_NODE_ID --option prompt --value "小孩奔向海浪@首帧图1,夕阳洒在海面@尾帧图1" --canvas "$CANVAS_PATH"
> 想看模型最终拿到的 prompt 字面值?先用 canvas:node:prompt --id 预览解析结果。
编辑类操作均返回 Partial Success 格式:
{
"results": [
{ "status": "ok", "id": "xxx", "type": "image_generator", "name": "生图节点", "position": { "x": 0, "y": 0 } },
{ "status": "error", "id": null, "type": "unknown_type", "error": "NODE_TYPE_INVALID" }
],
"successCount": 1,
"failCount": 1
}
status 字段标注 "ok" / "error"successCount / failCount 汇总| 错误码 | 含义 | 解决方案 |
|---|---|---|
| -------- | ------ | ---------- |
AUTH_REQUIRED | Token 未配置 | auth:login |
MCP_TOKEN_INVALID | Token 无效/过期 | auth:verify 或重新 auth:login |
CANVAS_NOT_FOUND | 画布不存在 | 检查路径,file:stat 确认 |
CANVAS_SAVE_FAILED | 保存失败(server overload) | 系统已内置重试 3 次(间隔 1s/2s/3s),仍失败则手动重试 |
NODE_NOT_FOUND | 节点不存在 | canvas:node:list 确认 |
NODE_TYPE_INVALID | 节点类型不合法 | 用 text_input / image_input / video_input / audio_input / image_generator / normal_video_generator / first_to_last_video_generator / composite_video_generator / comprehensive_reference_generator / llm / group / video_process / frame_extraction;中文标签不是 type |
INVALID_JSON | --data / --value-json JSON 解析失败 | 检查引号、逗号、括号等 JSON 格式 |
MISSING_VALUE | 必填字段缺失 | 查看报错信息中标注的缺失字段(如 data[0].type 是必填项) |
MISSING_CONFIG | 配置缺失(project 等) | 通过 auth:login 或 config:set defaultProject 设置 |
OPTION_NOT_FOUND | 无该选项 | canvas:node:info --ids 查看可用选项 |
EDGE_HANDLE_INVALID | 连线 handle 不合法 | canvas:node:info --ids 查看 inputPins/outputPins |
DAEMON_TIMEOUT | daemon 超时 | daemon:stop 后重试;若启动直接超时见下文"已知问题 #2 react 缺失" |
DAEMON_START_FAILED | daemon 启动失败 | 检查端口占用,清理后重试 |
DAEMON_CONNECTION_FAILED | daemon 连接失败 | daemon:stop 后重试 |
TASK_SUBMIT_FAILED | 任务提交失败 | 检查节点参数,重跑 node:model <类型> 对齐参数 |
UPLOAD_TOKEN_FAILED / UPLOAD_FAILED / REGISTER_ASSET_FAILED | file:upload 各阶段失败(已内置 3 次重试) | 查 error.message 与 details;多为网络/凭证问题,过段时间重试 |
NETWORK_ERROR | 网络错误 | 检查网络连接,确认 host 配置 |
daemon 异常强制清理:
zenvfx daemon:stop
kill $(cat ~/.config/zenvfx/daemon.pid) 2>/dev/null
rm -f ~/.config/zenvfx/daemon.sock ~/.config/zenvfx/daemon.pid
调试运行节点的请求体(对照网页协议时常用):
daemon 会把每次提交后端的 submitTask 请求体写到 ~/.config/zenvfx/daemon.log。可用脚本快速取最近一次:
bash src/libs/zenvfx-cli/test/scenarios/dump-last-submit.sh # 最近 1 次
bash src/libs/zenvfx-cli/test/scenarios/dump-last-submit.sh 3 # 最近 3 次
bash src/libs/zenvfx-cli/test/scenarios/dump-last-submit.sh 1 image_generator-xxx # 按关键词过滤
> 这里收录已经踩过的"行为不符合预期 / 必须绕过"的问题。修复后请同步移除对应条目。
canvas:run --ids "a,b" 报 nodeId is required(版本错位,不是 bug)zenvfx canvas:run --ids "node1,node2" 报 MISSING_VALUE: nodeId is required。nodeIds: ['node1','node2']nodeId,自然为空nodeIds (string[]) is required,旧文案是 nodeId is required```bash
zenvfx daemon:stop
zenvfx daemon:status # 会自动拉起新版本 daemon
zenvfx canvas:run --ids "node1,node2" --canvas /proj/canvas # 此时正常
```
npm install -g @tencent/zenvfx-cli@latest 后顺手 daemon:stop 一次。DAEMON_TIMEOUT,日志缺 react 模块daemon:stop 后重启 daemon 直接超时,~/.config/zenvfx/daemon.log 显示类似:```
Error: Cannot find module 'react'
at zustand/react.js
```
zustand 管状态,zustand/index.js 间接 import 了 zustand/react.js,但打包时未把 react 作为 bundled 依赖打入;Node.js 端无 react 即启动失败。react 即可——```bash
# 找到全局安装目录
npm root -g
# 进入 CLI 包目录补 react(版本不敏感,挂个 18 即可)
cd "$(npm root -g)/@tencent/zenvfx-cli"
npm install react@18 --no-save --registry=https://mirrors.tencent.com/npm/
# 重启 daemon 验证
zenvfx daemon:stop
zenvfx daemon:status
```
zenvfx-cli 的 esbuild 配置里把 zustand/react 标为 external 或换用 zustand/vanilla,避免引入 react。file:id-to-path 返回路径多拼了"项目名"层级```bash
zenvfx file:id-to-path --id
# 返回: /d6683tdk40pqu9ruglp0/内部项目体验/用户空间/李智_4866893/xxx
# 实际: /d6683tdk40pqu9ruglp0/用户空间/李智_4866893/xxx
```
file:id-to-path 在 projectId 之后多拼了项目名(如"内部项目体验"),与 VFS 实际路径结构不一致。直接用此路径调用 canvas:* / file:stat 会得到 CANVAS_NOT_FOUND / FILE_NOT_FOUND。file:readdir 反查真实路径——```bash
zenvfx file:readdir --path "/
# 或先 file:stat 探测两种路径,哪条 ok 用哪条
```
file:id-to-path 拼接时去掉项目名层级,与 file:readdir / file:stat 路径口径对齐。共 2 个版本