接口
OpenAI 兼容接口
用 OpenAI 的 SDK 发图片、语音请求;每个请求创建一个任务,并立即返回。
按 OpenAI 图片、语音接口写的请求可以直接发到这里:把接口地址换成 https://janvia.io/v1,密钥换成这里的 API 密钥。model 要填这里的模型 ID,见 模型。
和 OpenAI 不同,这些接口不会一直等到结果出来。每个请求都会创建一个普通的 任务,并立即返回任务对象。之后用 GET /v1/tasks/TASK_ID 查询结果;也可以传 callback_url,任务结束时我们把任务 POST 给你(见 回调通知)。路由、计费、失败退款都和任务接口一样。
支持三个接口:
POST /v1/images/generations:文生图,JSON。POST /v1/images/edits:改图、参考图生图,multipart,图片放在image或image[]。POST /v1/audio/speech:语音合成,JSON。
视频请用 任务接口。OpenAI 自己的视频接口已经停用,这里不提供。
提交,再查结果
curl https://janvia.io/v1/images/generations \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "a red fox in the snow",
"size": "1536x1024",
"callback_url": "https://example.com/hooks/relay"
}'返回 HTTP 200 和任务对象,状态一般是 queued。X-Relay-Task-Id 和 Location 两个 Header 也指向这个任务:
{
"id": "task_9f2c...",
"object": "task",
"model": "gpt-image-2",
"status": "queued",
"output": null,
"cost_usd": 0.06,
...
}反复查询,直到 status 变成 completed 或 failed,生成的文件在 output.files[].url:
curl https://janvia.io/v1/tasks/task_9f2c... \ -H "Authorization: Bearer $API_KEY"
Python
SDK 调用返回的是任务,不是 OpenAI 的 data 列表。这里自己的字段(如 callback_url、route)放在 extra_body 里。
import time
import httpx
from openai import OpenAI
client = OpenAI(base_url="https://janvia.io/v1", api_key="sk_xxx")
task = client.images.generate(
model="gpt-image-2",
prompt="a red fox in the snow",
size="1536x1024",
# extra_body={"callback_url": "https://example.com/hooks/relay"},
).to_dict()
while task["status"] not in ("completed", "failed"):
time.sleep(3)
task = client.get(f"/tasks/{task['id']}", cast_to=httpx.Response).json()
if task["status"] == "completed":
print(task["output"]["files"][0]["url"])
else:
print(task["error"])改图也一样:client.images.edit(model=..., image=[open("product.png", "rb")], prompt=...) 返回任务。client.audio.speech.create(...) 也返回任务,用 .json() 读取;任务完成后,音频在 output.files[0].url。
Node.js
import OpenAI from 'openai';
const client = new OpenAI({ baseURL: 'https://janvia.io/v1', apiKey: 'sk_xxx' });
let task = await client.images.generate({
model: 'gpt-image-2',
prompt: 'a red fox in the snow',
size: '1536x1024',
// callback_url: 'https://example.com/hooks/relay',
});
while (!['completed', 'failed'].includes(task.status)) {
await new Promise((resolve) => setTimeout(resolve, 3000));
task = await client.get(`/tasks/${task.id}`);
}
console.log(task.output?.files[0].url ?? task.error);在 TypeScript 里,SDK 会把返回值标成 OpenAI 的响应类型,请转成你自己的任务类型。client.audio.speech.create(...) 返回 Response,用 await response.json() 读取任务。
参数对应
图片:
size:1024x1536这类宽高,换算成最接近的aspect_ratio,分辨率按长边算:1536 以内为 1K,2560 以内为 2K,更大为 4K。auto或不传,用模型默认值。n:生成几张,1–4。quality:low、medium、high、auto原样使用;standard当作medium;hd、xhigh、max当作high。output_format:png、jpeg或webp。response_format:只支持url。结果是任务上的文件,传b64_json会返回 400。- 不支持、会返回 400:
background: "transparent"、mask、stream。 - 其他 OpenAI 参数会被忽略。
也可以直接带上这里自己的字段,它们优先于换算结果:resolution、aspect_ratio、negative_prompt、seed、image_urls、route(见 线路与路由)、callback_url。
语音:
input是要朗读的文本,voice是音色 ID(字符串,或{ "id": ... })。response_format:音频文件的格式,mp3(默认)或wav。speed:0.5–2。- 不支持
stream_format: "sse";instructions会被忽略。
报错和重试
提交时出错(参数不对、余额不足等)返回 4xx,不创建任务,也不扣费。任务之后失败的,费用全额退回,任务上写明错误码。
SDK 遇到超时、网络错误和 5xx 会自动重试。带上 Idempotency-Key,重试就会拿回同一个任务,不会再付一次钱:
client.images.generate(
model="gpt-image-2",
prompt="a red fox in the snow",
extra_headers={"Idempotency-Key": "order-123"},
)await client.images.generate(
{ model: 'gpt-image-2', prompt: 'a red fox in the snow' },
{ headers: { 'Idempotency-Key': 'order-123' } }
);