service_online/OpenAI Compatible/image · video

一把 KEY,接入生图 · 生视频

文生图与文生视频统一收进同一个接口、同一个 KEY。具体怎么接,全部在下面这份文档里。

POST/v1/images/generations
POST/v1/videos

接入方式

RESTful 风格接口,兼容主流图像 / 视频生成 API 的请求结构。把 base_url 指向本站、 把 Authorization 换成统一 KEY 即可,其余参数照常填写。

01

配置环境变量

把 KEY 放在环境变量里,不要写进代码
export RELAY_BASE_URL = "http://ai.beiangou.com"
export RELAY_API_KEY  = "<平台方提供的统一 KEY>"
02

生成图片(同步)

POST /v1/images/generations
curl -sS -X POST "http://ai.beiangou.com/v1/images/generations" \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "image-2.5-flash",
    "prompt": "晨光透过白色纱帘洒在极简客厅,空气中漂浮着微尘,胶片质感",
    "size": "2K",
    "ratio": "16:9",
    "extra_body": { "response_format": "url" }
  }'

返回路径 data[0].url。 文生图必填 model / prompt,可选 n(张数,最多 6)、seed;ratio 取 1:1 / 3:4 / 4:3 / 16:9 / 9:16 / 2:3 / 3:2 / 21:9,size 支持档位(1K–4K)或 宽x高 精确写法;URL 输出务必写在 extra_body.response_format, 不能放在请求体顶层。建议客户端超时 60–360 秒(4K 更久),本站上限 300 秒。

兼容主流 SDK:像 quality / background 这类 SDK 默认携带、但本通道不接受的字段会被自动忽略,size:"auto" 归到默认档, 实际改动通过响应头 x-relay-compat 如实回传,不影响出图。

并发提交:生图支持一次性整批并发发出, 无需在客户端自行限速或错峰,排队与调度由平台侧完成。瞬时并发过高时个别请求可能返回 429(relay_overloaded / relay_queue_timeout),此类响应未进入生成、不产生费用, 直接重试即可。

03

图生图 / 多图合成

在 extra_body.image 传入参考图
curl -sS -X POST "http://ai.beiangou.com/v1/images/generations" \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "image-2.5-flash",
    "prompt": "把这张照片改成赛博朋克夜景,保留主体构图",
    "size": "1K",
    "ratio": "4:3",
    "extra_body": {
      "image": ["https://example.com/source.jpg"],
      "response_format": "url"
    }
  }'

图生图不需要 tags;Base64 输出用 extra_body.response_format: "b64_json", 返回路径 data[0].b64_json。 写在顶层的 image / images 也会自动归到 extra_body.image,两种写法都能用。

参考图可以是 https:// 公网地址、 data:image/...;base64, 内联,也可以直接复用生图接口返回的 url(无需你自己转存)。纯内网 / localhost 落地址取不到, 返回 400 bad_request 并说明原因。

04

创建视频任务(异步)

POST /v1/videos · 文生视频
curl -sS -X POST "http://ai.beiangou.com/v1/videos" \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "video-2.5-flash",
    "prompt": "雨后的未来城市街道,霓虹灯倒映在地面,一辆银色跑车缓慢驶过,电影级运镜",
    "mode": "text",
    "seconds": "5",
    "size": "720P",
    "aspect_ratio": "16:9"
  }'

从响应中保存 video_id。seconds 为时长("4"–"12",写成数字如 5 也会自动归一为字符串);画幅用 aspect_ratio(见右侧 720P 画幅表,共 6 档)。 生图与生视频均固定使用对应的免费模型(image-2.5-flash / video-2.5-flash),传其他模型名会被归一到该免费模型,并在响应头 x-relay-model-override 中告知;视频分辨率固定 "720P",请求 1080P 会返回 400。

并发提交:多个视频任务可以一次性并发发出, 无需在客户端自行限速或错峰,排队与调度都在平台侧完成。并发量较大时,个别任务可能返回 429,按 Retry-After 重试即可。 注意「创建任务」这一步在整批并发下会被摊开发出(响应可能较慢,实测可达 100s+), 客户端对 POST /v1/videos 的超时应给足(建议 ≥180s), 不要设得太短导致任务其实已创建、客户端却先超时。

图视混发:生图与生视频可以在同一批里混着并发发出, 两种任务互不阻塞、各走各的处理通道,无需拆分成先后两批。

04b

首尾帧 / 参考视频模式

mode=keyframe:first_frame(锁第一帧)/ last_frame(锁最后一帧),两者至少给一个
curl -sS -X POST "http://ai.beiangou.com/v1/videos" \
  -H "Authorization: Bearer $RELAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "video-2.5-flash",
    "prompt": "镜头缓缓推进,人物转身走向霓虹深处",
    "mode": "keyframe",
    "first_frame": "https://example.com/first.jpg",
    "last_frame": "https://example.com/last.jpg",
    "seconds": "8",
    "size": "720P",
    "aspect_ratio": "16:9"
  }'

# 也接受数组写法(等价): "images": ["https://…/first.jpg", "https://…/last.jpg"]

keyframe 把传入图片锁成第一帧(可再给尾帧锁成最后一帧),动画严格从这一帧开始; 首尾两个位置至少给一个,推荐 first_frame / last_frame,数组写法 images:[首帧, 尾帧] 等价可用(≤2 张)。reference 语义不同——只把素材当参考(构图由模型自行决定),支持 images(≤5)/ videos /audios(≤3,音视频同步)。 可选 callback_url,任务完成时会回调。

素材地址怎么填
图片支持三种写法:① https:// 公网地址; ② data:image/...;base64, 内联; ③ 直接复用生图接口返回的 url(本站会把内部地址还原成可拉取的源,无需你自己转存)。 纯内网 / localhost 的外部落地址取不到,会返回 400 bad_request 并说明原因。 素材尺寸有下限:边长需在 256–5760 像素之间,太小的占位图会被如实拒绝。
05

查询可用模型

GET /v1/models · OpenAI SDK 初始化时会调用
curl -sS "http://ai.beiangou.com/v1/models" \
  -H "Authorization: Bearer $RELAY_API_KEY"

# { "object": "list", "data": [ { "id": "image-2.5-flash", ... }, { "id": "video-2.5-flash", ... } ] }

返回 data[].id 即可直接用于model 参数;加 ?kind=image 或 ?kind=video 只要某一类。

06

轮询视频结果

GET /v1/videos/{video_id}
curl -sS "http://ai.beiangou.com/v1/videos/VIDEO_ID" \
  -H "Authorization: Bearer $RELAY_API_KEY"

建议每 2–5 秒查询一次,直到 status 为 completed 或 failed, 视频地址在顶层 url 字段, 可直接下载或内联播放,支持 Range 分段。

07

SDK 接入

Python · openai SDK 生图 + httpx 建视频
from openai import OpenAI
import httpx, time

BASE = "http://ai.beiangou.com"
KEY  = "<统一 KEY>"

client = OpenAI(base_url=f"{BASE}/v1", api_key=KEY, timeout=300)

# 1) 生图
img = client.images.generate(
    model="image-2.5-flash",
    prompt="晨光透过白色纱帘洒在极简客厅,胶片质感",
    n=1, size="1024x1024",
    extra_body={"ratio": "16:9", "response_format": "url"},
)
print(img.data[0].url)

# 2) 生视频:建任务 + 轮询
def gen_video(prompt: str, model: str = "video-2.5-flash") -> str:
    h = {"Authorization": f"Bearer {KEY}"}
    task = httpx.post(
        f"{BASE}/v1/videos", headers=h, timeout=180,
        json={"model": model, "prompt": prompt, "mode": "text",
              "seconds": "5", "size": "720P", "aspect_ratio": "16:9"},
    ).json()
    vid = task["video_id"]
    for _ in range(360):                      # 最长约 30 分钟
        st = httpx.get(f"{BASE}/v1/videos/{vid}", headers=h, timeout=30).json()
        if st["status"] == "completed":
            return st["url"]
        if st["status"] == "failed":
            raise RuntimeError(st.get("error", {}).get("message", "生成失败"))
        time.sleep(3)
    raise TimeoutError(vid)
Node.js · openai SDK + fetch
import OpenAI from "openai";

const BASE = "http://ai.beiangou.com";
const KEY  = process.env.RELAY_API_KEY;

const client = new OpenAI({ baseURL: BASE + "/v1", apiKey: KEY, timeout: 300_000 });

// 生图
const img = await client.images.generate({
  model: "image-2.5-flash",
  prompt: "雨后的未来城市街道,霓虹倒映在地面",
  n: 1,
  size: "1024x1024",
});
console.log(img.data[0].url);

// 生视频(SDK 未覆盖,用 fetch)
const auth = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };
const task = await (await fetch(BASE + "/v1/videos", {
  method: "POST", headers: auth,
  body: JSON.stringify({ model: "video-2.5-flash", prompt: "镜头缓慢推进", mode: "text",
                         seconds: "5", size: "720P", aspect_ratio: "16:9" }),
})).json();

for (;;) {
  const st = await (await fetch(BASE + "/v1/videos/" + task.video_id, { headers: auth })).json();
  if (st.status === "completed") { console.log(st.url); break; }
  if (st.status === "failed") throw new Error(st.error?.message ?? "生成失败");
  await new Promise((r) => setTimeout(r, 3000));
}
08

错误与重试

错误体统一为 OpenAI 风格: { "error": { "message", "type", "code" } }, 响应头带 x-request-id,反馈问题时请附上它。

HTTPcode处理建议
400bad_json / missing_prompt / bad_mode / bad_size / missing_frame / too_many_images参数不合法或素材张数超上限(图像 n≤6、首尾帧≤2、参考≤5、音频≤3),修正请求体后重发,不要原样重试
401missing_api_key / invalid_api_key未带 KEY 或 KEY 无效(已吊销 / 复制不完整),核对后重发
403api_key_disabled / capability_deniedKEY 已停用或未开通该能力(生图 / 生视频),联系发放方
403quota_exceeded日或累计配额用满,未进入生成、不计费,联系发放方调整
404query_failed / bad_media_tokenvideo_id 不存在或已过期,或资源 token 无效,勿重试
429rate_limited请求过于频繁,按 Retry-After 头退避后重试
429relay_overloaded服务瞬时繁忙,未进入生成、不计费,可立即重试
429relay_queue_timeout排队超时,稍后重试即可
429upstream_capacity该能力瞬时繁忙,按 Retry-After 稍后重试
429upstream_no_quota该能力暂时不可用,稍后重试或联系发放方
502 / 504upstream_error / all_keys_failed / media_fetch_failed服务处理异常或超时,带 request_id 反馈
503no_upstream_key服务暂时不可用,带 request_id 联系发放方

该重试:429(带 Retry-After 头时按其秒数退避,指数退避上限 30s)、502/503/504。不该重试:400(参数错)、401/403(KEY 问题)、 403 配额或能力不足——重试只会继续消耗额度。 429 relay_overloaded 与 quota_exceeded 都未进入生成流程、不产生费用。