Skip to content

[bug] 画布:首尾帧模式连接第二张图片未分配尾帧,图片未传入模型 #83

Closed

Description

@wuzhf9

问题与影响

视频节点使用 MiniMax 官方 V2 的“首尾帧”模式时,依次连接两张图片,画布上两条参考连线均存在,但生成面板只显示首帧,尾帧仍为空。第二张图片未被分配为尾帧,提交时会作为 context_only 被过滤,不发送图片内容给模型,容易让用户误以为两张图片都参与了生成。

复现步骤

  1. 配置 minimax_video_v2 协议的 MiniMax-H3 模型;其能力契约声明支持 first_frame 和 last_frame。
  2. 在画布添加两张不同且可用的图片 A、B,以及一个空白视频节点。
  3. 为视频节点选择该模型,切换至“首尾帧”模式。
  4. 依次从 A、B 向视频节点连接参考线,不手动操作首尾帧选择器。
  5. 查看生成面板。填写非空提示词后,可在隔离环境用模拟模型服务检查输入快照和请求,无需调用付费服务。

预期与实际

  • 预期:支持双帧的模型按连接顺序填入空闲首帧、尾帧,面板与工程保存的引用角色一致;提交时两张图片分别以对应角色发送。
  • 实际:两条连线均建立,但 A 为 first_frame,B 保持 reference;尾帧槽位为空。首尾帧输入策略将 B 标记为 context_only,生成请求只携带 A 的图片内容。
  • 临时绕过:手动在尾帧槽位选择 B。显式指定为 last_frame 后,输入解析会将两张图片均标记为 content。

定位与证据

检查基线:5581f19f4375950e3286678366ac0b13ad2b9cc1。本次使用 Node.js v24.14.0 运行隔离的画布命令复现,并调用现有 Python 输入策略核对发送范围;未修改用户工程、未调用远端模型。界面现象来自用户操作截图,本轮没有新增浏览器端端到端复现。

已核实的链路:

  1. 官方 MiniMax 能力规则 明确声明 frameRoles=['first_frame', 'last_frame']。
  2. 自动分配函数 却执行 if (settings.modelConfigId && field === "lastFrameNodeId") continue,将所有已配置服务模型都按仅支持首帧处理,没有读取实际帧能力。
  3. 引用保存映射 根据选中的槽位写入 first_frame / last_frame,未选入槽位的图片保持 reference。
  4. 后端输入策略 将首尾帧模式中的普通图片参考标记为 context_only;任务构造 排除这些图片,不交给模型适配器。

从仓库根目录执行以下命令,可独立复现两条连线存在但尾帧未分配的状态:

node --experimental-strip-types --input-type=module <<'JS'
import { applyCommand, createDocument, createNode } from './src/canvas/model.ts';
import { generationDefaults } from './src/canvas/generationCatalog.ts';
const image = () => createNode('image', undefined, {
  src: 'data:image/png;base64,fixture', assetState: 'ready',
});
const a = image(), b = image();
const target = createNode('video', undefined, { settings: {
  ...generationDefaults('video'), videoMode: 'first-last',
  modelConfigId: 'configured-minimax',
}});
let doc = { ...createDocument(), nodes: [a, b, target] };
for (const source of [a, b]) doc = applyCommand(doc, {
  type: 'add-edge', edge: {
    id: crypto.randomUUID(), source: source.id, target: target.id,
  },
});
const s = doc.nodes.find(n => n.id === target.id).data.settings;
console.log({ edges: doc.edges.length,
  firstIsA: s.firstFrameNodeId === a.id,
  last: s.lastFrameNodeId ?? null });
JS

实际输出为 { edges: 2, firstIsA: true, last: null }。此脚本仅复现前端命令层,fixture 不代表真实媒体上传。

另以隔离的两个图片参考调用 reference_policy,使用官方模型的实际 inputRules,得到:

A.png  first_frame  content
B.png  reference    context_only

仅在内存中将 B 改为 last_frame 后,两张图片均为 content。对用户现有项目的只读解析也得到相同的过滤结果;该节点当时未提交新任务,因此上述发送范围是输入策略验证结果,不是一次新的远端请求抓包。

测试缺口:现有 tests/frameReferences.test.ts 可通过,但单帧适配测试 只用是否有 modelConfigId 区分能力,固化了该假设;MiniMax 浏览器测试 直接创建正确的首尾帧角色,绕过拖线后的自动分配。

验收标准

  • 对契约支持首尾帧的模型,依次连接两张图片后,首帧与尾帧显示、保存角色和重新打开后的状态一致;覆盖逐张及批量连接、从参考模式切换至首尾帧。
  • 通过模拟服务检查两张不同的真实图片:接受任务的输入快照与实际请求均保留正确角色及图片内容;不能仅验证缩略图或连线存在。
  • 仅支持首帧的模型不会自动获得尾帧;模型不可用或能力未加载时有明确反馈。
  • 手动选择、互换、清空、断线和撤销行为正确;刷新或后台同步不自动恢复用户明确清空的槽位。
  • 已连接但未参与生成的图片有可见说明;已有工程不在加载时被静默改写,既有任务执行快照保持不变。
  • UI 与 Agent 对同样的显式首尾帧输入遵守相同的后端校验和发送规则;新增真实拖线流程回归测试。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:canvasCanvas, nodes and direct manipulationarea:providerModel providers and generation protocolstype:bugSomething is broken

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions