mcpField
P
product-shots-image-gen

product-shots-image-gen

github.com/motiful创意与媒体121137 次安装20 周前更新
代码仓库

关于 product-shots-image-gen

此技能将图像生成请求路由到 OpenAI 或 Gemini 系列 API,并将结果保存到磁盘,适用于产品图工作流。它会预处理参考图,处理模型专属参数,并在调用前检查 API 密钥配置。

主要功能

  1. 01按模型系列路由请求
  2. 02根据文本或参考图生成图像
  3. 03发送前调整参考图尺寸
  4. 04处理宽高比与负面约束
  5. 05在本地保存结果并返回路径
  6. 06调用前检查 API 密钥配置

适用场景

  1. 01根据提示词生成产品图
  2. 02利用参考文件生成图像变体
  3. 03通过兼容网关执行图像生成

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/motiful/product-shots --skill product-shots-image-gen

安装后在 Claude Code 中输入/product-shots-image-gen确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
error-handling.md
model-selection.md
parameter-spec.md
reference-image-handling.md
scripts/
generate.py
setup.sh

详细介绍

图像生成

产品图生态系统的图像生成引擎。提供单一的参数化入口:根据模型系列将请求路由到正确的 API 端点(OpenAI 的 /v1/images/generations 和 /v1/images/edits,或 Gemini 的多模态 /v1/chat/completions),预处理参考图像,并返回已保存的文件路径。

主要后端:OmniMaaS / Cloubic 图像网关——https://api.omnimaas.com/v1。该网关兼容 OpenAI SDK,通过一个身份验证令牌统一提供对 GPT image 2 和 Gemini Nano Banana 系列的访问。请参阅:

**备用后端:**任何其他兼容 OpenAI SDK 的图像网关均可使用——设置 PRODUCT_SHOTS_IMAGEGEN_BASE_URL 和 PRODUCT_SHOTS_IMAGEGEN_API_KEY,或者在迁移后的安装中继续使用旧版 CANVASFLOW_IMAGEGEN_* 环境变量。

入门设置(首次使用)

**生成任何图像之前,此技能都必须确认已配置 API 网关。**如果缺少环境变量,请将以下说明原样展示给用户——绝不要静默回退到硬编码密钥,也不要要求用户复刻仓库或将密钥粘贴到聊天中。

检测逻辑

每次调用时都运行。按以下顺序解析:

  1. OMNIMAAS_API_KEY(环境变量,优先使用——统一的 Cloubic / OmniMaaS 网关)
  2. PRODUCT_SHOTS_IMAGEGEN_API_KEY(环境变量,通用备用项)
  3. CANVASFLOW_IMAGEGEN_API_KEY(环境变量,旧版兼容项)
  4. ~/.product_shots_imagegen_api_key(文件,权限设为 600,单行密钥)
  5. ~/.canvasflow_imagegen_api_key(文件,旧版)

如果以上均未解析出密钥,停止并在下一节输出入门说明。不要尝试调用 API。

入门说明(缺少环境变量时原样展示给用户)

**此技能需要图像网关 API 密钥才能生成图像。**你尚未配置密钥——以下是 30 秒快速设置说明:

选项 A——临时设置(仅限当前终端):

export OMNIMAAS_API_KEY="sk-..."             # 你的 OmniMaaS / Cloubic 令牌
# 可选:仅在你使用私有网关端点时设置
# export OMNIMAAS_BASE_URL="https://api.omnimaas.com/v1"

选项 B——在多个会话中持续生效: 将相同的 export 行添加到 ~/.zshrc(或 ~/.bashrc),然后运行 source ~/.zshrc。

选项 C——通过文件设置(无需环境变量):

echo "sk-..." > ~/.product_shots_imagegen_api_key
chmod 600 ~/.product_shots_imagegen_api_key

**获取密钥的方式:**访问 docs.cloubic.com——从 OmniMaaS / Cloubic 控制台获取令牌。同一个令牌可用于 OpenAI gpt-image-2 和 Gemini gemini-3-pro-image-preview(Nano Banana Pro)。

任何兼容 OpenAI SDK 的图像网关也都可以使用——将 OMNIMAAS_* 替换为指向你的网关的 PRODUCT_SHOTS_IMAGEGEN_BASE_URL 和 PRODUCT_SHOTS_IMAGEGEN_API_KEY。

配置完成后,重新运行原始请求。

安全要求
  • 绝不要回显完整密钥。确认检测到密钥时,只显示前 8 个字符(sk-wPfH6K…)。
  • 绝不要将密钥写入日志、标准输出或仓库内的任何文件。
  • 绝不要指示用户复刻仓库、编辑技能源文件或将密钥粘贴到聊天中。密钥只能存放在环境变量或 ~/.*_api_key 文件中。
  • API 密钥只能通过 Authorization: Bearer <key> 标头传输。
本地代理绕过(中国用户)

ClashX / Shadowsocks / 类似的本地代理会将 ALL_PROXY=socks5://... 注入环境,从而导致 requests 出错(Missing dependencies for SOCKS support)。随附的 scripts/generate.py 已通过 Session.trust_env = False 处理此问题。如果你自行实现调用程序,请复现此模式。

交互原则

这些规则始终适用。执行前请阅读。

  1. 自动检测模型系列,绝不询问用户。 模型名称(例如 gpt-image-2 与 gemini-3-pro-image-preview)决定端点和请求格式。调用方指定模型;技能负责解析其所属系列。
  2. 调用方未指定模型时,默认使用 gemini-3-pro-image-preview。 它是单模型中表现最强的(Nano Banana Pro),并通过一个端点同时支持文生图和图生图。参见 references/model-selection.md。
  3. 发送参考图前,最大尺寸必须 ≤1024px,且文件大小必须 ≤1MB。 否则自动调整大小。原因:大多数边缘代理会在约 100s 时超时;2.5MB 的 PNG 加上 base64 扩容和 Gemini 处理,通常会在该时限触发 HTTP 524。参见 references/reference-image-handling.md。
  4. 负向约束会以“避免:……”的形式附加到提示词中,绝不作为单独参数发送。 没有受支持的模型提供真正的 negative_prompt 字段;这是 API 的设计如此,并非权宜之计。
  5. 不同系列的宽高比处理方式不同。 OpenAI:转换为像素 size 参数。Gemini:附加到提示文本中(“宽高比:X:Y”),因为 chat-completions 没有尺寸字段。调用方传入 --aspect-ratio;技能会分别处理。
  6. 始终将输出保存到磁盘并返回路径。 绝不向调用方返回 base64 或 URL——磁盘上的文件才是规范产物。默认位置使用时间戳;调用方可通过 --output 覆盖。
  7. 每次调用都会记录费用和令牌用量。 调用方可据此进行预算。估算费率:gpt-image-2 ≈ ¥0.35/张,gemini-3-pro-image-preview ≈ ¥1/张,gemini-3.1-flash-image-preview ≈ ¥0.20/张。
  8. 图生图采用有限重试;其他情况一律快速失败。 图生图调用遇到可重试错误(HTTP 429、5xx、524、连接错误、读取超时)时,最多重试 3 次,并采用指数退避(每次尝试之间等待 1s、4s、16s)。文生图调用不重试。认证错误(401 / 403)会快速失败,绝不重试。参见 references/error-handling.md。
  9. API 密钥绝不会写入日志或标准输出。 按以下顺序加载:OMNIMAAS_API_KEY(首选 — Cloubic / OmniMaaS 网关)→ PRODUCT_SHOTS_IMAGEGEN_API_KEY(规范通用密钥)→ RENDER_API_KEY(短别名)→ CANVASFLOW_IMAGEGEN_API_KEY(旧版)→ ~/.product_shots_imagegen_api_key → ~/.product_shots_render_api_key(兼容)→ ~/.canvasflow_imagegen_api_key(旧版)。仅通过 Authorization 标头传递。绝不回显。基础 URL 会自动解析(设置了 OMNIMAAS_API_KEY 且未显式设置 OMNIMAAS_BASE_URL 时,默认为 https://api.omnimaas.com/v1)。

执行流程

请严格遵循此流程。每个步骤对应 scripts/generate.py 中的一个章节。

generate_image(prompt, model, [aspect_ratio], [negative_prompt],
               [reference_images], [output_path]) → file_path

# Step 0 — Resolve API key + base URL (MUST come first)
api_key,  key_source = load_api_key()
    # 1. OMNIMAAS_API_KEY env var (preferred — OmniMaaS gateway)
    # 2. PRODUCT_SHOTS_IMAGEGEN_API_KEY env var (canonical generic)
    # 3. RENDER_API_KEY env var (short alias)
    # 4. CANVASFLOW_IMAGEGEN_API_KEY env var (legacy)
    # 5. ~/.product_shots_imagegen_api_key file
    # 6. ~/.product_shots_render_api_key file (compat)
    # 7. ~/.canvasflow_imagegen_api_key file (legacy)
    # fail with clear message if none present
base_url, url_source = load_base_url()
    # 1. OMNIMAAS_BASE_URL env var
    # 2. PRODUCT_SHOTS_IMAGEGEN_BASE_URL env var (canonical generic)
    # 3. RENDER_BASE_URL env var (short alias)
    # 4. CANVASFLOW_IMAGEGEN_BASE_URL env var (legacy)
    # 5. https://api.omnimaas.com/v1 (default when OMNIMAAS_API_KEY is set)

# Step 0a — Validate caller arguments + fill caller-context defaults
args = validate_args(args)                       # see references/parameter-spec.md
    # rejects empty prompt, unknown model, invalid aspect_ratio
    # auto-fills size for OpenAI from aspect_ratio
    # warns when Gemini ignores --n / --size
args = lookup_caller_defaults(caller_skill, surface) | args
    # caller-skill-specific defaults from parameter-spec.md §Family-Specific Defaults
    # explicit args win over defaults (dict merge with args on the right)

# Step 1 — Resolve model + identify family
if not model:
    model = select_default_model(use_case)       # see references/model-selection.md
        # use_case from caller brief: "text-overlay" / "photorealistic" /
        # "creative" / "image-to-image" / "cost-sensitive" / "general" (default)
        # ⚠ "text-overlay" WINS over all others — any caller whose prompt
        # asks for on-image letters or digits (headlines, labels, CTAs,
        # price chips, callouts) MUST pass "text-overlay" so the dispatcher
        # routes to gpt-image-2. Gemini family garbles small text.
family = model_family(model)                     # see references/model-selection.md
    # openai  → {gpt-image-1, gpt-image-2, dall-e-3}
    # gemini  → {gemini-3-pro-image-preview, gemini-3.1-flash-image-preview, ...}
    # unknown → exit with the supported model list

# Step 2 — Preprocess reference images (if any)
for img_path in reference_images:
    img_path = maybe_resize(img_path, max_dim=1024, max_bytes=1MB)
    # Pillow thumbnail → temp file
    # passthrough if already within limits
    # see references/reference-image-handling.md

# Step 3 — Compose effective prompt and size
final_prompt = compose_prompt(prompt, negative_prompt, aspect_ratio, family)
    # Gemini: prompt + "(aspect ratio: X:Y)" + "Avoid: ..."
    # OpenAI: prompt + "Avoid: ..."  (aspect handled via size param instead)
if family == "openai":
    size = OPENAI_SIZE_BY_RATIO[aspect_ratio] OR explicit --size OR "1024x1024"

# Step 4 — Dispatch
if family == "openai":
    if reference_images:
        response = POST <base_url>/images/edits  (multipart, image[]=@file...)
    else:
        response = POST <base_url>/images/generations  (JSON, {model, prompt, n, size})
elif family == "gemini":
    response = POST <base_url>/chat/completions
        body: {model, messages:[{role:"user", content:[
            {type:"text", text: final_prompt},
            {type:"image_url", image_url:{url: data_url_per_ref_image}}, ...
        ]}]}

if response.status != 200:
    handle_http_error(family, response.status, response.body)
                                                 # see references/error-handling.md

# Step 5 — Parse response (family-specific)
if family == "openai":
    first = response.body["data"][0]
    if "b64_json" not in first and "url" not in first:
        classify_response_error(family, response.body)  # references/error-handling.md
    image_bytes = base64_decode(first["b64_json"]) if "b64_json" in first else fetch(first["url"])
    ext = "png"
elif family == "gemini":
    content = response.body["choices"][0]["message"]["content"]
    # content is a markdown string: ![image](data:image/jpeg;base64,...)
    if no "data:image/...;base64" pattern in content:
        classify_response_error(family, response.body)  # references/error-handling.md
    image_bytes = base64_decode(extract_data_url(content))
    ext = "jpeg"

# Step 6 — Save + log
out_path = output_path OR ./output-<unix_ts>.<ext>
write_bytes(out_path, image_bytes)
log(gateway_source, elapsed, file_size, total_tokens, out_path)

# Self-check
assert out_path.exists()
assert out_path.stat().st_size > 10_000        # tiny files = broken response
return out_path

模块文件目录

  • references/model-selection.md — 模型目录(此技能支持的图像模型)、系列路由规则,以及按使用场景选择合适模型的决策树(照片级真实感 / 文本渲染 / 低成本高速 / CJK 文本渲染)。
  • references/parameter-spec.md — scripts/generate.py 的所有 CLI 标志:名称、类型、默认值、适用的系列、有效范围。调用方可传入内容的唯一可信来源——包括完整的 API 密钥 / 基础 URL 解析顺序。
  • references/reference-image-handling.md — 524 错误的发现、1024px / 1MB 上限、多参考图行为(Gemini 每次调用最多 ≤9 张图片)、直传规则,以及使用 Pillow thumbnail 的原因(保留宽高比)。
  • references/error-handling.md — 常见 API 故障模式(401 / 429 / 524 / 响应格式错误 / 连接超时),以及诊断消息和建议的调用方处理方式。524 → 调整大小并重试模式。

章节索引

Goal                                              → SKILL.md intro paragraph
Engagement Principles                             → SKILL.md §Engagement Principles
Execution Procedure                               → SKILL.md §Execution Procedure
Model Selection                                   → references/model-selection.md
   Family Routing
   Model Catalogue
   Decision Tree
Parameter Spec                                    → references/parameter-spec.md
   CLI Flags
   Aspect Ratio → OpenAI Size Mapping
   API Key + Base URL Resolution
Reference Image Handling                          → references/reference-image-handling.md
   The 524 Finding
   Auto-Resize Rule
   Multi-Reference Constraints
Error Handling                                    → references/error-handling.md
   Common Failure Modes
   Retry Patterns

工具配置

  • scripts/generate.py — 参数化入口。仅使用标准库、requests 和 Pillow。无需主机功能支持。
  • scripts/setup.sh — 幂等依赖安装程序(Python 3 + pip + requests + Pillow)。首次使用前运行一次。
  • 不调用子技能。此技能是叶节点,不会调用其他技能。
  • 调用方(其他产品截图专用技能)通过 shell 调用。请从主机的技能目录解析脚本路径,而不要硬编码任何平台路径:
    # Path examples — pick whichever your harness uses; do NOT bake one in:
    #   Claude Code:  ~/.claude/skills/product-shots-image-gen/scripts/generate.py
    #   Codex:        ~/.agents/skills/product-shots-image-gen/scripts/generate.py
    #   Cursor:       ~/.cursor/skills/product-shots-image-gen/scripts/generate.py
    #   Windsurf:     ~/.codeium/windsurf/skills/product-shots-image-gen/scripts/generate.py
    #   Copilot:      ~/.copilot/skills/product-shots-image-gen/scripts/generate.py
    python <skill-dir>/scripts/generate.py \
        --prompt "..." --model gemini-3-pro-image-preview --output ./out.jpeg
    
    或通过直接导入 Python 中的 generate_openai / generate_gemini 函数调用。

调用方约定

从产品截图生态系统中的其他技能调用时(例如,product-shots-main-image 执行 image = generate_image(prompt) 步骤),调用方会传入:

字段必填格式技能行为
prompt是字符串,≤4000 个字符原样传递(并附加负面提示词和宽高比)
model是来自支持的集合按系列路由到相应端点
aspect_ratio否"1:1" / "16:9" / "9:16" / "4:3" / "3:4" / "3:2" / "2:3"OpenAI:→ size;Gemini:附加到提示词
reference_images否文件路径列表发送前自动调整大小至 ≤1024px / ≤1MB
negative_prompt否字符串以 "Avoid: …" 的形式附加
output否文件路径默认为 ./output-<ts>.<png|jpeg>

返回:磁盘上的文件路径(OpenAI 为 PNG,Gemini 为 JPEG)。调用方必须将该文件视为规范产物。

OmniMaaS 网关快速入门

# 1. Get an OmniMaaS / Cloubic API token from https://docs.cloubic.com
export OMNIMAAS_API_KEY="your-omnimaas-token"

# 2. (optional) Override the base URL if you have a private endpoint
# export OMNIMAAS_BASE_URL="https://api.omnimaas.com/v1"

# 3. Install dependencies
bash scripts/setup.sh

# 4. Test
python scripts/generate.py --prompt "a red apple on wood" \
                           --model gemini-3-pro-image-preview \
                           --output /tmp/test.jpeg

设置 OMNIMAAS_API_KEY 后,脚本会自动将基础 URL 默认设为 https://api.omnimaas.com/v1,无需额外配置。

评论

支持 Markdown