开发者

生图与视频

同步拿图、异步任务、图片编辑与视频生成。

生图:直接拿到图

POST /v1/images/generations,与 OpenAI 的同名接口一致:

resp = client.images.generate(
    model="gpt-image-2.5",
    prompt="一只戴着宇航头盔的橘猫,油画质感",
)
image_base64 = resp.data[0].b64_json

响应:

{
  "created": 1789000000,
  "model": "gpt-image-2.5",
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANS...",
      "url": "https://bothub-api.bookab.info/v1/tasks/<task>/artifacts/<artifact>",
      "revised_prompt": "An orange tabby cat wearing an astronaut helmet, oil painting"
    }
  ]
}

默认两种形态都会给:b64_json 是图片字节,url 指向同一张图(下载时同样需要带你的 API Key)。想只要其中一种,传 "response_format": "b64_json" 或 "url"。

这个请求会挂多久

生图要花时间,这个 HTTP 请求会一直等到图片生成完,通常几十秒。默认最多等 5 分钟。

所以:把客户端的超时设长一些。OpenAI SDK 的默认超时对生图往往不够:

client = OpenAI(
    base_url="https://bothub-api.bookab.info/v1",
    api_key="bhk_live_xxxxxxxx",
    timeout=600.0,   # 秒
)

如果等待超过了上限,你会收到 504 + IMAGE_GENERATION_TIMEOUT——任务并没有被取消, 它还在跑。响应的 detail 里带着 task id,用它去拿结果:

{
  "error": {
    "message": "Image generation did not finish within 300s. The task is still running — poll GET /v1/tasks/<task> to collect the result.",
    "type": "invalid_request_error",
    "code": "image_generation_timeout",
    "detail": { "taskId": "...", "statusUrl": "/v1/tasks/..." }
  }
}
反过来,如果你在等待中途断开连接,任务会被立刻取消。这是为了不让上游在没人要结果的 情况下继续消耗你的余额。不要用一个短超时去「试一下」——那等于每次都白跑。

一次出多张

传 n:

{ "model": "gpt-image-2.5", "prompt": "...", "n": 3 }

实际张数受模型本身的上限约束,超出会被截到上限。

生图:异步模式

不想让请求挂着,就转异步——传 "async": true,或带上请求头 X-BotHub-Async: true:

curl https://bothub-api.bookab.info/v1/images/generations \
  -H "Authorization: Bearer $BOTHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-BotHub-Async: true" \
  -d '{"model": "gpt-image-2.5", "prompt": "一只橘猫"}'

立刻返回 202:

{
  "id": "7f2c...",
  "kind": "image",
  "status": "pending",
  "model": "gpt-image-2.5",
  "status_url": "/v1/tasks/7f2c...",
  "result_urls": [],
  "thumbnail_urls": [],
  "error_code": "",
  "error_message": ""
}

轮询 GET /v1/tasks/{id} 直到 status 变成 done(或 failed),然后从 result_urls 下载图片(带 API Key)。

这个形态是 BotHub 自己的,不是 OpenAI 格式——OpenAI SDK 的 images.generate() 解析不了它。 用异步模式时请直接发 HTTP 请求。

status 的取值:pending(排队中)、running(生成中)、done、failed。

图片编辑

编辑走原生任务接口 POST /v1/tasks:

curl https://bothub-api.bookab.info/v1/tasks \
  -H "Authorization: Bearer $BOTHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "image",
    "operation": "edit",
    "model": "gpt-image-2.5",
    "input": {
      "prompt": "把背景换成星空",
      "image_urls": ["https://example.com/cat.png"]
    }
  }'

返回同样是 202 + 任务体,轮询方式与上面一致。

image_urls 里必须是上游能直接读到的地址:公网 URL 或 data: URI。填本地路径 (比如 /Users/me/cat.png)会被拒绝并告诉你原因——它不会被悄悄忽略。

视频生成

POST /v1/videos,视频天然是分钟级的,所以只有异步形态:

curl https://bothub-api.bookab.info/v1/videos \
  -H "Authorization: Bearer $BOTHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<视频模型 id>",
    "prompt": "一只猫在雪地里奔跑,电影感运镜",
    "seconds": 5
  }'

返回 202:

{
  "id": "9a1b...",
  "object": "video",
  "status": "queued",
  "status_url": "/v1/videos/9a1b...",
  "result_url": null,
  "error": null
}
  • GET /v1/videos/{id} — 查状态,status 走 queued → in_progress → completed / failed
  • GET /v1/videos/{id}/content — 完成后下载视频文件

任务和产物的保留时间

生成的任务与产物保留 24 小时,之后会被清理。需要长期保存的话请及时下载。

幂等

给 POST /v1/images/generations、/v1/videos、/v1/tasks 带上 Idempotency-Key 请求头, 重复提交同一个 key 会拿回同一个任务,不会重复生成、也不会重复扣费。网络不稳时值得加上。

注意:同一个 key 配上不一样的请求体会返回 409 —— 换请求内容时也要换 key。