Codex CLI 图像生成 — Stage1 换装图的产图通道
跟 H3-CONSOLE.md 同一角色:一份外部生成服务的接入契约。H3 Console 只
产 mp4 不产图(H3-CONSOLE.md),Stage1 的"人物 + 衣服 → 换装图"要另找
通道,这里记录本机 Codex CLI 这条路的实测结果和接入方式。
核对时间:2026-09-01,codex-cli 0.152.0(/opt/homebrew/bin/codex),
已登录 ChatGPT 账号。标注"实测"的都是在这台机器上真跑过的;标注"未实测"
的是读文档得来的,别当既成事实。
1. 先澄清三个名词
| 说法 | 实际情况 |
|---|---|
| "codex acp 接口" | 本机没有 codex acp 子命令(实测:codex acp --help 直接落回交互式 CLI 的帮助)。ACP(Agent Client Protocol)是 Zed 那边的编辑器↔Agent 协议,Codex 侧由第三方适配器 codex-acp 提供,不是官方 CLI 的一部分。而且 ACP 是给"交互式会话"用的,我们要的是批量出图,用不上它 |
| "image2 文生图模型" | 是 gpt-image-2,OpenAI 2026-04-21 发布,已是 Codex CLI 的默认图像模型(取代 gpt-image-1.5)。它不只文生图,也支持图片编辑(多张输入图),这对我们更重要 |
| "codex 的接口" | 官方对外接口是 codex app-server(stdio / unix socket / ws)、codex mcp-server(stdio MCP)、codex exec(一次性非交互)。批量出图用 codex exec 最省事,理由见第 4 节 |
⚠️ 协议层不等于能力层:app-server / mcp-server 只是通信代理,它们暴露
的是"Codex Agent 的能力",不是一个固定的 generate_image(prompt) 方法。
能不能出图,取决于那个 Codex 运行环境装没装、启用没启用图像工具。
2. 本机能力核对(实测)
$ codex features list | grep -i image
image_generation stable true ← 已启用
view_image stable true ← 读本地图进上下文,编辑流程要用
内置技能在 ~/.codex/skills/.system/imagegen/(SKILL.md + references/
scripts/image_gen.py)。
一次真实出图(实测通过):
codex exec --skip-git-repo-check -s workspace-write -o last.txt \
"Generate an image: a plain red rubber ball on a white studio floor. Then print the absolute path of the generated image file."
- 产物:
~/.codex/generated_images/<thread-uuid>/exec-<uuid>.png - 实际尺寸 1254×1254,1.2 MB。当时我在 prompt 里只顺口写了"square
1024x1024",没给到。但后续换装实测里把
Size 1024x1536作为独立一行 明确写进 prompt,三张图全部精确命中 —— 所以尺寸不是控不住,是要在 prompt 里明确要求 -o last.txt里拿到了绝对路径,这是脚本取回文件的可靠方式- 消耗 29,914 tokens(走 ChatGPT 订阅额度,不是 API 计费)
换装编辑(S3 spike,2026-09-01 实测通过):合成一组测试素材(1 张人物 全身图 + 2 张衣服平铺图),跑两次多图编辑换装,两次都成功:
| 项 | 结果 |
|---|---|
| 人脸/发型/体型 | 完全保持,看不出改动 |
| 姿势/机位/背景/光线 | 完全保持 |
| 服装还原度 | 高——旗袍的红缎、金边、盘扣、侧开衩,校服的水手领白条、红领巾、百褶裙,都准确转移 |
| 尺寸 | 两次都精确给到要求的 1024×1536 |
| 耗时 | 约 73 秒/张 |
| 消耗 | 23,253 / 23,268 tokens/张 |
| 一次 exec 生成 3 张图 | 38,894 tokens —— 批量塞进一次 exec 比一张一次省得多 |
素材和产物在 spike 目录,结论:路径 A 的换装质量达标。
3. 两种模式(SKILL.md 原文,非推测)
技能明确只有两个顶层模式:
3.1 内置 image_gen 工具(默认)
- 不需要
OPENAI_API_KEY,走已登录的 ChatGPT 账号额度 - 支持生成 + 编辑 + 透明背景
- 编辑语义:只能编辑"已经在对话上下文里可见"的图(附件或本轮先前生成
的图)。要编辑本地文件,先用内置
view_image工具把它读进上下文, 再走编辑流程。SKILL.md原话:不要承诺内置工具能按任意文件路径编辑 - 落盘位置固定在
$CODEX_HOME/generated_images/...,内置工具没有 目标路径参数;要放到别处只能"先生成、再 move/copy"
3.2 CLI 回退模式 scripts/image_gen.py
- 需要
OPENAI_API_KEY(= 按张计费,跟订阅额度是两条账) - 三个子命令:
generate/edit/generate-batch - 有内置模式没有的东西:确定的输出路径、
--quality、--mask、--size精确控制、--concurrency并发、--dry-run SKILL.md明确:不要为了普通的质量/尺寸/路径控制就切到 CLI;也 不要修改scripts/image_gen.py
4. 我们的 Stage1 该怎么接
4.1 换装 = edit,不是 generate
关键契约(references/cli.md / image-api.md):
- 编辑端点
POST /v1/images/edits,输入图最多 16 张 --image可重复传,顺序有意义,要在 prompt 里按 index 说明每张的 角色 —— 这正好是换装:--image 人物.png --image 衣服.png+ prompt "把第 2 张的服装穿到第 1 张的人物身上,保持面部/发型/体型不变"gpt-image-2对图片输入恒为 high fidelity,不支持也不需要设input_fidelity—— 对"换装但人脸不变"是好消息,它默认就是最高保真档- 编辑 prompt 要每轮重复不变量("change only the outfit; keep the face, hairstyle and body unchanged")以减少漂移,这是官方 prompt 指导
- 实测发现的一个不一致:换旗袍时它保留了人物原来的黑皮鞋;换校服时它 自作主张把鞋换成了乐福鞋并加了过膝袜。"outfit"的边界它自己在拿捏。 prompt 里要显式规定鞋子怎么处理(保留原鞋 / 一并替换 / 不入镜), 否则同一批产出的脚部会不统一
4.2 尺寸:480×832 是非法输入
gpt-image-2 的尺寸硬约束:边 ≤3840、两边都是 16 的倍数、长短边比
≤3:1、总像素 655,360 – 8,294,400。
我们视频的 480×832 总像素只有 399,360,低于下限,传进去会被拒。
但这不是问题:Stage1 的参考图不需要等于视频分辨率。H3 出片的尺寸由
它自己的 width/height 参数决定(H3-CONSOLE.md),参考图给高一点反而
更清楚。竖屏候选(都已按上面四条约束验算过):
| 尺寸 | 总像素 | 比例 | 合法 |
|---|---|---|---|
1024x1536 |
1,572,864 | 2:3 | ✅ 推荐 |
832x1472 |
1,224,704 | ≈1.77:1,接近 9:16 | ✅ 更贴近视频构图 |
480x832 |
399,360 | 9:16 | ❌ 像素数不足 |
4.3 批量:edit 没有 batch 子命令
generate-batch 只对 generate 有效(JSONL + --concurrency,默认 5)。
我们的换装是 edit,所以批量得自己循环调用——冷启动脚本要自己做
并发控制和失败重试,不能指望 generate-batch。
4.4 内置模式 vs CLI 模式,怎么选
内置 image_gen(走 codex exec) |
CLI image_gen.py |
|
|---|---|---|
| 凭证 | 已登录的 ChatGPT 账号 | OPENAI_API_KEY |
| 成本 | 订阅额度(实测一张 ≈3 万 token) | 按张计费 |
| 输出路径 | 固定 $CODEX_HOME/...,要自己 move |
--out 精确指定 |
| 尺寸控制 | prompt 里明确写就能命中(实测 3/3 精确到 1024×1536);写得含糊会漂 | --size 精确 |
| 并发 | 无(一次一个 exec 进程) | --concurrency |
| 确定性 | 低(Agent 中转,可能自作主张) | 高(直接打 API) |
建议:冷启动批量走内置模式 + codex exec,因为这个项目的整个前提
就是"冷启动内容零按次成本"(需求文档 4.3 节),订阅额度正好对上;确定性
差一点可以靠脚本兜(见 5.2 的取回约定)。真要上生产的实时付费路径,再
评估 CLI/API 模式或别的通道。
5. 接入方式(建议写进冷启动脚本)
5.1 调用形态
codex exec --skip-git-repo-check -s workspace-write \
-o "$TMP/last.txt" \
"$PROMPT" \
-i "$CHARACTER_IMG" -i "$GARMENT_IMG"
注意 prompt 在 -i 之前,原因见下面的踩坑。
-i/--image可重复,把两张参考图直接附进初始 prompt(省掉手动view_image那一步)-o/--output-last-message把最后一条消息写进文件 —— 让 prompt 结尾 强制要求"只输出生成图的绝对路径",脚本读这个文件取回路径--json也可以,输出 JSONL 事件流,要更结构化的进度时用
⚠️ 踩坑(实测):-i/--image 是变长参数(<FILE>...)
codex exec -i a.png -i b.png "PROMPT"→ prompt 被当成第三个图片文件 吞掉,进程转而从 stdin 读 prompt,报No prompt provided via stdincodex exec "PROMPT" -i a.png b.png→ 两个文件挂在同一个-i上, 实测挂死 10 分钟、零输出、不产图- ✅ 正确写法:prompt 放最前面,每个文件单独一个
-icodex exec [其他 flag] "$PROMPT" -i person.png -i garment.png
5.2 取回约定(内置模式没有目标路径参数,必须自己搬)
- prompt 末尾固定加一句:
Then print ONLY the absolute path of the generated image file, nothing else. - 读
-o指定的文件拿到路径 - 校验:文件存在、是 PNG、尺寸等于 prompt 里要求的值。尺寸只要在 prompt 里明确写就能命中(实测 3/3),但它不是硬参数,校验不能省
copy到我们自己的uploads/composed/{uuid}.png,不要让产物只留在$CODEX_HOME(SKILL.md明确要求项目引用的资产不能只躺在那)
5.3 沙箱
codex exec 默认带沙箱。-s workspace-write 实测够用。图片落在
$CODEX_HOME 而不是工作区,所以脚本要有读 ~/.codex/ 的权限。
6. 还没验证的(正式接入前必须跑)
换装质量本身—— 已实测通过(见第 2 节表格)。但用的是 gpt-image-2 自己生成的合成素材;换成真实拍摄的人物照/衣服图后要再抽 查一遍,真实照片的光线、背景杂乱度、衣服褶皱都比合成图难。- 并发:多个
codex exec同时跑会不会撞订阅限流,没测过。 - 失败形态:额度耗尽、内容被拒、超时各自返回什么,脚本要能区分 "重试有用"和"重试没用"。
- 额度消耗:单张约 3 万 token 是一次样本。冷启动要跑几十上百张, 实际配额够不够要先小批量试。
7. 两个合规提醒(不是技术问题,但会让流水线在运行时断掉)
- 订阅额度的用途:内置模式跑在个人 ChatGPT 订阅上。把它当成一个对外
商业产品(付费直播间)的生产后端,是否符合 OpenAI 的订阅条款,值得先
确认一下。按张计费的
OPENAI_API_KEY路径在这点上是干净的,代价是成本。 - 内容策略:
gpt-image-2带内容审核(API 有moderation参数)。 冷启动阶段用我们自己的素材/合成人物没问题;但需求文档模式三是 观众上传真人照片做换装,这类请求大概率会被 OpenAI 侧拦下来。也就是 说 这条通道适合第一期冷启动,不一定能承载第五期的付费传人物——那时 候可能还是得回到自己的 GPU(ComfyUI)或别的供应商。这一点要早点想清楚, 别在第五期才发现通道不通。
8. 相关文档
H3-CONSOLE.md— Stage2 视频生成(内部 2080Ti 集群)docs/todo/dressup-dance-room.md8.1 — Stage1 的路径选择docs/todo/dev-plan.mdS1/S3 — S3 已完成,S1/S2/S4 待跑~/.codex/skills/.system/imagegen/SKILL.md— 本机技能原文(本文引用的 契约都来自它和references/cli.md、references/image-api.md)