Add UI-design asset extraction & spritesheet support
Introduce a new UI design asset extraction flow: add POST /api/editor/ui-designs/assets/extractions handler that always uses gpt-image-2 with the fixed prompt "提取画面中的所有独立并整理成spritesheet"; parse Data URL references, call OpenAI image edits, return a spritesheet and sliced icon assets. Increase request body limit for image Data URLs and wire the route with bearer auth. Add platform-image slicing: slice_generated_icon_spritesheet_all_by_connected_components (with auto-naming "素材 1..N", foreground estimation and heuristics) and export it. Add Rust tests for the handler, prompt constant, and slicing behavior. Update frontend client and integration tests to call the new extractEditorUiDesignAssets API and verify spritesheet + icon layers are added to the canvas and persisted. Update multiple docs to describe the extraction UI, toolbar placement, and related audio/playback pitfalls. Minor related updates: toolbar button ordering and audio duration / signed read-url notes.
This commit is contained in:
@@ -16,6 +16,14 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-18 图片画布 UI 设计图提取素材保留图集
|
||||
|
||||
- 背景:UI 设计图需要从成图中继续抽取可复用独立素材;原图标素材生成只把拆分后的图标放入画布,spritesheet 原图没有保留,后续追溯和二次切图不方便。
|
||||
- 决策:`assetKind="ui-design"` 图层浮动工具栏新增 `提取素材`,固定调用 `/api/editor/ui-designs/assets/extractions`,后端固定 `gpt-image-2` 和提示词 `提取画面中的所有独立并整理成spritesheet`,返回结构复用图标 spritesheet 响应。图标生成与 UI 提取都必须把 spritesheet 图集作为 `assetKind="icon-spritesheet"` 图层放到画布,再放拆分后的 `assetKind="icon"` 素材。
|
||||
- 影响范围:图片画布浮动工具栏、编辑器图片生成 BFF、`platform-image` 图集连通域拆分、画布图层类型和编辑器文档。
|
||||
- 验证方式:运行图片画布工具栏 / 图集落层 / 生成提交相关前端测试,`cargo test -p platform-image generated_asset_sheets --manifest-path server-rs/Cargo.toml`,以及 `cargo test -p api-server editor_ui_design_asset_extraction_prompt_is_fixed --manifest-path server-rs/Cargo.toml`。
|
||||
- 关联文档:`docs/【编辑器】画板UI设计图生成入口设计-2026-06-17.md`、`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`。
|
||||
|
||||
## 2026-06-18 图片画布 Seedance 2.0 参考媒体提交边界
|
||||
|
||||
- 背景:`/editor/canvas` 生成视频需要严格对齐火山 Seedance 2.0 多模态参考输入;参考视频若继续走 Base64 / `data:video` 会超过请求体并被上游拒绝,参考音频单独输入和非 Seedance 模型携带参考字段也会违反文档契约。
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
- 验证:`cargo test -p platform-audio --manifest-path server-rs/Cargo.toml`;`cargo test -p api-server vector_engine_audio_generation --manifest-path server-rs/Cargo.toml`。
|
||||
- 关联:`server-rs/crates/platform-audio/src/client.rs`、`server-rs/crates/platform-audio/src/response.rs`、`docs/【编辑器】画板音乐生成入口设计-2026-06-18.md`。
|
||||
|
||||
## 图片画布音频卡播放条 0:00 要优先查签名 URL 和嵌套交互
|
||||
|
||||
- 现象:画板音效或背景音乐已经生成成功,但卡片里的播放条显示 `0:00`,点击无法预览。
|
||||
- 原因:generated 音频资源通常是私有 OSS 路径,直接把 `/generated-*` 或 generated OSS 地址交给 `<audio>` 会无鉴权读取失败;如果音频控件嵌在 `<button>` 图层里,浏览器还可能因嵌套交互元素阻断 controls 行为。
|
||||
- 处理:音频图层使用非嵌套交互容器承接画布选择语义,内部 `<audio controls preload="metadata">` 单独阻止 pointer / click 冒泡;generated 音频播放前统一通过 `useResolvedAssetReadUrl` / `/api/assets/read-url` 换签。卡片和角标展示 `时长`,后端没返回时长时可用 `loadedmetadata.duration` 兜底。
|
||||
- 验证:`npx vitest run src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/ImageCanvasMetadataModalView.test.tsx src/components/image-editor/ImageCanvasGenerationLayerModel.test.ts --reporter verbose`,并在浏览器确认 generated 音频控件可播放。
|
||||
- 关联:`src/components/image-editor/ImageCanvasWorldView.tsx`、`src/components/image-editor/ImageCanvasMediaModel.ts`、`docs/【编辑器】画板音乐生成入口设计-2026-06-18.md`。
|
||||
|
||||
## 图片编辑器底部生成按钮不要复用单一画布生成状态
|
||||
|
||||
- 现象:图片画布里先新建一个“生成规范”占位,再点击“生成角色形象”或其它底部生成入口,前一个规范占位和面板状态被销毁。
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
- `DELETE /api/editor/assets/{assetId}`:删除素材。已放入画布的 project resource 不被级联删除,避免旧画布丢图。
|
||||
- `POST /api/editor/images/generations`:按提示词调用 VectorEngine 生成图片;角色生成可携带 `model`、`aspectRatio`、`imageSize` 和 `referenceImageSrcs`。`nanobanana2` 参考图作为 `inline_data` 进入 `generateContent`,`gpt-image-2` 参考图进入 edits。携带参考图的快速编辑也走该接口,前端必须把参考图源预读成图片 Data URL 后放入 `referenceImageSrcs`;接口返回 data URL、尺寸、prompt、model、provider 和 taskId。
|
||||
- `POST /api/editor/icon-spritesheets/generations`:按图标规范图和素材描述数组生成 spritesheet,再由后端切分为独立透明图标。请求支持 `model`、`aspectRatio`、`imageSize` 和 `priceMudPoints`;`priceMudPoints` 必须来自编辑器生成计费配置的 `icon` 档位(首版 12 泥点),后端用 `editor_generation_config` 校验后才调用上游;`nanobanana2` 走原生 `generateContent` 并写入 `generationConfig.imageConfig.aspectRatio/imageSize`,`0.5K` 传 `"512"`;`gpt-image-2` 走 `/v1/images/edits`,后端把 UI 尺寸归一为文档支持的 `1024x1024`、`1024x1536`、`1536x1024`、`2048x2048`、`2048x1152` 等 `size` 字符串。
|
||||
- `POST /api/editor/ui-designs/assets/extractions`:以 UI 设计图 Data URL 作为参考图,固定 `gpt-image-2` 和提示词 `提取画面中的所有独立并整理成spritesheet` 生成素材 spritesheet,再按连通域自动拆分为 `素材 1..N`,返回结构复用图标 spritesheet 响应。前端必须把 spritesheet 原图与拆分素材都加入画布。
|
||||
- `POST /api/editor/images/edits`:按提示词和当前图片 Data URL 调用 VectorEngine edits,返回新的生成图片元数据。
|
||||
- `POST /api/editor/videos/generations`:按视频描述、模型、比例、时长、分辨率、模式、声音和泥点价格生成视频。前端可选模型为 `seedance2.0-fast`、`seedance2.0`、`kling3.0`、`kling3.0-omni`,默认 `seedance2.0-fast`;后端必须将 `seedance2.0-fast` 映射到 `doubao-seedance-2-0-fast-260128`,将 `seedance2.0` 映射到 `doubao-seedance-2-0-260128`,两者不得混用。后端复用 Ark / VectorEngine content generation task 轮询链路,下载最终视频并持久化到 OSS,返回 `videoSrc`、尺寸、prompt、model、provider、taskId、durationSeconds、resolution 和 `priceMudPoints`。
|
||||
|
||||
@@ -95,7 +96,7 @@
|
||||
- 快速编辑面板底部必须以禁用态参数按钮显示原图尺寸和原图模型,视觉对齐可编辑面板参数控件;参考图顺序为额外参考图在前、原图在最后。
|
||||
- 点击生成、生成规范、生成角色形象或生成图标素材后创建的占位图可继续保留;点击画布空白区域让当前图片或占位图失焦时,关闭当前生成面板并移除图片选中样式,但不删除占位图本身。
|
||||
- 生成资源显示元数据按钮,元数据窗口展示来源、生成输入快照、model、provider、task、Resolution 和 OSS 引用;生成输入快照只包含用户面板输入和参考图,不包含后端拼接 Prompt,不再展示独立 Size 字段。
|
||||
- 图片选中后的浮动工具栏按钮顺序固定为:快速编辑、分割线、裁扩按钮、去除背景按钮、角色图专属生成动画、分割线、重绘、下载按钮。裁扩通过画布边界拖拉完成,不再展示四边数值输入;默认自由比例,选择固定比例后拖拉边界保持对应比例,完成后在原素材旁边新增裁扩结果图层,扩展区域透明填充。去除背景使用前端轻量去背并回写为新的工程资源快照。
|
||||
- 图片选中后的浮动工具栏按钮顺序固定为:快速编辑、分割线、裁扩按钮、去除背景按钮、UI设计图专属提取素材、角色图专属生成动画、分割线、重绘、下载按钮。裁扩通过画布边界拖拉完成,不再展示四边数值输入;默认自由比例,选择固定比例后拖拉边界保持对应比例,完成后在原素材旁边新增裁扩结果图层,扩展区域透明填充。去除背景使用前端轻量去背并回写为新的工程资源快照。UI设计图的提取素材固定走 `gpt-image-2` 和提示词 `提取画面中的所有独立并整理成spritesheet`,生成的 spritesheet 原图和拆分后的独立素材都作为画布图层保留。
|
||||
- 重绘生成资源后,右侧出现新生成结果图层,并自动 fit 原图 + 新图,且重绘面板保持打开。
|
||||
- 快速编辑 / 重绘站内 public 示例图、历史 generated 图或 OSS generated 图时,前端先读取成 `data:image/*;base64,...` 再提交,后端不得再收到 `/creation-type-references/*`、`/generated-*` 或 OSS URL 作为 `referenceImageSrcs/sourceImageSrc`。
|
||||
- 快速编辑的额外参考图同样必须在前端读取成图片 Data URL 后提交;后端 `referenceImageSrcs` 上限为 9 张,承载 8 张额外参考图加 1 张原图。
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
## 生成视频模型与接口
|
||||
|
||||
- 底部 `生成视频` 面板提交到 `POST /api/editor/videos/generations`。
|
||||
- 固定 `16:9`、静音、标准模式;结果作为 `mediaType="video"`、`assetKind="video"` 的视频图层加入画布。
|
||||
- 固定 `16:9`、静音、标准模式;结果作为 `mediaType="video"`、`assetKind="video"` 的视频图层加入画布,并在画布中使用原生 `<video>` 播放控件渲染,不再走图片元素。
|
||||
- 支持模型:
|
||||
- `seedance2.0-fast`
|
||||
- `seedance2.0`
|
||||
@@ -163,6 +163,7 @@
|
||||
- 快速编辑生成中的占位图同样只支持键盘 `Delete` / `Backspace` 删除,不新增 UI 删除按钮;删除后异步结果不得再落回画布。
|
||||
- 生成视频 / 角色形象 / 角色动作 / 音效 / 背景音乐新建后,画布占位空白样式和右上角标签均与对应生成类型一致,不再统一使用图片占位 icon。
|
||||
- 点击角色图只选中图层并显示工具栏,不自动弹出重绘、快速编辑或角色动画面板;点击工具栏或右键菜单中的 `生成动画` 才创建角色动作占位和面板。
|
||||
- 点击 UI 设计图只选中图层并显示工具栏;工具栏在 `去除背景按钮` 后显示 `提取素材`,点击后固定用 `gpt-image-2` 和提示词 `提取画面中的所有独立并整理成spritesheet` 生成 spritesheet,再复用图标素材拆分流程,把 spritesheet 图集和拆分素材都放到画布。
|
||||
- 生成游戏音效面板底部不显示 `type` / `tempo` 字段标题,只有一个音效参数按钮;type 只支持 `one-shot` / `loop`,BPM 为 `1-300` 的数字或 `null`,选择后按钮显示 `单次·120BPM` 这类组合值。
|
||||
- 生成视频结果以视频图层加入画布,画布媒体元素标记为 `画布视频:生成视频 N`。
|
||||
- 生成器输入、参数、参考图和占位框在刷新后仍存在;已生成对象的生成器面板继续跟随成品图层。
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
- 底部 AI 画布工具栏新增 `生成UI设计图`。
|
||||
- 点击后立即在画布中新建 `UI设计图生成占位图`,不复用普通新建图片的空白样式。
|
||||
- 占位图默认 16:9 展示,生成成功后替换为 `assetKind: "ui-design"` 的画布图层。
|
||||
- 用户点击 `assetKind: "ui-design"` 图层后,图片上方浮动工具栏在 `去除背景按钮` 后显示 `提取素材` 按钮;普通图片、角色图和图标图层不显示该入口。
|
||||
|
||||
## 生成面板
|
||||
|
||||
@@ -44,6 +45,18 @@
|
||||
|
||||
生成请求固定使用 `gpt-image-2`。有参考图时走图片编辑请求;无参考图时走图片生成请求。
|
||||
|
||||
## 提取素材
|
||||
|
||||
- 点击浮动工具栏 `提取素材` 后,前端把当前 UI 设计图读取为图片 Data URL,提交到 `POST /api/editor/ui-designs/assets/extractions`。
|
||||
- 后端固定使用 `gpt-image-2` 图片编辑链路,并固定提示词:
|
||||
|
||||
```text
|
||||
提取画面中的所有独立并整理成spritesheet
|
||||
```
|
||||
|
||||
- 后端收到 spritesheet 后复用图标素材的连通域拆分能力;未知素材数量时按从上到下、从左到右自动命名为 `素材 1`、`素材 2`。
|
||||
- 前端先把 spritesheet 原图作为 `assetKind: "icon-spritesheet"` 图集图层放在 UI 设计图右侧,再把拆分出的独立素材作为 `assetKind: "icon"` 图标图层继续放到画布。
|
||||
|
||||
## 验收点
|
||||
|
||||
- 点击 `生成UI设计图` 后出现 UI 设计占位图和独立生成面板。
|
||||
@@ -51,3 +64,4 @@
|
||||
- 从画布选择时只能绑定图标规范图片。
|
||||
- 请求参数包含 `kind: "ui-design"`、`model: "gpt-image-2"`、比例、大小与可选参考图。
|
||||
- 生成图层信息面板展示 `用户输入` 与 `图标规范`。
|
||||
- 选中 UI 设计图时浮动工具栏显示 `提取素材`;点击后调用固定 `gpt-image-2` 提取接口,画布同时出现 spritesheet 图集和拆分后的独立素材。
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
- 底部 AI 画布工具栏新增 `生成图标素材` 按钮。
|
||||
- 点击后立即在画布中心创建图标素材占位图,不复用普通“单张空白图片”图标;占位图表现为一叠空白素材图标卡片。
|
||||
- 图标素材面板锚定在占位图下方,和现有生成输入框同一层级展示。
|
||||
- 生成完成后删除占位态,把拆分出的每个独立图标素材作为画布图片图层铺开,图标之间不重叠,并保留少量间距。
|
||||
- 生成完成后删除占位态,先把后端返回的 spritesheet 原图作为 `assetKind: "icon-spritesheet"` 的图集图层放到画布,再把拆分出的每个独立图标素材作为画布图片图层铺开,图集与图标之间、图标彼此之间不重叠,并保留少量间距。
|
||||
- 图标素材图层写入 `assetKind: "icon"`;图标规范图写入 `assetKind: "icon-spec"`,用于刷新后保留标签和限制点选来源。
|
||||
|
||||
## 面板结构
|
||||
@@ -64,10 +64,10 @@
|
||||
|
||||
## 前端铺放规则
|
||||
|
||||
- 第一张图标放在原占位图左上附近。
|
||||
- 后续图标按行铺开,图标之间保留约 `24px` 世界坐标间距。
|
||||
- spritesheet 图集放在原占位图左上附近。
|
||||
- 第一张拆分图标放在 spritesheet 图集右侧,后续图标按行铺开,图标之间保留约 `24px` 世界坐标间距。
|
||||
- 每个图标图层标题使用对应素材描述文本。
|
||||
- 生成成功后关闭图标素材面板,选中第一张图标素材,并打开图层面板。
|
||||
- 生成成功后关闭图标素材面板,选中 spritesheet 图集,并打开图层面板。
|
||||
|
||||
## 验收
|
||||
|
||||
@@ -76,5 +76,5 @@
|
||||
- 默认 6 个素材描述会进入 prompt;用户在单个文本框中继续输入时最多解析 100 个素材描述。
|
||||
- 默认打开图标素材面板时选中 `nanobanana2 / 1:1 / 1K`;模型切换后,角色和图标素材面板之间沿用上次选择的模型。
|
||||
- 图标素材生成请求必须带 `model`、`aspectRatio` 和 `imageSize`;`nanobanana2` 请求体必须包含 `generationConfig.imageConfig.aspectRatio/imageSize`,`gpt-image-2` 请求必须包含文档映射后的 `size`。
|
||||
- 生成成功后画布出现按描述命名的多个透明图标素材图层,图层之间不重叠。
|
||||
- 生成成功后画布出现 spritesheet 图集和按描述命名的多个透明图标素材图层,图层之间不重叠。
|
||||
- 生成图标素材提交体包含 `priceMudPoints: 12`;若前端传入与后端计费配置不一致的值,后端返回 `priceMudPoints` 校验错误,不继续调用上游生成。
|
||||
|
||||
@@ -44,7 +44,11 @@
|
||||
- `assetKind="sound-effect"`
|
||||
- `assetKind="background-music"`
|
||||
- 音频结果以小型音频卡加入画布,卡片内使用 `<audio controls>` 播放;音频结果当前只保存为画布资源,不进入图片素材库。
|
||||
- 元数据弹窗按音频显示 `音频信息` / `音频类型`,生成输入快照只展示用户面板字段。
|
||||
- 音频结果卡片显示用户提示词和 `时长 mm:ss`;如果上游暂未返回时长,先显示 `时长 --:--`,并在 `<audio>` 元数据加载后用真实 duration 兜底。
|
||||
- generated 私有音频资源播放前必须通过 `/api/assets/read-url` 换签;画布卡片不得直接把 `/generated-*` 或 generated OSS 私有地址交给 `<audio>` 裸请求。
|
||||
- 音频卡片、音频生成占位和元数据弹窗都使用 `时长`,不使用图片 / 视频的分辨率语义。
|
||||
- 音频图层右上角标签显示在信息按钮左侧,和其他素材卡右上角信息区保持一致。
|
||||
- 元数据弹窗按音频显示 `音频信息` / `音频类型` / `时长`,生成输入快照只展示用户面板字段。
|
||||
|
||||
## 前端提交契约
|
||||
|
||||
@@ -84,7 +88,8 @@ POST /api/editor/audios/background-music/generations
|
||||
provider: string,
|
||||
taskId: string,
|
||||
priceMudPoints: number,
|
||||
audioKind: "sound-effect" | "background-music"
|
||||
audioKind: "sound-effect" | "background-music",
|
||||
durationSeconds?: number | null
|
||||
}
|
||||
```
|
||||
|
||||
@@ -113,5 +118,7 @@ POST /api/editor/audios/background-music/generations
|
||||
- 点击 `生成游戏背景音乐` 后出现背景音乐面板,字段为 `gpt_description_prompt`,不展示 `make_instrumental`。
|
||||
- 音效提交到 `/api/editor/audios/sound-effects/generations`,背景音乐提交到 `/api/editor/audios/background-music/generations`。
|
||||
- 成功后画布新增音频卡,能通过 `<audio controls>` 播放。
|
||||
- 成功后的音频卡展示提示词;卡片、悬停角标、信息弹窗和待生成占位均显示时长。
|
||||
- 私有 generated 音频能先换签再预览播放,不出现播放条一直为 `0:00` 的裸路径失败状态。
|
||||
- 刷新后 layout 能恢复音频生成器和音频图层。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user