Skip to content

fix(flow): 修复新版 Flow 图片引用 RPC 参数结构 - #182

Merged
TheSmallHanCat merged 1 commit into
TheSmallHanCat:mainfrom
john-walks-slow:fix/image-to-image-rpc-arguments
Sep 30, 2026
Merged

TheSmallHanCat merged 1 commit into
TheSmallHanCat:mainfrom
john-walks-slow:fix/image-to-image-rpc-arguments

Conversation

@john-walks-slow

Copy link
Copy Markdown
Contributor

问题

图生图(传 image_url 垫图)在新版 Flow 接口下 100% 失败:

上传 1 张参考图片...
错误: 生成失败: Flow frontend RPC rejected: rpc=maseQ, code=[3]

纯文生图正常,所以问题出在垫图链路。README 里图生图的 payload 格式没问题。

这与 96f30e3(修复新版 Flow 视频引用 RPC 参数结构)是同一类问题——上游改了参数结构,图片这条漏了。

排查过程中排除的假设

假设 验证 结论
reCAPTCHA action 名不对 action="UPLOAD_IMAGE" → "IMAGE_GENERATION",重启重试 仍报 code=[3],非主因
垫图触发内容策略 换成纯几何绘制的红苹果 仍报 code=[3],与内容无关
图片体积/尺寸 71KB 降采样 vs 1024×1024 原图 两种都失败
账号权限/额度 账号有额度、cookies 有效、文生图正常 正常

根因

用 Playwright 驱动真实 Flow UI 走一遍上传 + 生成,拦截 batchexecute 的 f.req,逐槽比对。

① maseQ(上传)实际是 12 槽

原实现发 14 槽,且第 4 槽传的是布尔值,真实值是整数 1。proto 字段要整型,喂 boolean 直接类型不匹配,这就是 INVALID_ARGUMENT code=[3] 的直接来源。

槽 前端真实值 原实现
0–2 context / base64 / mime 一致
3 整数 1 布尔 True ← 类型不匹配
4–6 null 一致
7 null False
8 filename 一致
9 null 宽高比数字
10–11 客户端 UUID null
12–13 不存在 null, null

② ogiZ0b(生成)参考图分支

上传修好后暴露出第二个错误,纯文生图时该 RPC 正常,说明是参考图分支写错了:

位置 前端真实值 原实现
request[2] [["<mediaId>", null, null, null, 1]] [[1, "<mediaId>"]]
request[9] null generation_settings JSON 串

参考图条目是 5 元素信封(mediaId 打头、末位是整数 1)。request[9] 往结构体字段塞字符串,是这一处的直接死因。

验证

  • 垫图改写(红苹果加绿叶):通过,76.8s / 213KB
  • 垫图换装(保留角色身份换服装):通过,91.6s / 340KB,发色/瞳色/发饰三项与原图一致
  • 文生图回归:未被改坏,57.7s / 736KB
  • 本地 unittest discover 54 项全绿

补充观察(未包含在本次改动里)

真实前端 ogiZ0b 的 request 是 14 槽,当前实现是 15 槽(多一个 null)。文生图带着这个多余槽一直正常,上游应当是容忍的,所以没有一并改动。如果希望严格对齐,可以再去掉一个 null——但那属于未验证的改动,建议单独处理。

说明

抓包过程中用到的 flow.db 里的 cookie、recaptcha token、project id 均未包含在本 PR 中。测试用固定的假 UUID 与 mock token。

图生图(image_url 垫图)在新版 Flow 接口下 100% 失败,报
Flow frontend RPC rejected: rpc=maseQ, code=[3] (INVALID_ARGUMENT),
纯文生图不受影响。与 96f30e3 修复的视频引用 RPC 是同一类问题:
上游改了参数结构,图片这条漏了。

maseQ(上传)实际是 12 槽,且第 4 槽传的是整数 1 而不是布尔值。
proto 字段要整型,喂 boolean 直接类型不匹配,这就是 code=[3] 的直接
来源。同时第 8、10 槽应为 null(原实现传了 False 和宽高比数字),
第 11、12 槽需带上客户端 UUID。

ogiZ0b(生成)在带参考图时同样被拒:
- 参考图条目应为 5 元素信封 [mediaId, null, null, null, 1],
  而不是 [1, mediaId]
- 第 10 槽必须保持 null。原实现在有参考图时往该槽塞了一段
  generation_settings JSON 串,往结构体字段喂字符串是这里的直接死因。

抓取方式:用 Playwright 驱动真实 Flow UI 走一遍上传加生成,
拦截 batchexecute 的 f.req 后逐槽比对。

验证:垫图改写通过(76.8s / 213KB),垫图换装保持角色身份一致,
文生图回归正常。
@TheSmallHanCat
TheSmallHanCat merged commit 4429700 into TheSmallHanCat:main Sep 30, 2026
TheSmallHanCat pushed a commit that referenced this pull request Sep 30, 2026
视频生成成功但取媒体地址失败:

```
HTTP 502
{"error":{"code":502,"message":"视频生成成功但获取媒体地址失败:
 Flow frontend RPC rejected: rpc=as29s, code=[5]","status":"UNAVAILABLE"}}
```

生成本身成功,挂在 as29s 这一步。

与 #182 那两处不同:这次参数结构没有错。as29s 的 argument 仍是
单元素 UUID 列表,bl / f.sid / source-path 也都与前端一致。错的是值——
as29s 按「生成操作 id」索引,而 _resolve_video_asset 的取值优先级把
mediaName 排在了第一位。

一个 operation 里同时存在两个不同 UUID:

- mediaGenerationId / operation.name —— as29s 要的是这个
- mediaName —— 传它就 NOT_FOUND

2x2 组合实测(同一 media,仅换 id 与 source-path):

| 传入 id | source-path | 结果 |
|---|---|---|
| mediaName | /project/{id} | code=[5] |
| mediaName | /project/{id}/edit/{media} | code=[5] |
| operation.name | /project/{id} | 返回 fifeUrl |
| operation.name | /project/{id}/edit/{media} | 返回 fifeUrl |

可见 source-path 两种都通,唯一的变量就是 id。

附带收益:video_media_id 的兜底值也一并修正。返回的 URL 形如
/video/<operation.name>,故 extend:// 续写引用的正是该 id,
此前兜底会给出一个取不到媒体的 mediaName。

定位手法(可复用,无需重跑生成):把 operation dump 出来,拿到全部候选
UUID,再直接对 as29s 打点组合。比重跑一次视频生成快一个量级。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants