生成图片(Gemini 原生,SSE 流式)
curl --request POST \
--url https://api.hairoute.ai/v1/models/{model}:streamGenerateContent \
--header 'Content-Type: application/json' \
--header 'x-goog-api-key: <x-goog-api-key>' \
--data '
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "画一只橘猫"
}
]
}
],
"generationConfig": {
"responseModalities": [
"TEXT",
"IMAGE"
],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
'import requests
url = "https://api.hairoute.ai/v1/models/{model}:streamGenerateContent"
payload = {
"contents": [
{
"role": "user",
"parts": [{ "text": "画一只橘猫" }]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
headers = {
"x-goog-api-key": "<x-goog-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-goog-api-key': '<x-goog-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [{role: 'user', parts: [{text: '画一只橘猫'}]}],
generationConfig: {
responseModalities: ['TEXT', 'IMAGE'],
imageConfig: {aspectRatio: '1:1', imageSize: '1K'}
}
})
};
fetch('https://api.hairoute.ai/v1/models/{model}:streamGenerateContent', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hairoute.ai/v1/models/{model}:streamGenerateContent",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'contents' => [
[
'role' => 'user',
'parts' => [
[
'text' => '画一只橘猫'
]
]
]
],
'generationConfig' => [
'responseModalities' => [
'TEXT',
'IMAGE'
],
'imageConfig' => [
'aspectRatio' => '1:1',
'imageSize' => '1K'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-goog-api-key: <x-goog-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hairoute.ai/v1/models/{model}:streamGenerateContent"
payload := strings.NewReader("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"画一只橘猫\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-goog-api-key", "<x-goog-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hairoute.ai/v1/models/{model}:streamGenerateContent")
.header("x-goog-api-key", "<x-goog-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"画一只橘猫\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hairoute.ai/v1/models/{model}:streamGenerateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-goog-api-key"] = '<x-goog-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"画一只橘猫\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}"
response = http.request(request)
puts response.read_body"data: {\"candidates\":[{\"content\":{\"role\":\"model\",\"parts\":[{\"inlineData\":{\"mimeType\":\"image/png\",\"data\":\"<BASE64_IMAGE_DATA>\"}}]},\"finishReason\":\"STOP\"}],\"usageMetadata\":{\"totalTokenCount\":1302}}\n\n"{
"error": {
"code": 123,
"message": "<string>",
"status": "<string>"
}
}Gemini 原生图片生成(流式)
使用 Gemini 原生 streamGenerateContent 接口以 SSE 流式接收图片结果,仅适用于 Google/Gemini 图片模型
POST
/
v1
/
models
/
{model}
:streamGenerateContent
生成图片(Gemini 原生,SSE 流式)
curl --request POST \
--url https://api.hairoute.ai/v1/models/{model}:streamGenerateContent \
--header 'Content-Type: application/json' \
--header 'x-goog-api-key: <x-goog-api-key>' \
--data '
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "画一只橘猫"
}
]
}
],
"generationConfig": {
"responseModalities": [
"TEXT",
"IMAGE"
],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
'import requests
url = "https://api.hairoute.ai/v1/models/{model}:streamGenerateContent"
payload = {
"contents": [
{
"role": "user",
"parts": [{ "text": "画一只橘猫" }]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}
headers = {
"x-goog-api-key": "<x-goog-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-goog-api-key': '<x-goog-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [{role: 'user', parts: [{text: '画一只橘猫'}]}],
generationConfig: {
responseModalities: ['TEXT', 'IMAGE'],
imageConfig: {aspectRatio: '1:1', imageSize: '1K'}
}
})
};
fetch('https://api.hairoute.ai/v1/models/{model}:streamGenerateContent', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hairoute.ai/v1/models/{model}:streamGenerateContent",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'contents' => [
[
'role' => 'user',
'parts' => [
[
'text' => '画一只橘猫'
]
]
]
],
'generationConfig' => [
'responseModalities' => [
'TEXT',
'IMAGE'
],
'imageConfig' => [
'aspectRatio' => '1:1',
'imageSize' => '1K'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-goog-api-key: <x-goog-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hairoute.ai/v1/models/{model}:streamGenerateContent"
payload := strings.NewReader("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"画一只橘猫\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-goog-api-key", "<x-goog-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hairoute.ai/v1/models/{model}:streamGenerateContent")
.header("x-goog-api-key", "<x-goog-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"画一只橘猫\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hairoute.ai/v1/models/{model}:streamGenerateContent")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-goog-api-key"] = '<x-goog-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"画一只橘猫\"\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseModalities\": [\n \"TEXT\",\n \"IMAGE\"\n ],\n \"imageConfig\": {\n \"aspectRatio\": \"1:1\",\n \"imageSize\": \"1K\"\n }\n }\n}"
response = http.request(request)
puts response.read_body"data: {\"candidates\":[{\"content\":{\"role\":\"model\",\"parts\":[{\"inlineData\":{\"mimeType\":\"image/png\",\"data\":\"<BASE64_IMAGE_DATA>\"}}]},\"finishReason\":\"STOP\"}],\"usageMetadata\":{\"totalTokenCount\":1302}}\n\n"{
"error": {
"code": 123,
"message": "<string>",
"status": "<string>"
}
}使用 Gemini 原生
实际调用时不要手写或裁剪上一轮的
逐个解析 SSE
streamGenerateContent 按块接收生成结果。在图片模型中,此端点仅供 Google/Gemini 图片模型使用;其他图片模型请使用其相应的 OpenAI 图片接口。Gemini 聊天模型的原生流式调用不属于本图片接口文档的范围。
功能特性
- 使用 Gemini 原生
streamGenerateContent端点,按 SSE 数据块接收图片生成结果 - 请求体结构与非流式接口相同,支持文生图、单图编辑、多图参考合成和多轮继续编辑
- 可通过
generationConfig.responseModalities与generationConfig.imageConfig配置图片输出;不需要stream: true - 在
candidates[].content.parts[]中接收文本和 Base64 图片,而不是 OpenAI 图片 URL 或命名事件
认证方式
POST https://api.hairoute.ai/v1/models/{model}:streamGenerateContent
{model} 是 模型列表 中可用的 Google/Gemini 图片模型名,不放在请求体中。使用 HaiRoute API Key,通过 x-goog-api-key: YOUR_API_KEY 或 Authorization: Bearer YOUR_API_KEY 认证。请求体可传 contents、generationConfig.responseModalities 和 generationConfig.imageConfig;该路由始终返回 text/event-stream。
支持的图片模型
此端点仅用于 Google/Gemini 图片模型。| 模型标识 | 模型类型 | 模型描述 |
|---|---|---|
gemini-3.1-flash-lite-image | 图片生成与编辑 | Gemini 3.1 Flash Lite Image;配置的输出档位为 1K。 |
gemini-3.1-flash-image | 图片生成与编辑 | Gemini 3.1 Flash Image;配置的输出档位为 512(约 0.5K)、1K、2K、4K。 |
gemini-3-pro-image | 图片生成与编辑 | Gemini 3 Pro Image;配置的输出档位为 1K、2K、4K。 |
快速示例
curl -N -X POST 'https://api.hairoute.ai/v1/models/YOUR_GEMINI_IMAGE_MODEL:streamGenerateContent' \
-H 'x-goog-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
-d '{
"contents": [{"role": "user", "parts": [{"text": "画一只在月球上行走的橘猫"}]}],
"generationConfig": {"responseModalities": ["TEXT", "IMAGE"]}
}'
生成方式
以下示例只展示请求体;四种方式都使用本页同一个端点与认证方式,不需要新增mode 参数。图片 Base64 均为占位符,需替换为真实图片的纯 Base64 数据。
文生图
只传文本提示词,不传输入图片;可直接使用上面的快速示例。局部修改、风格转换等是提示词要求,不是独立的接口参数。单图编辑
在同一条user 消息中传入一张图片和编辑指令。下面是更换背景的例子;也可以在文本中要求保留主体、修改局部元素或调整风格。
{
"contents": [{"role": "user", "parts": [
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_INPUT_IMAGE>"}},
{"text": "将背景改为日落海滩,保留主体"}
]}],
"generationConfig": {"responseModalities": ["TEXT", "IMAGE"]}
}
多图参考合成
将多张参考图放入同一条user 消息的 parts,用文本说明各图的用途。图片数量、尺寸及实际效果取决于所选模型和渠道的限制。
{
"contents": [{"role": "user", "parts": [
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_SUBJECT_IMAGE>"}},
{"inlineData": {"mimeType": "image/jpeg", "data": "<BASE64_BACKGROUND_IMAGE>"}},
{"text": "以第一张图的人物为主体,使用第二张图的场景作为背景,生成一张自然的合照"}
]}],
"generationConfig": {"responseModalities": ["TEXT", "IMAGE"]}
}
多轮继续编辑
把前一轮的user 请求、实际返回的 candidates[0].content(作为 model 消息)和本轮的新指令依次放进 contents。下面仅示意结构:
{
"contents": [
{"role": "user", "parts": [{"text": "画一只戴围巾的橘猫"}]},
{"role": "model", "parts": [
{"inlineData": {"mimeType": "image/png", "data": "<BASE64_FROM_PREVIOUS_RESPONSE>"}}
]},
{"role": "user", "parts": [{"text": "保持橘猫与围巾不变,把背景换成雪地"}]}
],
"generationConfig": {"responseModalities": ["TEXT", "IMAGE"]}
}
model 内容;如果上一轮是流式响应,先按顺序汇总各 data: 块中同一候选的 content.parts,再将完整内容作为 model 消息回传,保留图片、文本及 thoughtSignature(如果返回)。不能只使用最后一个 SSE 块。多轮编辑和多图参考的效果取决于所选图片模型。
流式响应
服务端按 SSE 格式输出,每个data: 行是一个完整的 Gemini GenerateContentResponse JSON 块;以下为示意,Base64 是占位值:
data: {"candidates":[{"content":{"role":"model","parts":[{"text":"正在生成图片"}]}}]}
data: {"candidates":[{"content":{"role":"model","parts":[{"inlineData":{"mimeType":"image/png","data":"<BASE64_IMAGE_DATA>"}}]},"finishReason":"STOP"}],"usageMetadata":{"totalTokenCount":1302}}
data,检查 candidates[].content.parts[]:text 为文本,inlineData.data 为 Base64 图片,inlineData.mimeType 表示图片格式。块可能只包含部分字段;用量通常在后续块出现。此流没有 OpenAI 格式的命名事件和 [DONE] 标记,不要将 Base64 片段或单个块当作图片 URL。
常见错误排查
先检查 HTTP 状态及返回体中的error;流式请求还需检查已收到的每个 SSE data: 块。不要在日志或求助信息中贴出 API Key、完整图片 Base64。
| 现象 | 排查方法 |
|---|---|
| 认证失败(如 401/403) | 确认使用 HaiRoute API Key,并通过 x-goog-api-key 或 Authorization: Bearer 传入;不要把 Google API Key 填在这里。检查 Key 是否有效、是否有模型访问权限。 |
| 模型找不到或不可用 | 检查 URL 中的 {model} 是否为当前账户 模型列表 中可用的 Google/Gemini 图片模型;不要把模型名放在请求体里,也不要用其他图片模型调用此端点。 |
| 请求参数或输入图片报错 | 核对 contents[].parts、generationConfig.responseModalities(图片输出为 ["TEXT", "IMAGE"])和所选模型支持的 imageConfig;inlineData.data 必须是纯 Base64,不含 data:image/...;base64, 前缀,mimeType 要与输入图片格式一致。 |
| 响应成功但没找到图片 | 逐个检查 candidates[].content.parts[].inlineData;图片不在 data[].url。若没有图片,检查返回的 finishReason、promptFeedback 和文本内容,再调整提示词或请求配置;不要把 HTTP 200 等同于已出图。 |
| 流式没有图片或解析失败 | 以空行分隔 SSE 事件,逐条解析 data: 后面的 JSON;图片可能在任意块的 candidates[].content.parts[].inlineData,不能只读取最后一块。本端点没有 OpenAI 命名事件或 [DONE]。若连接中途断开,不能仅凭已收到的文本或用量判断出图成功。 |
| 多轮编辑失败或没有延续上轮 | 按顺序回传先前的 user 消息、上一轮完整的 candidates[0].content(包括 thoughtSignature,如果返回)以及新的 user 指令;不要只回传图片 Base64。 |
下一步
请求头
HaiRoute API Key。此处展示原生请求头;也可改用 Authorization: Bearer YOUR_API_KEY 认证(二选一)。
路径参数
HaiRoute 可用的 Google/Gemini 图片模型名称
请求体
application/json
响应
SSE 数据流:每个 data 帧为一个 Gemini GenerateContentResponse JSON 块,无命名事件或 [DONE]。
The response is of type string.