WIP: [编辑器] 支持 Spine 序列帧多模态生成与后处理链路 #171

Closed
suzmii wants to merge 23 commits from feat/spine-sequence-export-v2 into master
Member

背景

为编辑器补齐 Spine 序列帧动画的完整创作链路:

  • 从文本、角色图片或参考视频生成角色动作序列帧;
  • 将已有视频直接转换为序列帧;
  • 支持序列帧拆帧、算法去背景和 Spine JSON 导出;
  • 保证异步生成、刷新恢复、对象存储幂等和资源来源校验;
  • 保持 Spine 序列帧与视频一致,不提供快速编辑入口。

主要变更

1. Spine 序列帧多模态生成

新增统一的 Spine 序列帧生成面板,支持:

  • 文本生成角色动作;
  • 角色图片生成动作;
  • 参考视频生成动作;
  • 动作视频与角色外观图组合;
  • AI 生成 / 改造与视频直接转换两个模式;
  • 生成配方、输入模式、参考资源、动作描述、背景色、比例、清晰度、帧数和时长的持久化恢复。

AI 生成链路继续使用现有 Seedance、FFmpeg 抽帧和逐帧抠图能力,最终发布为正式的 character-animation / image-sequence 资源。

2. 视频直接转换

新增视频直接转换链路:

  • API:/api/editor/character-animations/video-conversions
  • 使用 durable queue 执行;
  • 支持 owner-scoped MP4 / MOV 源视频;
  • 源视频限制为 50MB、2–15 秒;
  • 按源视频 FPS 计算目标帧数,最终限制为 2–66 帧;
  • 保留源视频背景;
  • 不调用 Seedance;
  • 不调用 BgFilter 或其它去背景模型;
  • 不重复保存源视频;
  • 正式资源保存准确的序列帧时长和帧信息。

3. 序列帧去背景

序列帧去背景改为独立的 durable 派生任务:

  • 请求进入现有 external_generation_job 队列;
  • 同一任务内并行处理所有帧;
  • 使用本地纯算法扣除 #00FF00 绿幕;
  • 不调用 LLM、Seedance、BgFilter 或阿里云抠图模型;
  • 全部帧成功后才一次性发布新的透明序列帧资源;
  • 源序列帧保持不变;
  • 任一帧失败都会清理已上传的临时对象并整批失败;
  • 去背景结果使用新的 character-animation.remove-background action。

当前 v1 只允许以下源序列帧执行去背景:

  • V2 生成配方;
  • action 为 character-animation.generate
  • backgroundColor=green

以下情况由后端拒绝,前端也不展示去背景入口:

  • 白、蓝、紫背景;
  • 视频直接转换结果;
  • 已去背景结果;
  • 缺失或非法生成配方。

4. 序列帧拆帧

新增序列帧拆帧能力:

  • API:/api/editor/character-animations/frame-splits
  • 复用原有帧的 assetObjectId / objectKey
  • 不重新上传 PNG;
  • 使用现有批量持久化事务登记独立项目资源和素材;
  • 对 pending、local resource、generation dialog 临时资源进行前后端双重拦截;
  • 按 owner、源资源、目标目录和标签稳定隔离拆帧 operation;
  • 防止不同项目或不同目标发生错误的 cohort 合并。

5. 资产来源与安全校验

在序列帧去背景前,对每一帧执行正式资产对象校验:

  • assetObjectId 必须存在;
  • asset_object 必须存在;
  • 资产对象必须属于当前用户;
  • objectKey 必须与帧中声明的路径完全一致;
  • source_job_id 必须与源序列资源的 task_id 一致;
  • content_type 必须是 image/*
  • 帧尺寸必须有效。

所有帧验证完成后才会开始下载、抠图、上传和发布,避免通过伪造 imageSequenceFrames 读取其他用户的 OSS 对象。

6. 前端编辑器能力

补齐以下前端能力:

  • Spine 序列帧生成入口和底部工具栏;
  • 视频直接转换模式;
  • 序列帧播放器和帧信息展示;
  • 去背景、拆帧、下载和改造入口;
  • 生成结果、队列状态和刷新恢复;
  • 序列帧结果不提供快速编辑;
  • character-animation.remove-background 加入生成 action 白名单;
  • 去背景 action 保持不可 remix;
  • 修复底部工具栏宽度和视觉容器样式,避免桌面端出现横向滚动条。

7. 后端与共享契约

  • 新增角色动画相关 shared contracts;
  • 增加编辑器角色动画请求、响应和序列帧 payload;
  • 增加 SpacetimeDB 项目资源、帧对象和资产登记编排;
  • 增加 durable queue worker 处理;
  • 增加 operation-scoped OSS 对象路径;
  • 同一 operation 重放复用路径;
  • 不同 operation 即使请求 fingerprint 相同,也不会复用旧对象位置;
  • 生成结果保存正式帧列表、资源 lineage 和序列帧时长;
  • 预览视频不作为最终交付物。

关键产品约束

  • Spine 序列帧与视频保持一致,不支持快速编辑;
  • 视频直接转换保留背景;
  • 去背景 v1 只扣纯绿幕;
  • 去背景生成新的序列帧动画,不原位覆盖源资源;
  • 拆帧不重新上传已有 PNG;
  • 生成结果必须经过队列和持久化恢复链路;
  • 前端 generation inputs 不是业务权威来源,后端会重建和校验关键执行字段;
  • 资源对象、owner、项目、任务和 objectKey 必须保持一致。

验证

已通过:

  • Rust character_animation 定向测试:90 passed;
  • 前端序列帧生成模型和工具栏测试:63 passed;
  • npm run typecheck
  • npm run lint:eslint
  • npm run check:encoding
  • npm run check:rustfmt
  • npm run check:spacetime-schema
  • git diff --check

Review 状态

已完成 pre-PR review:

  • 逐帧 OSS 资产归属和来源验证;
  • 去背景 action 白名单;
  • 非绿幕序列帧入口和后端门禁;
  • 队列失败清理;
  • operation-scoped 对象存储幂等;
  • 结果项目快照应用和刷新恢复。

Review 结果:No findings。

风险与后续关注

  • 当前去背景算法只支持纯绿幕,复杂背景不在本 PR 范围内;
  • AI 生成和真实 OSS / 队列生产联调仍需要在具备对应 Provider 和 OSS 配置的环境中验证;
  • 需要在 PR 环境确认远端 worker、队列恢复和真实序列帧导出链路;
  • 需要在浏览器中补充一次底部工具栏、序列帧播放器和去背景入口的手工回归。
## 背景 为编辑器补齐 Spine 序列帧动画的完整创作链路: - 从文本、角色图片或参考视频生成角色动作序列帧; - 将已有视频直接转换为序列帧; - 支持序列帧拆帧、算法去背景和 Spine JSON 导出; - 保证异步生成、刷新恢复、对象存储幂等和资源来源校验; - 保持 Spine 序列帧与视频一致,不提供快速编辑入口。 ## 主要变更 ### 1. Spine 序列帧多模态生成 新增统一的 Spine 序列帧生成面板,支持: - 文本生成角色动作; - 角色图片生成动作; - 参考视频生成动作; - 动作视频与角色外观图组合; - AI 生成 / 改造与视频直接转换两个模式; - 生成配方、输入模式、参考资源、动作描述、背景色、比例、清晰度、帧数和时长的持久化恢复。 AI 生成链路继续使用现有 Seedance、FFmpeg 抽帧和逐帧抠图能力,最终发布为正式的 `character-animation` / `image-sequence` 资源。 ### 2. 视频直接转换 新增视频直接转换链路: - API:`/api/editor/character-animations/video-conversions` - 使用 durable queue 执行; - 支持 owner-scoped MP4 / MOV 源视频; - 源视频限制为 50MB、2–15 秒; - 按源视频 FPS 计算目标帧数,最终限制为 2–66 帧; - 保留源视频背景; - 不调用 Seedance; - 不调用 BgFilter 或其它去背景模型; - 不重复保存源视频; - 正式资源保存准确的序列帧时长和帧信息。 ### 3. 序列帧去背景 序列帧去背景改为独立的 durable 派生任务: - 请求进入现有 `external_generation_job` 队列; - 同一任务内并行处理所有帧; - 使用本地纯算法扣除 `#00FF00` 绿幕; - 不调用 LLM、Seedance、BgFilter 或阿里云抠图模型; - 全部帧成功后才一次性发布新的透明序列帧资源; - 源序列帧保持不变; - 任一帧失败都会清理已上传的临时对象并整批失败; - 去背景结果使用新的 `character-animation.remove-background` action。 当前 v1 只允许以下源序列帧执行去背景: - V2 生成配方; - action 为 `character-animation.generate`; - `backgroundColor=green`。 以下情况由后端拒绝,前端也不展示去背景入口: - 白、蓝、紫背景; - 视频直接转换结果; - 已去背景结果; - 缺失或非法生成配方。 ### 4. 序列帧拆帧 新增序列帧拆帧能力: - API:`/api/editor/character-animations/frame-splits` - 复用原有帧的 `assetObjectId` / `objectKey`; - 不重新上传 PNG; - 使用现有批量持久化事务登记独立项目资源和素材; - 对 pending、local resource、generation dialog 临时资源进行前后端双重拦截; - 按 owner、源资源、目标目录和标签稳定隔离拆帧 operation; - 防止不同项目或不同目标发生错误的 cohort 合并。 ### 5. 资产来源与安全校验 在序列帧去背景前,对每一帧执行正式资产对象校验: - `assetObjectId` 必须存在; - `asset_object` 必须存在; - 资产对象必须属于当前用户; - `objectKey` 必须与帧中声明的路径完全一致; - `source_job_id` 必须与源序列资源的 `task_id` 一致; - `content_type` 必须是 `image/*`; - 帧尺寸必须有效。 所有帧验证完成后才会开始下载、抠图、上传和发布,避免通过伪造 `imageSequenceFrames` 读取其他用户的 OSS 对象。 ### 6. 前端编辑器能力 补齐以下前端能力: - Spine 序列帧生成入口和底部工具栏; - 视频直接转换模式; - 序列帧播放器和帧信息展示; - 去背景、拆帧、下载和改造入口; - 生成结果、队列状态和刷新恢复; - 序列帧结果不提供快速编辑; - `character-animation.remove-background` 加入生成 action 白名单; - 去背景 action 保持不可 remix; - 修复底部工具栏宽度和视觉容器样式,避免桌面端出现横向滚动条。 ### 7. 后端与共享契约 - 新增角色动画相关 shared contracts; - 增加编辑器角色动画请求、响应和序列帧 payload; - 增加 SpacetimeDB 项目资源、帧对象和资产登记编排; - 增加 durable queue worker 处理; - 增加 operation-scoped OSS 对象路径; - 同一 operation 重放复用路径; - 不同 operation 即使请求 fingerprint 相同,也不会复用旧对象位置; - 生成结果保存正式帧列表、资源 lineage 和序列帧时长; - 预览视频不作为最终交付物。 ## 关键产品约束 - Spine 序列帧与视频保持一致,不支持快速编辑; - 视频直接转换保留背景; - 去背景 v1 只扣纯绿幕; - 去背景生成新的序列帧动画,不原位覆盖源资源; - 拆帧不重新上传已有 PNG; - 生成结果必须经过队列和持久化恢复链路; - 前端 generation inputs 不是业务权威来源,后端会重建和校验关键执行字段; - 资源对象、owner、项目、任务和 objectKey 必须保持一致。 ## 验证 已通过: - Rust `character_animation` 定向测试:90 passed; - 前端序列帧生成模型和工具栏测试:63 passed; - `npm run typecheck`; - `npm run lint:eslint`; - `npm run check:encoding`; - `npm run check:rustfmt`; - `npm run check:spacetime-schema`; - `git diff --check`。 ## Review 状态 已完成 pre-PR review: - 逐帧 OSS 资产归属和来源验证; - 去背景 action 白名单; - 非绿幕序列帧入口和后端门禁; - 队列失败清理; - operation-scoped 对象存储幂等; - 结果项目快照应用和刷新恢复。 Review 结果:No findings。 ## 风险与后续关注 - 当前去背景算法只支持纯绿幕,复杂背景不在本 PR 范围内; - AI 生成和真实 OSS / 队列生产联调仍需要在具备对应 Provider 和 OSS 配置的环境中验证; - 需要在 PR 环境确认远端 worker、队列恢复和真实序列帧导出链路; - 需要在浏览器中补充一次底部工具栏、序列帧播放器和去背景入口的手工回归。
suzmii added 9 commits 2026-08-15 14:58:06 +08:00
合并master当前工程、后端、前端和文档更新

按已确认方案解决Spine序列帧多模态、帧数和快速编辑冲突

保留当前分支底部工具栏宽度与隐藏滚动条样式
序列帧去背景改用本地绿幕算法并在 durable 父任务内并行处理。

将去背景操作加入生成结果白名单,并按 operation_id 隔离帧对象路径。

去背景结果发布为新的序列资源、素材和画布图层,同时保留原始序列。

同步前端生成占位、相关测试及队列与资源契约文档。
视频直接转换和序列帧去背景按 operation 隔离对象存储路径
队列后处理失败统一返回脱敏用户文案
inline 转换和去背景结果直接应用服务端项目快照
修复去背景加载状态和相关前端回归测试
收紧序列帧去背景来源与绿幕门禁
Project CI / Repository checks (pull_request) Failing after 13s
Project CI / Backend tests (pull_request) Failing after 13s
Project CI / Frontend tests (pull_request) Successful in 2m38s
Project CI / Native shell tests (pull_request) Failing after 11m22s
101fd952d5
验证去背景每帧正式资产对象的用户归属、对象路径和来源任务
仅允许编辑器生成的纯绿幕角色动画执行算法去背景
补齐去背景生成 action 白名单但保持不可改造
更新工具栏门禁、回归测试和Spine序列帧技术方案
suzmii added 1 commit 2026-08-15 15:00:55 +08:00
Merge branch 'master' into feat/spine-sequence-export-v2
Project CI / Repository checks (pull_request) Successful in 1m19s
Project CI / Backend tests (pull_request) Failing after 3m12s
Project CI / Frontend tests (pull_request) Successful in 3m14s
Project CI / Native shell tests (pull_request) Successful in 14m53s
c94bb6d3ed
suzmii marked the pull request as work in progress 2026-08-15 15:01:23 +08:00
suzmii added 1 commit 2026-08-15 15:08:56 +08:00
Revert "local: stash the document"
Project CI / Frontend tests (pull_request) Successful in 3m12s
Project CI / Native shell tests (pull_request) Successful in 14m9s
Project CI / Backend tests (pull_request) Failing after 2m29s
Project CI / Repository checks (pull_request) Successful in 1m0s
b5dc99e067
This reverts commit 0123f3db76.
suzmii added 3 commits 2026-08-15 17:38:22 +08:00
后端仅接受 character-animation.convert 结果执行序列帧去背景

前端工具栏与工作流同步收紧视频转换门禁

更新相关测试与Spine序列帧技术方案
将character_animation_assets的持久计费边界预期从3调整为4

覆盖AI生成、视频转换、去背景与视频生成四条内联路由
收紧序列帧预览恢复校验
Project CI / Backend tests (pull_request) Failing after 9s
Project CI / Repository checks (pull_request) Failing after 13s
Project CI / Frontend tests (pull_request) Successful in 2m56s
Project CI / Native shell tests (pull_request) Failing after 12m17s
4d1c9d9b1b
taskId 缺失时不恢复关联预览视频

补充序列帧与预览任务标识缺失的恢复测试
suzmii added 1 commit 2026-08-15 17:48:47 +08:00
合并 master 的预览部署控制面
Project CI / Repository checks (pull_request) Successful in 55s
Project CI / Frontend tests (pull_request) Successful in 2m56s
Project CI / Backend tests (pull_request) Successful in 3m35s
Project CI / Native shell tests (pull_request) Successful in 17m44s
c51d88fd19
保留 Spine 序列帧与 Jenkins 容器预览决策记录

合入 preview-deployer-web、preview-deployer-server 及部署脚本
suzmii marked the pull request as ready for review 2026-08-15 18:09:05 +08:00
suzmii added 1 commit 2026-08-15 18:09:17 +08:00
Merge branch 'master' into feat/spine-sequence-export-v2
Project CI / Frontend tests (pull_request) Successful in 3m33s
Project CI / Repository checks (pull_request) Successful in 1m17s
Project CI / Backend tests (pull_request) Successful in 4m11s
Project CI / Native shell tests (pull_request) Successful in 17m58s
95e34b8760
kdletters requested review from wuxiangwanzi 2026-08-15 18:10:10 +08:00
suzmii requested review from kdletters 2026-08-15 18:10:11 +08:00
suzmii removed review request for wuxiangwanzi 2026-08-15 18:10:14 +08:00
kdletters requested review from wuxiangwanzi 2026-08-15 18:10:25 +08:00
suzmii added 1 commit 2026-08-17 11:37:46 +08:00
Merge branch 'master' into feat/spine-sequence-export-v2
Project CI / Repository checks (pull_request) Successful in 1m7s
Project CI / Frontend tests (pull_request) Successful in 3m4s
Project CI / Backend tests (pull_request) Successful in 4m24s
Project CI / Native shell tests (pull_request) Successful in 13m56s
8b4ec2c4d4
kdletters requested changes 2026-08-17 14:20:47 +08:00
kdletters left a comment
Member

本次当前 head 仍有两个 P1,均会在正常允许的输入下产生错误结果或耗尽 worker 资源,需修复后再合并:

  1. 视频直接转换的去背景资格没有证明输入是绿幕,却固定按 #00FF00 键色处理任意转换结果;普通背景视频可能被错误发布为已去背景序列。
  2. 视频模式的角色外观参考图在 Provider 调用前没有数量、字节或解码像素门禁;第 10 张及大尺寸/压缩炸弹图片可在长任务中持续下载解码。

请在前后端和 durable worker 一致收口资格与容量门禁,并补普通背景拒绝、绿幕允许、9/10 张边界、单图大小与像素上限的回归。

本次当前 head 仍有两个 P1,均会在正常允许的输入下产生错误结果或耗尽 worker 资源,需修复后再合并: 1. 视频直接转换的去背景资格没有证明输入是绿幕,却固定按 #00FF00 键色处理任意转换结果;普通背景视频可能被错误发布为已去背景序列。 2. 视频模式的角色外观参考图在 Provider 调用前没有数量、字节或解码像素门禁;第 10 张及大尺寸/压缩炸弹图片可在长任务中持续下载解码。 请在前后端和 durable worker 一致收口资格与容量门禁,并补普通背景拒绝、绿幕允许、9/10 张边界、单图大小与像素上限的回归。
@@ -643,0 +1124,4 @@
Ok(())
}
fn editor_character_animation_sequence_is_video_conversion(
Member

[P1] 这里仅把 version=2 且 action=character-animation.convert 当作可去背景资格,但直接转换允许任意 MP4/MOV,配方也没有可验证的绿幕/键色字段。后续算法固定删除 #00FF00;因此普通实拍或非绿幕视频也会进入任务并发布背景未去除、或误删绿色主体的正式序列资源。请把可信绿幕/键色元数据写入并由后端复验,再与前端入口共同要求该条件;否则普通视频应拒绝或改走通用分割。补非绿幕拒绝、绿幕允许和绿色主体保护回归。

[P1] 这里仅把 version=2 且 action=character-animation.convert 当作可去背景资格,但直接转换允许任意 MP4/MOV,配方也没有可验证的绿幕/键色字段。后续算法固定删除 #00FF00;因此普通实拍或非绿幕视频也会进入任务并发布背景未去除、或误删绿色主体的正式序列资源。请把可信绿幕/键色元数据写入并由后端复验,再与前端入口共同要求该条件;否则普通视频应拒绝或改走通用分割。补非绿幕拒绝、绿幕允许和绿色主体保护回归。
@@ -793,0 +1823,4 @@
editor_character_animation_bad_request("角色外观图仅支持视频模式。"),
));
}
for appearance_src in &payload.appearance_reference_srcs {
Member

[P1] appearanceReferenceSrcs 在此逐项解析、下载并完整解码,却没有先限制数量或资源预算;后面的通用视频引用规范化才有“最多 9 张”门禁,但本路径会直接把全部 appearance_object_keys 传给 Provider。正常操作中连续添加第 10 张即可让长任务先下载解码超额输入;大尺寸或压缩炸弹图片也会在无像素上限的 DynamicImage::from_decoder 前占用 worker 内存。请在入队与 worker 执行前统一规范化为最多 9 张,并为单图/总字节和解码边长/像素设硬上限;前端追加和恢复同样拒绝超额。补 9/10 张、超 30MB 与超像素边界测试。

[P1] appearanceReferenceSrcs 在此逐项解析、下载并完整解码,却没有先限制数量或资源预算;后面的通用视频引用规范化才有“最多 9 张”门禁,但本路径会直接把全部 appearance_object_keys 传给 Provider。正常操作中连续添加第 10 张即可让长任务先下载解码超额输入;大尺寸或压缩炸弹图片也会在无像素上限的 DynamicImage::from_decoder 前占用 worker 内存。请在入队与 worker 执行前统一规范化为最多 9 张,并为单图/总字节和解码边长/像素设硬上限;前端追加和恢复同样拒绝超额。补 9/10 张、超 30MB 与超像素边界测试。
suzmii marked the pull request as work in progress 2026-08-17 14:47:06 +08:00
suzmii added 4 commits 2026-08-17 20:22:54 +08:00
限制视频模式角色外观图最多九张,并在前端追加、恢复和提交链路统一收口。

在入队归一化和 durable worker 执行前限制单图、累计字节、解码边长与总像素。

补充九/十张、三十兆字节、累计大小和压缩炸弹像素边界回归。

同步更新 Spine 技术方案与团队决策记录。
去背景弹窗要求用户显式选择纯色键控或通用智能分割。

纯色模式支持颜色输入和吸管取色,并以本地算法处理任意键色。

通用模式逐帧使用 BgFilter complex 分割,禁止携带键色。

入队与 durable worker 统一校验模式参数并持久化权威处理元数据。

补充双色键控、模式冲突、双路径路由和前端交互回归。

同步更新 Spine 技术方案与团队决策记录。
将序列帧去背景选择框改为贴近画布的非模态悬浮窗

增加原始帧取色、实时色样与自适应方向的像素放大预览

区分提交接受状态与 durable 任务处理状态,入队成功后立即关闭悬浮窗

支持纯色键控轻微色差并补充通用模式与后端回归验证

同步更新Spine技术方案与项目决策记录
同步远端分支并保留序列帧去背景修复
Project CI / Backend tests (pull_request) Failing after 14s
Project CI / Repository checks (pull_request) Failing after 14s
Project CI / Frontend tests (pull_request) Successful in 2m39s
Project CI / Native shell tests (pull_request) Successful in 13m41s
2f1da79f9c
suzmii added 1 commit 2026-08-17 20:48:36 +08:00
合并master并保留双方决策记录
Project CI / Frontend tests (pull_request) Successful in 3m4s
Project CI / Backend tests (pull_request) Successful in 3m58s
Project CI / Native shell tests (pull_request) Successful in 14m2s
Project CI / Repository checks (pull_request) Failing after 34s
4ca93a6f16
保留Spine序列帧去背景双模式与悬浮窗决策

保留预览发布记录使用Jenkins构建编号与有限保留决策

同步master预览部署控制面代码与文档变更
suzmii added 1 commit 2026-08-17 21:12:16 +08:00
修复序列帧去背景面板导入顺序
Project CI / Repository checks (pull_request) Successful in 1m7s
Project CI / Frontend tests (pull_request) Successful in 3m4s
Project CI / Backend tests (pull_request) Successful in 4m14s
Project CI / Native shell tests (pull_request) Successful in 14m27s
e695cdf499
按 simple-import-sort 规则调整类型导入顺序
suzmii marked the pull request as ready for review 2026-08-17 21:32:15 +08:00
suzmii requested review from kdletters 2026-08-17 21:32:29 +08:00
suzmii marked the pull request as work in progress 2026-08-22 11:04:21 +08:00
suzmii closed this pull request 2026-08-22 11:04:37 +08:00
Some checks are pending
Project CI / Repository checks (pull_request) Successful in 1m7s
Project CI / Frontend tests (pull_request) Successful in 3m4s
Project CI / Backend tests (pull_request) Successful in 4m14s
Project CI / Native shell tests (pull_request) Successful in 14m27s

Pull request closed

Sign in to join this conversation.