无限画布
Spark Work 无限画布(Infinite Canvas)能力全景:项目管理、节点类型、AI 操作、任务队列、生成结果节点、lineage 边、资产中心、媒体任务路由与持久化。
无限画布(Infinite Canvas)不是一张生图页面,而是以项目为单位的多模态创作工作台: 你在一个可平移缩放的画布上摆文本、图片、视频、音频和 AI 操作节点, 用连线表达「谁是谁的输入」,AI 产物自动落成新节点并保留来源关系。 这一页讲清楚真实的节点枚举、菜单结构、任务链路、资产中心和持久化位置。
1. 核心闭环
- 在画布模式的项目列表里新建(或打开)一个 Canvas 项目。
- 进入画布,导入素材或直接双击空白处新建文本 / Prompt 节点。
- 选中节点,用右键菜单或顶部工具条发起一个 AI 操作(例如「图片生成」)。
- 操作节点有自己的配置面板;确认 Prompt、模型与参数后提交运行。
- 主进程创建任务,走媒体路由(云端 Provider)或本地能力(深度视频、分离音频、提取首尾帧)。
- 任务进度通过流式事件回写画布,操作节点上显示 running,右侧面板「任务」tab(任务队列)里能看到明细。
- 成功后自动生成结果节点,并在输入 / 输出之间建立血缘边。
- 结果节点可以继续作为下一个操作的输入,整条流水线一直往前推。
2. 项目管理与画布
切到侧边栏的**「画布」**模式,没选项目时是欢迎页,列出最近打开的项目 (最多 8 个,按更新时间倒序)。新建流程是:
- 点「新建项目」,或在侧栏触发同一个创建信号。
- 在「新建 Canvas 项目」对话框里填项目名称(占位文案是 「例如:618 商品主图」)、可选的描述,以及封面图(占位提示「点击选择封面图(建议 16:9,<= 8MB)」)。
- 点「创建并进入画布」。之后在项目卡片上可以编辑、置顶、打开文件夹、导出、归档或删除; 进入项目详情后,还可以在资产条目上右键「设为封面」把任意已有资产设为项目封面。
每个项目会在磁盘上有一个真实目录,默认位置是应用数据目录下的canvas-projects/(可以在画布设置里改根路径),目录名是<项目名>-<项目 id>。目录里固定有:
assets/,下面分images/、videos/、audio/、files/;thumbnails/、tasks/、exports/;snapshots/,含latest.json与按时间戳命名的历史快照;project.json,是导出的项目包清单(kind: spark.canvas.project)。
一个项目就是一个可见画布。底层历史数据里可能还带 boardId, 但当前 UI 没有挂载多画板侧栏;内置的画布助手提示词也明确要求不要创建 / 删除 / 复制 / 重命名 / 切换画板,需要区分内容时用分组、区域和命名来组织。
3. 节点类型
画布节点分两类:内容节点承载素材,**操作节点(任务节点)**承载一次 AI 操作。操作节点的node.type与node.data.operation 一一对应, 下面是完整枚举(中文名取自应用里的节点标签映射):
| 类型(type) | 界面名 | 说明 |
|---|---|---|
image | 图片 | 本地上传、粘贴或 AI 产出 |
video | 视频 | 可内联预览,也是视频工作台的入口 |
audio | 音频 | 音频节点有独立的探测 / 截取 / 变速能力 |
text | 文本 | 文案、脚本、备注;也可作为 Prompt 载体 |
prompt | Prompt | 结构化提示词节点 |
group | 分组 | 把多个节点编组,可折叠成封面卡 |
操作节点的类型枚举(共 19 个,另有 1 个已废弃类型):
| type / operation | 界面名 | 产物 |
|---|---|---|
text_generate | 文本生文 | 文本 |
text_rewrite | 文本改写 | 文本 |
prompt_optimize | Prompt 优化 | Prompt |
image_prompt_reverse | 图片反推 | 文本 |
text_to_image | 文生图 / 图片生成 | 图片 |
image_to_image | 图生图 | 图片 |
image_edit | 图片编辑 | 图片 |
image_compose | 多图合成 | 图片 |
storyboard_grid | 故事板 | 图片 |
panorama_360 | 全景图 | 图片(2:1 等距圆柱投影) |
text_to_video | 视频生成 | 视频 |
image_to_video | 图生视频 | 视频 |
video_edit | 视频编辑 | 视频 |
video_extend | 视频扩展 | 视频 |
video_depth_map | 深度视频转换 | 视频(本地推理) |
extract_audio | 分离音频 | 音频 |
extract_first_last_frames | 提取首尾帧 | 图片 |
text_to_audio | 文生音频 | 音频 |
audio_transcribe | 语音转写 | 文本 |
task(已废弃) | 任务 | 旧通用任务节点,只保留读取兼容,新节点不再创建 |
几条交互约定:
- 标题格式是
#编号 标题,例如#3 图片、#7 文生图。编号按当前画布里现存节点的最大编号 + 1 分配。 - 双击:分组节点折叠 / 展开,其他节点打开编辑弹窗。 操作节点还有自己的配置面板(Prompt、模型、参数),从节点或工具条打开。
- 选中单个节点时顶部出现常驻工具条(提交运行、预览、展开产物、复制节点、视频编辑、分离音频、提取首尾帧、尺寸与压缩等,按节点能力出现)。
- 取消任务用节点上的取消入口,或右侧任务队列里的取消按钮;批量取消在任务队列顶部。
4. AI 操作
发起操作有三个入口:空白画布右键、节点右键菜单, 以及节点工具条 / 选中后的「AI 操作」面板(面板标题就是「AI 操作」,副标题「基于画布选择创建任务」)。 菜单按用途分组,不是一长条平铺列表。
4.1 右键菜单结构
右键一个节点,菜单按可用性拼装,稳定出现的部分有:
- 视频编辑 / 尺寸与压缩:仅当节点是视频节点(或操作节点的产物是视频)时出现。
- 影视创作(二级菜单):按「文本编排 / 资产提取 / 视觉生成 / 视频生成」四组, 放入流水线动作,例如「转剧本」「生成分镜脚本」「提取角色」「生成分镜关键帧图」 「生成角色身份板」「生成场景图」「生成关键帧」「出视频(首尾帧)」「按剧情分集」 「场景 360 全景图」等。这些动作按节点的流水线角色与内容类型筛选—— 没有角色的普通文本节点也能拿到剧本类入口,而不是所有节点都看到全部动作。
- 特色功能(二级菜单):
- 视觉工具:上下文专属动作——图片节点有「图片扩图」「提取风格」 「细节设定图(九宫格)」;文本 / Prompt 节点有「提取风格」「细节设定图(九宫格)」; 之后统一接「故事板」和「360 全景图」。
- 媒体工具:深度视频转换、分离音频、提取首尾帧。
- 图片工具(图片类节点且有产物时):尺寸与压缩、图片标注、 提取子视图、宫格切分。
- 基础任务(直接列在菜单里,不折叠):文本生文、图片生成、 图片反推、视频生成。注意「图片生成」是一个合并入口,运行时按所选模式和参考图数量 归到文生图 / 图生图 / 多图合成。
- 其余是节点管理动作:保存到资源库…、添加到 Agent 对话(把节点加进画布 Agent 的引用列表)、切换类型(仅图片 / 文本等可切换子类型)、 分组节点上的「选中组内节点 / 折叠编组 / 多图合并 / 解散组」、组内节点的「移出组」, 以及危险色的删除节点。
选中两个以上节点再右键,走的是批量菜单(编组、批量配置任务、批量提交等), 而不是上面这份单节点菜单。
「文生音频」和「语音转写」这两个能力仍然存在(能力表里能查到,输入输出类型也定义了), 但当前右键菜单的基础任务分组会过滤掉音频组; 需要它们时从操作面板的「AI 操作」面板或预设中心选。
4.2 图片反推与深度视频转换
这两个操作的配置面板形态和其它操作明显不同,值得单独记:
- 图片反推:输入恰好一张图片,产物是文本。面板里没有自定义参数, Prompt 区域改叫「反推要求」(占位示例是「只反推图中场景;只描述人物外观;…」), 提交按钮是「生成提示词」。它走视觉理解模型,需要你配置一个支持图片输入的对话模型。
- 深度视频转换:输入一段本地视频,输出近白远黑的深度视频。 面板里没有 Prompt、没有云端 Provider 和模型参数,只显示本地深度组件的状态, 提交按钮是「生成深度视频转换」。
4.3 360 全景图与环视预览
360 全景图产出 2:1 等距圆柱投影(equirectangular)图片,用来锁定一个场景的 光照与物体布局;从同一张全景图取不同角度截图,多镜头之间天然一致。 右键全景产物节点选「全景预览」打开查看器,工具栏上有:
- 重置:把视角复位到默认朝向与默认 FOV。
- 自动环视开关:自动水平旋转,适合审片和录屏。
- 遥测读数:水平朝向、
Pitch、FOV三个值, FOV 滑杆范围 30°~100°(默认 75°)。 - 框选截图:在画面上拖框截取局部区域。
- 截图生成场景图:把当前视角整帧落成新的画布图片节点。
操作方式:拖拽或触屏滑动看方向,滚轮 / 滑杆缩放,方向键环视(+/- 缩放), 顶栏按钮进入「沉浸全屏」。图片标题栏会显示它是2:1 equirectangular还是普通panorama image(按宽高比判断,容差 0.22)。WebGL 不可用时查看器会明确提示,而不是黑屏。

4.4 快速创作:同一张画布外的轻量创作入口
快速创作是画布内的轻量生成面板:不摆节点、不连线,直接把「输入素材 + 提示词」提交成一个生成任务。它默认是主窗口里的一块画布导航页面,页头有一个「在独立窗口中打开」按钮可以把它切到一个单独的窗口。
三个模式页签(生图 / 反推 / 视频),真实操作类型按你放的素材自动判定:
| 模式页签 | 无输入素材 | 有输入素材 | 素材上限 |
|---|---|---|---|
| 生图 | 文生图(text_to_image) | 图片编辑(image_edit) | 6 |
| 视频 | 文生视频(text_to_video) | 输入含视频 → 视频编辑(video_edit);输入是图片 → 图生视频(image_to_video) | 6 |
| 反推 | 固定为 image_prompt_reverse | 同左 | 1(多余素材会被拒绝并提示) |
生图模式下,一旦你加了参考素材,面板提示会直接变成「已添加参考素材,当前按图像编辑处理」——这不是两个按钮,而是同一个提交入口根据素材切换了操作类型。反推模式只有 1 张图的上限,因为它的产物是一份可编辑的提示词,不是回填到你选中的图上的改动。
判定的意义不只是换个按钮文案:操作类型决定了模型候选。面板只会列出当前素材真正支持的能力对应的、已启用的模型,所以不会出现「选完模型提交才发现跑不动」的情况。视频参考输入会同时考虑 video.reference_to_video 与 video.edit 两种能力,避免仅支持参考视频生视频的模型(例如自建的 MiniMax H3)在选了参考视频后一个模型都选不出来。
顺带一个和画布主流程的区别:任务的产物落在画布媒体目录里,但不会自动在画布上创建节点。要移动或继续加工,用产物菜单里的「另存为…」「打开所在文件夹」「去图编辑」「复用配置」这几个动作完成。
独立窗口是怎么实现的:
- 它复用同一套 renderer 与任务流,只是把页面容器移到单独的
BrowserWindow。 - 生成任务本身跑在主进程,渲染层的视图只是订阅进度。所以切走这个页面(视图卸载)或关掉独立窗口,都不会中断正在跑的任务。
- 视图首次进入时会注册一次全局的进度订阅,把事件补丁回写到本地任务记录;重新挂载时还会对账一次,纠正「事件丢失(例如应用重启)导致任务永远停在 running」的记录。
任务与清理:
- 创作任务记录保存在本地,最多保留 60 条。
- 删除一条任务时会一并清理本次任务的输入拷贝与生成产物;你的原始文件、以及与其他功能共享的素材(例如粘贴图)不会被删。删除优先送系统回收站(可恢复),回收站不可用时才回退为直接删除。
5. 任务、队列与血缘
提交操作节点后,画布右侧面板的**「任务」** tab(标题是「任务队列」)是任务的权威视图, 顶部有筛选:全部 / 运行 / 失败 / 完成, 并且提供「全部取消」和「清理无节点」两个批量动作 (后者用于清理承载节点已被删除的残留任务)。
任务状态是五个值:
| 状态 | 含义 |
|---|---|
pending | 已入队,尚未开始 |
running | 执行中(节点上有 running 视觉态) |
completed | 成功,产物已落画布 |
failed | 失败;节点上显示「失败:<错误信息>」,任务队列与任务详情里有完整错误 |
cancelled | 被用户取消 |
血缘边是画布的基础数据结构,不是装饰。边的类型有五种:derived_from(派生自)、used_as_input(作为输入)、generated(由任务生成)、group_contains(分组包含)、references(引用)。一条边记录了 projectId、sourceNodeId、targetNodeId、 type、可选的 taskId 和 metadata,所以你可以从任一产物一路回溯到最初的输入与任务。
任务运行态会通过流式事件推给渲染端(媒体任务走stream:canvas:media-task),所以进度、阶段文案和终态都是实时显示的。 另外注意一个硬限制:本地深度视频转换同时只允许 1 个任务, 再提交会直接报错「已有深度视频转换任务正在运行」。
6. 资产中心与项目资产库
画布底部工具栏的「项目资产中心」是项目级公用资产的入口,按 tab 组织:
- 文稿(可下钻到章节正文)、剧本
- 角色、场景、道具、特效
- 分镜分组、提示词库
- Files:管理远端 Provider 的文件(例如火山方舟 / 百炼 / MiniMax 的 Files 接口)
每个 tab 里都支持关键词搜索、标签筛选和排序(最近修改 / 最近创建 / 按名称 / 按使用次数), 列表分批渲染(文稿类资产可能上千条)。资产条目可以编辑、用 AI 优化(走文本改写能力), 或插入画布。
左侧工作台里还有一个更偏治理的项目资产库(同一份数据的另一视图), 分类是:全部资产、收藏、角色、场景、道具、特效、文稿、剧本、分镜分组、提示词库、Files。 它支持:
- 列表 / 网格两种视图,多选(单次上限 30 个,避免大量资产时卡死)。
- 批量下载、批量插入画布、批量删除。
- 查看资产被哪些节点引用、由哪个任务生成、以及落盘路径。
- 从节点右键「保存到资源库…」把画布上的产物回存为资产; 资产条目可以直接拖进画布 Agent 的对话(拖拽载荷带类型信息), 也可以用批量动作「插入画布」把它放回画布。
7. 持久化与产物落盘
这一节是排查「我的画布还在不在」时最该看的。SQLite 才是画布的生产权威存储, localStorage 只是同会话内的热缓存。
- 热缓存:所有画布交互先写内存与 localStorage(写入做了 500ms 防抖合并), 只保证同一会话内打开快。
- 落库:默认是手动保存模型——
Ctrl/Cmd+S、 保存按钮、或离开时的确认弹窗触发全量落库,写入 SQLite 的canvas_projects与canvas_snapshots。 - 自动保存:工具栏上有「自动保存」开关,开启后停止操作约 1.2 秒触发保存, 且两次保存之间至少间隔 30 秒;失败会按 1.2s × 2ⁿ 退避(上限 30 秒), 连续失败 5 次后停止重试,避免把 CPU 打满。
- 同时写项目文件:每次落库都会把项目快照写到项目目录, 即
project.json与snapshots/latest.json, 并追加一份时间戳快照;时间戳快照只保留最近 10 份,退出画布后收紧到 2 份,latest.json永不删除。 - 未保存改动有守卫:离开画布时会检查未落库的项目并弹确认, 选「不保存」会把该项目回滚到上次落库状态(否则残留的 localStorage 数据会在下次保存时被写回去)。
生成产物与预览协议:
- 画布媒体产物默认落在
userData/.spark-artifacts/media/, 按类型分子目录(images/videos/audio/files), 各功能还有自己的子目录,例如video-workbench、canvas-depth、canvas-audio、canvas-frames、image-process、annotations。 - 渲染端用自定义协议读取本地文件:
safe-file://x/<base64 绝对路径>, 响应带Content-Type、Content-Length、Accept-Ranges, 所以视频可以拖动进度条 seek。 - 该协议有严格白名单:只放行应用数据目录、系统临时目录、
~/.spark-agent/board-attachments、已登记的工作区根目录,以及画布项目根目录; 其它路径一律 403。
8. 错误码与排错
媒体任务把各家 Provider 的报错归一成一套错误码,画布与 Inspector 展示的就是它们:
| 错误码 | 含义 / 处理 |
|---|---|
provider_not_configured | 没有可用 Provider;界面会提示去「模型 / Agent 配置」添加 |
capability_not_supported | 已配置的 Provider 不支持这个能力(或缺对应模型) |
api_key_missing | Provider 没有密钥,去「模型」页补填 |
invalid_input | 输入不合法(缺必填输入、参数越界等) |
provider_http_error | 上游返回非 2xx,看任务详情里的请求摘要 |
auth_required | 上游要求重新授权 |
task_failed | 异步任务终态失败 |
task_timeout | 异步任务轮询超时 |
artifact_download_failed | 产物下载失败(链接过期、网络等) |
local_depth_failed | 本地深度视频转换失败(模型 / 运行时问题,可在完整性页修复) |
失败任务不会消失,节点保持failed状态:节点上显示 「失败:<错误信息>」,任务队列卡片与任务详情弹窗里有完整错误内容。 如果看到 provider_not_configured且提示是「请先在『模型 / Agent 配置』中添加可用模型」, 说明是通用的「一个 Provider 都没配」;如果消息更具体,就按消息本身排查。
9. 当前限制
下面这些是能在代码里对上的真实限制,规划时先按这个预期走:
- 一个项目一个可见画布:多画板侧栏组件未挂载,画布助手也被告知不要切换画板。
- 深度视频转换串行:同一时间只允许一个本地深度任务。
- 深度转换的输入路径受限:输入视频必须在画布或已登记工作区目录内, 否则直接拒绝(路径不在允许范围)。
- 右键菜单不提供音频能力:文生音频 / 语音转写要从操作面板的能力入口选。
- 旧
task节点只读兼容:历史画布里的通用任务节点还能打开, 但新操作一律创建类型化操作节点。 - 快照有保留上限:单项目时间戳快照 10 份、退出画布后 2 份, 需要长期归档时用项目菜单里的「导出」(导出项目包)而不是靠快照堆积。
速查表
| 项目 | 内容 |
|---|---|
| 内容节点类型 | image / video / audio / text / prompt / group |
| 操作节点类型 | text_generate / text_rewrite / prompt_optimize / image_prompt_reverse / text_to_image / image_to_image / image_edit / image_compose / storyboard_grid / panorama_360 / text_to_video / image_to_video / video_edit / video_extend / video_depth_map / extract_audio / extract_first_last_frames / text_to_audio / audio_transcribe |
| 节点标题格式 | #编号 标题(编号 = 画布内最大编号 + 1) |
| 右键菜单分组 | 影视创作 / 特色功能(视觉工具·媒体工具·图片工具)/ 基础任务 |
| 任务状态 | pending / running / completed / failed / cancelled |
| 血缘边类型 | derived_from / used_as_input / generated / group_contains / references |
| 任务队列入口 | 画布右侧面板「任务」tab(筛选:全部 / 运行 / 失败 / 完成) |
| 项目默认根目录 | userData/canvas-projects/<项目名>-<项目 id> |
| 持久化 | SQLite canvas_projects + canvas_snapshots(默认手动保存,可开自动保存) |
| 热缓存 | localStorage,500ms 防抖合并写入 |
| 产物目录 | userData/.spark-artifacts/media/{images,videos,audio,files,...} |
| 本地文件协议 | safe-file://x/<base64 绝对路径>(白名单之外 403) |
| 快照保留 | 时间戳快照 10 份,退出画布后 2 份(latest.json 永不删) |
上手清单:用无限画布完成一次文生图迭代
从新建项目到产出第一个图片节点,并保留血缘
- 切到侧边栏「画布」模式,点「新建项目」,填项目名称、描述与封面,点「创建并进入画布」
- 在空白处右键新建一个文本或 Prompt 节点,写入提示词
- 右键该文本节点,在「基础任务」里选「图片生成」,或在节点工具条的 AI 操作面板里选
- 在操作面板里确认 Prompt、选择模型与参数,提交运行
- 打开右侧面板「任务」tab 查看进度;节点会显示 running,完成后自动生成图片节点并建立血缘边
- 在图片节点上继续右键发起「图片编辑」或「多图合成」等下一步操作
- 需要长期归档时用项目菜单的「导出」生成项目包,而不是依赖快照堆积
常见问题
画布上的「任务节点」和以前有什么不同?
现在一次 AI 操作就是一个类型化操作节点(例如 text_to_image、video_depth_map),它同时承载配置、运行状态和产物;旧的通用 type 为 task 的节点只保留读取兼容,新节点不再创建。
画布数据存在哪里?
SQLite 的 canvas_projects 与 canvas_snapshots 是生产权威存储,默认手动保存(Cmd/Ctrl+S、保存按钮或离开确认),也可开自动保存。localStorage 只是同会话的 500ms 防抖热缓存。每次落库还会写项目目录里的 project.json 与 snapshots/latest.json。
生成的图 / 视频落在哪个目录?
默认在 userData/.spark-artifacts/media/ 下,按类型分子目录(images / videos / audio / files),深度视频、视频工作台产物、抽帧结果等各有独立子目录。渲染端通过 safe-file:// 协议读取,白名单之外一律 403。
为什么右键菜单里找不到文生音频 / 语音转写?
右键菜单的基础任务分组当前会过滤掉音频组。这两个能力仍在能力表里,从操作面板的「AI 操作」入口或预设中心选即可。
可以同时跑多少个深度视频转换?
一次只能跑一个。已有任务在运行时再次提交会直接报「已有深度视频转换任务正在运行」,需要等它完成或先取消。
一组节点之间的连线有什么用?
连线是血缘边,类型有 derived_from / used_as_input / generated / group_contains / references,记录了来源节点、目标任务和元数据。它决定了操作节点的可用输入,也是你回溯某个产物是怎么来的依据。