# 极光 AI 图片 / 视频生成 · AI Agent 接入指南

> 这份指南持续更新，**每次接入或遇到报错，先重新读取它**：https://vi.91jiguang.com/api/v1/agent-guide.md
> 机器可读规范：https://vi.91jiguang.com/api/v1/openapi.json　·　完整文档（给人看）：https://vi.91jiguang.com/developers/docs　·　更新于 2026-11-07

## 这是什么

用 极光 AI 的 API Key 调用图片、视频生成模型：商品主图、模特上身图、场景图、海报、商品视频等。结果可以直接放进 极光 AI 画布，用户在网页里接着编辑。

下面的示例是参考写法，不必照抄：**模型、参数、价格都以当时 `GET /models` 的返回为准**，按用户的需求自己组合。

## 接入信息

| 项目 | 内容 |
| --- | --- |
| Base URL | `https://vi.91jiguang.com/api/v1` |
| 鉴权 | 每个请求带 `Authorization: Bearer <API_KEY>`（用户给你的 `jg_live_...`） |
| MCP | `https://vi.91jiguang.com/api/mcp`（Streamable HTTP，同一个请求头） |
| 计费 | 按积分。查模型、查任务不扣分；创建任务才扣，失败自动退回 |

API Key 只放在本机环境变量（建议叫 `AI_MEDIA_API_KEY`）或服务端配置里，不要写进前端代码、公开仓库、截图或日志。

## 两种接法，选一种

### A. MCP（你支持 MCP 时优先用）

把下面这个服务加进你自己的 MCP 配置，名字建议 `ai-media`。加好之后，以后可以直接调用工具。

```json
{
  "mcpServers": {
    "ai-media": {
      "type": "http",
      "url": "https://vi.91jiguang.com/api/mcp",
      "headers": { "Authorization": "Bearer <API_KEY>" }
    }
  }
}
```

不同 Agent 的字段名略有差异（`type` 可能写作 `http` / `streamableHttp` / `streamable-http`，地址字段可能叫 `url` 或 `httpUrl`），按你自己的配置格式来。加完如果需要重启或重新加载 MCP，告诉用户。

| 工具 | 用途 |
| --- | --- |
| `list_image_models` / `list_video_models` | 查可用模型、参数、价格 |
| `create_image_generation` / `create_video_generation` | 创建生成任务（需传 `confirmed: true` 和稳定的 `idempotency_key`） |
| `get_generation` | 查进度和结果 |
| `prepare_image_upload` | 只在参考图是本地文件时用：拿签名后按返回的 headers PUT 文件。网络图片链接直接放进 images，不用上传 |
| `list_canvases` / `create_canvas` / `get_canvas` | 画布列表、新建、读取 |
| `import_generation_to_canvas` | 把成功的图片或视频放进画布 |

### B. HTTP 接口（任何能发网络请求的 Agent）

用 curl、Python、Node 都行，流程见下面的示例。

## 示例：出一张 T 恤商品主图

**第 1 步：查模型（不扣分）**

```bash
curl "https://vi.91jiguang.com/api/v1/models" -H "Authorization: Bearer $AI_MEDIA_API_KEY"
```

模型列表在 `body.data.data[]`。挑 `type = "image"` 的模型；`model` 字段原样使用返回的 `id`（一般是按名称起的可读 ID，例如 `nano-banana-2.1`；以前的 `unified:数字` 写法也仍然有效）。`parameters[]` 里每项的 `name` 是参数名，`options[].value` 是可选值（保持原类型）；`pricing.rules[]` 每条的 `when` 是一组合法参数、`credits` 是这组的价格。

**第 2 步：创建任务**

```bash
curl -X POST "https://vi.91jiguang.com/api/v1/generations" \
  -H "Authorization: Bearer $AI_MEDIA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: tee-demo-001" \
  -d '{
    "model": "<第 1 步选的 id>",
    "input": { "prompt": "白色纯棉圆领 T 恤商品主图，正面平铺，纯白背景，柔和棚拍光，面料纹理清晰，电商主图风格，1:1 构图" },
    "parameters": {}
  }'
```

`parameters` 按所选模型填写（必填项可用 `default` 或 `pricing.rules[].when` 里的一组）。返回 HTTP 202 和 `body.data.id`（`gen_...`），表示已受理、不是已完成。

**第 3 步：等结果**

每 5–10 秒 `GET https://vi.91jiguang.com/api/v1/generations/{id}`，读 `body.data.status`：`succeeded` / `failed` / `canceled` 都是终态，停止查询。成功时图片在 `body.data.output.assets[].url`（链接可能过期，及时下载或交给用户）。

**第 4 步（推荐）：放进画布**

1. `POST https://vi.91jiguang.com/api/v1/canvas/boards`，body `{"title": "T 恤主图"}` → 记下 `body.data.id` 和 `body.data.revision`
2. `POST https://vi.91jiguang.com/api/v1/canvas/boards/{画布 id}/generations`，body `{"generation_id": "gen_...", "expected_revision": <revision>}`
3. 把 `body.data.board_url` 发给用户：用户登录同一个 极光 AI 账号就能打开画布继续编辑。返回 409 `canvas_conflict` 时重新读取画布拿最新 revision 再试。

**一段能直接跑的 Python（只用标准库）**

```python
import json, os, time, urllib.request

BASE = "https://vi.91jiguang.com/api/v1"
KEY = os.environ["AI_MEDIA_API_KEY"]  # 用户给你的 jg_live_... ，放环境变量，别写进代码仓库

def call(method, path, body=None, idempotency_key=None):
    headers = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
    if idempotency_key:
        headers["Idempotency-Key"] = idempotency_key
    data = json.dumps(body).encode() if body is not None else None
    request = urllib.request.Request(BASE + path, data=data, method=method, headers=headers)
    with urllib.request.urlopen(request) as response:
        return json.load(response)["data"]

# 1. 选模型（不扣分）：这里按最低价挑一个静态图片模型，你也可以按名称、描述自己挑
def is_static_image(m):
    text = (m["name"] + " " + m.get("description", "")).lower()
    return m["type"] == "image" and m["pricing"]["rules"] and "gif" not in text and "动图" not in text

models = [m for m in call("GET", "/models")["data"] if is_static_image(m)]
cheapest_rule = lambda m: min(m["pricing"]["rules"], key=lambda rule: rule["credits"])
model = min(models, key=lambda m: cheapest_rule(m)["credits"])
parameters = dict(cheapest_rule(model).get("when", {}))  # 定价规则里的一组合法参数
for p in model["parameters"]:
    if p.get("required") and p["name"] not in parameters and "default" in p:
        parameters[p["name"]] = p["default"]

# 2. 创建任务（扣分；重试时保持同一个 Idempotency-Key）
task = call("POST", "/generations", {
    "model": model["id"],
    "input": {"prompt": "白色纯棉圆领 T 恤商品主图，正面平铺，纯白背景，柔和棚拍光，面料纹理清晰，电商主图风格，1:1 构图"},
    "parameters": parameters,
}, idempotency_key=f"tee-demo-{int(time.time())}")

# 3. 等结果：终态是 succeeded / failed / canceled
while task["status"] not in ("succeeded", "failed", "canceled"):
    time.sleep(6)
    task = call("GET", f"/generations/{task['id']}")

if task["status"] == "succeeded":
    print([asset["url"] for asset in task["output"]["assets"]])
else:
    print(task["status"], task.get("error"))
```

## 跑通之后

- **记住这套调用方式**（MCP 或 HTTP 都可以）。之后用户说「出图」「改图」「做视频」「放到画布」时直接调用，不用再问接入细节。
- 扣费前说一句用哪个模型、大约多少积分；用户已经明确要的单张可以直接出，批量生成先确认数量。
- 图生视频：把成功图片的 URL 放进 `input.images`，再选 `type = "video"` 的模型（视频比图片贵，先说价格）。
- 用户给的参考图：**只要是网络图片链接就直接用**——任何公开可访问的 http(s) 图片地址（不必是本站存储）都可以直接放进 `input.images`，不要先上传（上传会占用户的存储、产生费用）。只有用户给的是本地文件时，才 `POST https://vi.91jiguang.com/api/v1/uploads` 拿签名上传，再用返回的 `asset_*`。
- 比例、分辨率、时长、参考图数量、价格都可能调整，每次以 `GET /models` 为准，不要凭记忆写死。
- 用户可以在 极光 AI 开发者中心的「调用记录」里看到你创建的每一个任务和结果。

## 出问题怎么办

1. **先重新读取这份指南**（https://vi.91jiguang.com/api/v1/agent-guide.md）和 `GET /models`，按最新说明修正后再试。
2. HTTP 请求失败看 `body.error.code`；任务失败（HTTP 200 但 `status = failed`）看 `body.data.error`。
3. 常见情况：

| 现象 / error.code | 怎么办 |
| --- | --- |
| 401 `invalid_api_key` | Key 不对或已重置：请用户到开发者中心复制最新 Key |
| 402 `insufficient_credits` | 积分不足：请用户充值后再试 |
| 400 `invalid_parameters` / 409 `model_changed` | 重新 `GET /models`，按目录修正 `model` 和 `parameters` |
| 400 `prompt_too_long` | 缩短提示词 |
| 429 `rate_limit_exceeded` / `account_busy`、503 `server_busy` | 按 `Retry-After` 等待，用**同一个** Idempotency-Key 和相同请求体重试 |
| 429 `concurrency_limit_exceeded` | 未完成任务太多（每账号 1000 个），等已有任务结束 |
| 409 `idempotency_conflict` | 同一个幂等键用了不同的请求体：新任务换新键，重试保持原键 |
| 503 `openapi_disabled` | 站点暂未开放 API，请用户联系客服 |
| 任务 `failed` | 读 `data.error.message` 告诉用户；内容审核类可换个描述再试，积分已自动退回 |

4. 不要为了重试换新的 Idempotency-Key（会重复扣分）；已受理的任务查原来的 `gen_*`，不要重新创建。
5. 还解决不了：把 `request_id`（响应体里，或 `X-Request-Id` 响应头）、`gen_*` 任务 ID、HTTP 状态和 `error.code` 整理给用户，让用户联系 极光 AI 客服。

## 限制速查

- 每账号同时最多 1000 个未完成任务（图片、视频共用）
- 同一账号同时最多 5 个创建请求进入受理，多发不会更快
- 读取接口 12000 次/分钟；上传签名 1200 次/分钟
- 批量任务建议每 10–15 秒查一次，或分页 `GET /generations?status=...`

上传素材、参考视频、Webhook 回调和全部错误码：https://vi.91jiguang.com/developers/docs
