Gemini 生图 API
用林易 Gemini 原生 v1beta 接口完成文生图、图片编辑与图生图,支持 HTTPS 参考图、1K / 2K / 4K、多画幅及 Base64 / URL 输入输出。
林易提供 Gemini 原生 v1beta 兼容接口,可直接调用 Gemini 图片模型完成文生图、图片编辑和图生图。
接口协议
Gemini 生图使用的是 Google Gemini 原生 generateContent 协议,不是 OpenAI 的 /v1/chat/completions,也不是 OpenAI Images 的 /v1/images/generations。
主端点:
POST https://linyiapi.ai/v1beta/models/{model}:generateContent1. 接口总览
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /v1beta/models | 查询 Gemini 原生模型目录及图片能力矩阵 |
GET | /v1beta/models/{model} | 查询指定模型、别名和 imageConfig 能力 |
POST | /v1beta/models/{model}:generateContent | 文生图、图片编辑、图生图主接口 |
POST | /v1beta/models/{model}:streamGenerateContent | SSE 流式响应;?alt=sse 为可选兼容参数 |
GET | /v1/models | 查询当前 Key 的 OpenAI 兼容模型列表,用于核对分组可路由模型 |
POST | /v1/images/batches | 林易 Gemini 异步批量生图扩展接口;需要系统及分组开关启用,详见Gemini 批量生图 API |
Base URL:
https://linyiapi.ai图片场景通常不需要流式端点
streamGenerateContent 带不带 ?alt=sse 都返回 SSE。图片二进制不会像文本一样逐步增量输出,因此图片生成通常优先使用非流式 generateContent。
2. 鉴权
推荐:Gemini 原生请求头
x-goog-api-key: YOUR_API_KEY兼容:Bearer 请求头
Authorization: Bearer YOUR_API_KEY服务端按以下优先级读取 API Key:
x-goog-api-key;Authorization: Bearer ...;x-api-key;/v1beta路径的?key=...查询参数。
不要把 Key 放进 URL
?api_key=... 已弃用并会返回 400。?key=... 虽然兼容,但容易被浏览器历史、反向代理和访问日志记录,生产环境请使用请求头。
典型鉴权错误:
{
"error": {
"code": 401,
"message": "Invalid API key",
"status": "UNAUTHENTICATED"
}
}API Key 必须绑定到 gemini 平台分组,否则不能调用 Gemini 原生接口。
3. 模型与可用性
Gemini 原生模型目录目前包含以下客户端模型 ID。模型是否能由某个 API Key 实际调用,还取决于该 Key 所在分组的模型配置:
| 模型 ID | 建议用途 | 图片编辑说明 |
|---|---|---|
gemini-3.1-flash-image | 默认推荐 | 已通过生产环境 inlineData 图片编辑实测 |
gemini-3.1-flash-image-preview | 预览兼容 | 使用同一 generateContent 编辑协议,正式接入前建议单独验证 |
gemini-3-pro-image | 质量优先 / 复杂编辑 | 使用同一 generateContent 编辑协议,以当前 Key 可用性为准 |
gemini-3-pro-image-preview | Pro 预览兼容 | 使用同一编辑协议,执行模型以服务端响应为准 |
gemini-3.1-flash-lite-image | 轻量场景(仅 1K) | 低延迟场景,以当前 Key 可用性为准 |
gemini-3.1-flash-lite-image-preview | Lite 预览兼容(仅 1K) | gemini-3.1-flash-lite-image 的预览别名 |
查询模型目录与当前 Key 可路由模型
curl 'https://linyiapi.ai/v1beta/models' \
-H 'x-goog-api-key: YOUR_API_KEY'响应中的 imageConfig.aspectRatios 和 imageConfig.imageSizes 是模型能力矩阵。-preview 别名还可能返回 aliasOf。
用于核对当前 Key 分组可路由模型的 OpenAI 兼容列表:
curl 'https://linyiapi.ai/v1/models' \
-H 'Authorization: Bearer YOUR_API_KEY'/v1beta/models 与 /v1/models 用途不同,返回集合可能不一致:前者提供 Gemini 原生目录和能力,后者反映当前 Key 在 OpenAI 兼容层可见的路由模型。最终能否调用仍以真实生成请求为准;未配置的模型会返回 404 NOT_FOUND。
查询单个模型能力:
curl 'https://linyiapi.ai/v1beta/models/gemini-3.1-flash-lite-image-preview' \
-H 'x-goog-api-key: YOUR_API_KEY'典型响应:
{
"name": "models/gemini-3.1-flash-lite-image-preview",
"baseModelId": "gemini-3.1-flash-lite-image-preview",
"displayName": "Gemini 3.1 Flash Lite Image",
"supportedGenerationMethods": ["generateContent", "streamGenerateContent"],
"imageConfig": {
"aspectRatios": ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"],
"imageSizes": ["1K"]
},
"aliasOf": "gemini-3.1-flash-lite-image"
}模型 ID 可能经过服务端映射
客户端提交的是请求模型 ID。林易支持兼容模型别名,因此请求模型名称不一定等于响应中的最终模型版本。
不要仅根据模型名称猜测是否可用:先用 /v1beta/models/{model} 查询能力,再用 /v1/models 核对当前 Key 的路由列表,并以真实生成请求的最终结果为准。
4. 快速开始:文生图
curl --request POST \
'https://linyiapi.ai/v1beta/models/gemini-3.1-flash-image:generateContent' \
--header 'x-goog-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "一只戴着宇航员头盔的橘猫,电影感灯光,精致细节"
}
]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}'默认使用 Base64 内联交付,成功后从下面的位置读取图片:
candidates[].content.parts[].inlineData.data2K / 4K 或高并发场景建议设置 generationConfig.responseDelivery: "uri",改从 fileData.fileUri 读取图片 URL。
5. 文生图请求结构
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "电影感雨夜城市街景,霓虹灯倒映在湿润路面,广角构图"
}
]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "16:9",
"imageSize": "2K"
}
}
}请求字段
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
contents | array | 是 | — | 对话内容数组,至少包含一条用户消息 |
contents[].role | string | 建议 | — | 用户输入使用 user |
contents[].parts | array | 是 | — | 文本或输入图片片段 |
parts[].text | string | 文生图必填 | — | 图片提示词或编辑指令 |
contents[].parts[].inlineData.data | string | 否 | — | 单张参考图与 fileData.fileUri 二选一;多参考图请求可混用两种方式 |
contents[].parts[].inlineData.mimeType | string | 否 | — | Base64 参考图类型:image/png、image/jpeg、image/webp |
contents[].parts[].fileData.fileUri | string | 否 | — | 参考图的公网 HTTPS 地址;单张参考图与 inlineData.data 二选一 |
contents[].parts[].fileData.mimeType | string | 否 | — | URL 参考图声明类型;推荐与实际图片类型一致 |
generationConfig | object | 否 | — | 生成参数;整体省略也能生图 |
generationConfig.responseModalities | string[] | 否 | 图片输出 | 图片端点会按图片模式处理,显式传入时推荐包含 IMAGE |
generationConfig.imageConfig | object | 否 | — | 图片分辨率和画幅配置 |
generationConfig.imageConfig.aspectRatio | string | 否 | 1:1 | 输出画幅,必须是目标模型支持的枚举 |
generationConfig.imageConfig.imageSize | string | 否 | 模型默认 | 大小写不敏感;Flash / Pro 支持 1K、2K、4K,Flash Lite 仅支持 1K |
generationConfig.responseDelivery | string | 否 | inline | inline 返回 Base64,uri 返回图片 URL |
参数层级要正确
画幅和分辨率必须放在 generationConfig.imageConfig;交付方式必须放在 generationConfig.responseDelivery。不要使用 responseFormat.image,也不要把 responseDelivery 放在请求体顶层;错误层级可能不会报错,但参数不会按预期生效。
6. 分辨率和画幅
支持的分辨率
imageSize | 推荐场景 | 模型支持情况 |
|---|---|---|
1K | 草图、快速预览、批量筛选 | Flash、Flash Lite、Pro |
2K | 常规交付、文章配图、电商素材 | Flash、Pro;Flash Lite 不支持 |
4K | 精细大图、高质量交付 | Flash、Pro;Flash Lite 不支持 |
imageSize 不区分大小写,1k、2k、4k 也能被服务归一化。推荐使用大写,以便与模型能力响应和示例保持一致:
{
"imageSize": "2K"
}imageSize 与 aspectRatio 一样都是模型级能力。gemini-3.1-flash-lite-image 及其 -preview 别名仅支持 1K;不要向 Lite 请求 2K 或 4K。
Flash / Pro 省略 imageSize 时当前默认使用 2K;Flash Lite 只支持 1K。为避免调用方误判费用或画质,生产请求建议显式传入,并先读取目标模型的 imageConfig.imageSizes。
支持的画面比例
aspectRatio 是模型级能力。仅 Flash 标准版支持四种超长画幅;Pro 与 Flash Lite 只支持通用比例。
通用 10 种比例:
1:1
2:3
3:2
3:4
4:3
4:5
5:4
9:16
16:9
21:9Flash 扩展 4 种比例:
1:4
1:8
4:1
8:1模型比例矩阵
| 客户端模型 ID | 确认支持的比例 | 数量 | imageSize |
|---|---|---|---|
gemini-3.1-flash-image | 通用 10 种 + Flash 扩展 4 种 | 14 | 1K / 2K / 4K |
gemini-3.1-flash-image-preview | 通用 10 种 + Flash 扩展 4 种 | 14 | 1K / 2K / 4K |
gemini-3.1-flash-lite-image | 仅通用 10 种 | 10 | 仅 1K |
gemini-3.1-flash-lite-image-preview | 仅通用 10 种 | 10 | 仅 1K |
gemini-3-pro-image | 仅通用 10 种 | 10 | 1K / 2K / 4K |
gemini-3-pro-image-preview | 仅通用 10 种 | 10 | 1K / 2K / 4K |
Pro 与 Flash Lite 不支持扩展比例
对 Pro 或 Flash Lite 模型及其 -preview 别名传入 1:4、1:8、4:1、8:1,会返回 INVALID_ARGUMENT、400,或在当前 Key 未配置该模型时返回 404 NOT_FOUND。例如:
{
"error": {
"code": 400,
"message": "generationConfig.imageConfig.aspectRatio has an unsupported value",
"status": "INVALID_ARGUMENT"
}
}Flash Lite 仅支持 1K
向 Flash Lite 或其 Preview 别名请求 2K / 4K 会被入口拒绝:
{
"error": {
"code": 400,
"message": "Image size '2K' is not supported. Supported: 1K",
"status": "INVALID_ARGUMENT"
}
}这是请求参数错误,不应重试。请改为 1K,或切换到支持 2K / 4K 的 Flash / Pro 模型。
上述矩阵以 Gemini 原生模型能力接口和实际请求校验为准。建议客户端启动时读取 /v1beta/models/{model} 的 imageConfig,不要长期硬编码比例与分辨率列表。未知或新模型在完成验证前,应使用通用 10 种。
不指定 aspectRatio 时,当前默认使用 1:1。不要传任意小数或任意 WIDTHxHEIGHT;必须使用目标模型接受的比例枚举。
示例(适用于支持 4K 的 Flash / Pro 模型):
{
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "9:16",
"imageSize": "4K"
}
}
}分辨率档位不是固定像素宽高
1K、2K、4K 是模型分辨率档位。图片的实际宽高由模型根据档位和画幅计算,客户端不应固定假设一定是 1024×1024、2048×2048 或 4096×4096。
7. 图片编辑 / 图生图
Gemini 支持图片编辑,只是没有类似 GPT 的独立 /v1/images/edits 端点。
文生图和图片编辑都调用:
POST /v1beta/models/{model}:generateContent两者的区别是:
| 场景 | contents[].parts[] 内容 |
|---|---|
| 文生图 | 只有文本提示词 |
| 图片编辑 / 图生图 | 文本编辑指令 + inlineData Base64 或 fileData.fileUri HTTPS 参考图 |
生产环境已验证
使用 gemini-3.1-flash-image,通过 Base64 和公网 HTTPS URL 两种方式提交参考图,均已成功返回:
- HTTP
200; finishReason: STOP;- 非空图片结果;
usageMetadata用量信息。
参考图输入使用 inlineData.data 或 fileData.fileUri;默认图片输出读取 inlineData.data,设置 generationConfig.responseDelivery: "uri" 后读取输出的 fileData.fileUri。当前图片服务通常返回 WebP,但客户端必须以每次响应的 mimeType 为准。响应可能只包含图片 part、不包含文本 part,客户端不能要求响应中必须同时存在文字。
7.1 最小图片编辑请求
{
"contents": [
{
"role": "user",
"parts": [
{
"text": "保留人物、构图和光线,把背景修改成雨夜霓虹街道"
},
{
"inlineData": {
"mimeType": "image/png",
"data": "INPUT_IMAGE_BASE64"
}
}
]
}
],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}7.2 Base64 参考图字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
contents[].parts[].text | string | 是 | 编辑指令,应明确哪些内容需要保留、哪些内容需要修改 |
inlineData.mimeType | string | 是 | 白名单:image/png、image/jpeg、image/webp |
inlineData.data | string | 是 | 推荐传裸 Base64;也兼容 data:image/...;base64, Data URL 前缀 |
imageConfig.aspectRatio | string | 否 | 输出画幅;需要保留输入比例时填写对应比例 |
imageConfig.imageSize | string | 否 | 输出档位,以模型能力为准;Flash Lite 及其 Preview 别名仅支持 1K |
推荐裸 Base64,也兼容 Data URL
推荐直接传不带前缀的裸 Base64:
/9j/4AAQSkZJRgABAQ...如果现有客户端生成的是 Data URL,服务也会自动处理:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...Base64 会增加请求体积。输入图片较大或并发较高时,建议改用下一节的 HTTPS URL 参考图。
7.3 使用 HTTPS URL 作为参考图
参考图已存放在自己的对象存储或 CDN 时,可以通过 fileData.fileUri 直接提交公网 HTTPS 图片地址,无需把图片编码进请求体。
下面的示例同时启用 URL 输出,实现参考图 URL 输入、生成图 URL 输出:
curl --request POST \
'https://linyiapi.ai/v1beta/models/gemini-3.1-flash-image:generateContent' \
--header 'x-goog-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "把背景改成星空,保留主体与构图,不要添加文字"
},
{
"fileData": {
"mimeType": "image/png",
"fileUri": "https://your-cdn.example.com/path/to/input.png"
}
}
]
}
],
"generationConfig": {
"responseDelivery": "uri",
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}'成功时,生成图 URL 位于:
candidates[].content.parts[].fileData.fileUri响应中的图片片段示例:
{
"fileData": {
"mimeType": "image/webp",
"fileUri": "https://IMAGE_HOST/path/to/generated-image.webp"
}
}URL 参考图限制
- 当前仅接受公网可达的 HTTPS URL,不要使用 HTTP、本机地址或内网地址;
- 单张图片最大
50 MB;最多跟随 3 次重定向;拉取总超时约 30 秒; - 支持的实际图片格式为 PNG、JPEG、WebP,服务会校验图片真实内容,不只依赖声明的
mimeType; - 图片源站必须允许服务端直接访问,不能依赖浏览器 Cookie、登录态或交互式验证;
- URL 被安全策略拒绝、源站返回非
200、图片过大或格式不支持时,接口返回400 INVALID_ARGUMENT,这类错误不应重试,应该先修正 URL 或源站访问策略。
典型的 400 错误信息包括:
image_url rejected: ...
Failed to fetch image_url: 403
image too large, max 50MBinlineData 与 fileData.fileUri 可以二选一,也可以在多参考图请求中混用;单次请求的参考图总数最多 6 张。
7.4 Base64 curl 完整示例
先把本地图片转换为不换行的 Base64:
IMAGE_BASE64=$(base64 < input.jpg | tr -d '\n')然后调用图片模型:
curl --request POST \
'https://linyiapi.ai/v1beta/models/gemini-3.1-flash-image:generateContent' \
--header 'x-goog-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw "{
\"contents\": [{
\"role\": \"user\",
\"parts\": [
{
\"text\": \"保留杯子、构图、光线和背景不变,只把杯子从蓝色改成紫色,并在杯身增加三个白色星形图案,不要添加文字\"
},
{
\"inlineData\": {
\"mimeType\": \"image/jpeg\",
\"data\": \"${IMAGE_BASE64}\"
}
}
]
}],
\"generationConfig\": {
\"responseModalities\": [\"TEXT\", \"IMAGE\"],
\"imageConfig\": {
\"aspectRatio\": \"3:2\",
\"imageSize\": \"1K\"
}
}
}"7.5 Python 图片编辑示例
import base64
import requests
api_key = "YOUR_API_KEY"
model = "gemini-3.1-flash-image"
input_path = "input.jpg"
with open(input_path, "rb") as f:
image_base64 = base64.b64encode(f.read()).decode("utf-8")
payload = {
"contents": [{
"role": "user",
"parts": [
{
"text": "保留主体和构图,把背景改成雨夜霓虹街道"
},
{
"inlineData": {
"mimeType": "image/jpeg",
"data": image_base64,
}
},
],
}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "3:2",
"imageSize": "1K",
},
},
}
response = requests.post(
f"https://linyiapi.ai/v1beta/models/{model}:generateContent",
headers={
"x-goog-api-key": api_key,
"Content-Type": "application/json",
},
json=payload,
timeout=300,
)
response.raise_for_status()
result = response.json()
saved = False
for candidate in result.get("candidates", []):
for part in candidate.get("content", {}).get("parts", []):
inline_data = part.get("inlineData", {})
if inline_data.get("data"):
mime_type = inline_data.get("mimeType", "image/png")
extension = "jpg" if "jpeg" in mime_type else "webp" if "webp" in mime_type else "png"
with open(f"gemini-edited.{extension}", "wb") as f:
f.write(base64.b64decode(inline_data["data"]))
saved = True
break
if saved:
break
if not saved:
raise RuntimeError("HTTP 请求成功,但响应中没有编辑后的图片")7.6 编辑提示词建议
图片编辑提示词最好明确区分“保留项”和“修改项”:
保留:主体身份、姿势、镜头角度、构图和光线。
修改:把背景改成雨夜霓虹街道。
禁止:不要增加文字,不要改变人物脸部。相比只写“把它改好看一些”,这种结构更容易获得稳定结果。
7.7 多张参考图
部分 Gemini 图片模型可以在同一个 parts[] 中接收多张 inlineData 或 fileData.fileUri 参考图,用于风格参考、人物参考或素材融合;两种输入方式可以混用。当前服务单次请求最多处理 6 张参考图;请不要超过该数量,避免多余图片被忽略。总请求体仍受网关大小限制,正式使用前应针对目标模型、图片尺寸和压缩方式单独验证。
不要仅因为 /v1beta/models 返回了某个图片模型,就假定它支持无限数量或无限大小的参考图。
8. 图片交付方式
实时生图和图片编辑支持两种响应交付方式。responseDelivery 是林易在 Gemini 兼容协议上的扩展字段。配合第 7.3 节的 fileData.fileUri URL 参考图输入,可实现 URL 输入、URL 输出,客户端请求和响应中都不需要携带图片 Base64:
responseDelivery | 图片字段 | 适用场景 |
|---|---|---|
inline | parts[].inlineData.data | 默认模式;直接获得 Base64,适合小图或必须内联处理的客户端 |
uri | parts[].fileData.fileUri | 推荐用于 2K / 4K 和高并发场景,避免大段 Base64 穿过网关 |
8.1 URL 交付(推荐大图使用)
responseDelivery 必须放在 generationConfig 内:
curl --request POST \
'https://linyiapi.ai/v1beta/models/gemini-3.1-flash-image:generateContent' \
--header 'x-goog-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"contents": [
{
"role": "user",
"parts": [{"text": "极简绿色方块,白色背景,无文字"}]
}
],
"generationConfig": {
"responseDelivery": "uri",
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}'成功响应中的图片片段:
{
"fileData": {
"mimeType": "image/webp",
"fileUri": "https://IMAGE_HOST/path/to/generated-image.webp"
}
}客户端从以下路径读取图片 URL:
candidates[].content.parts[].fileData.fileUri公开网关请使用请求体参数
请使用 generationConfig.responseDelivery: "uri"。不要把 responseDelivery 放在请求体顶层;顶层字段会被忽略。当前也不要依赖 x-image-delivery: uri 请求头,因为该请求头经过公开网关时可能不会稳定透传到图片服务。
图片 URL 的主机名和路径由服务端决定。客户端不要硬编码存储域名,也不要把 URL 当作永久存储凭证;如需长期保存,请在业务侧及时归档。
8.2 Base64 内联交付
省略 responseDelivery,或显式设置为 inline:
{
"generationConfig": {
"responseDelivery": "inline",
"imageConfig": {
"aspectRatio": "1:1",
"imageSize": "1K"
}
}
}图片数据路径:
candidates[].content.parts[].inlineData.dataBase64 会比原始二进制更大。对于 2K / 4K、图生图和高并发任务,优先使用 URI 交付可以明显降低客户端、网关和应用服务器的内存与网络开销。
9. 成功响应
典型响应:
{
"candidates": [
{
"content": {
"role": "model",
"parts": [
{
"text": "已根据要求生成图片。"
},
{
"inlineData": {
"mimeType": "image/webp",
"data": "BASE64_IMAGE_DATA"
}
}
]
},
"finishReason": "STOP",
"index": 0
}
],
"usageMetadata": {
"promptTokenCount": 15,
"candidatesTokenCount": 0,
"totalTokenCount": 15,
"creditsConsumed": 20
},
"modelVersion": "gemini-3.1-flash-image",
"createTime": 1780000000,
"responseId": "RESPONSE_ID"
}关键响应字段
| 字段 | 说明 |
|---|---|
candidates[] | 候选输出列表 |
candidates[].content.parts[] | 文本或图片片段 |
parts[].inlineData.mimeType | 返回图片 MIME 类型 |
parts[].inlineData.data | inline 模式返回的图片 Base64 内容 |
parts[].fileData.mimeType | uri 模式返回的图片 MIME 类型 |
parts[].fileData.fileUri | uri 模式返回的图片 URL |
candidates[].finishReason | 结束原因;常见成功值为 STOP |
usageMetadata.promptTokenCount | 输入 Token 数 |
usageMetadata.totalTokenCount | 请求 Token 汇总 |
usageMetadata.creditsConsumed | 本次请求返回的 credits 消耗值 |
modelVersion | 服务实际执行的模型版本 |
createTime | 服务端创建时间 |
responseId | 响应标识;报障时建议一并提供 |
正确判断生图成功
客户端应同时检查:
- HTTP 状态码为
2xx; candidates非空;- 至少一个
parts[]含有非空inlineData.data或fileData.fileUri; inline模式下 Base64 能成功解码,uri模式下 URL 格式合法;- 必要时检查
finishReason。
HTTP 200 不等于一定生成了图片
服务可能返回 HTTP 200,但响应中既没有 inlineData.data,也没有 fileData.fileUri。这类请求必须按“业务生图失败”处理,不能计入成功图片数。
10. Node.js 示例
import { writeFile } from 'node:fs/promises';
const BASE_URL = process.env.GEMINI_BASE_URL || 'https://linyiapi.ai';
const API_KEY = process.env.GEMINI_API_KEY;
const MODEL = 'gemini-3.1-flash-image';
if (!API_KEY) throw new Error('缺少 GEMINI_API_KEY');
const payload = {
contents: [
{
role: 'user',
parts: [
{ text: '日落时分的海边灯塔,水彩插画,温暖色调,细腻纸张纹理' },
],
},
],
generationConfig: {
responseDelivery: 'uri',
responseModalities: ['TEXT', 'IMAGE'],
imageConfig: {
aspectRatio: '16:9',
imageSize: '2K',
},
},
};
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 300_000);
try {
const response = await fetch(
`${BASE_URL}/v1beta/models/${encodeURIComponent(MODEL)}:generateContent`,
{
method: 'POST',
headers: {
'x-goog-api-key': API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
signal: controller.signal,
},
);
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
throw new Error(`服务返回非 JSON 内容:HTTP ${response.status}`);
}
if (!response.ok) {
throw new Error(
`HTTP ${response.status}: ${data?.error?.message || JSON.stringify(data)}`,
);
}
const parts = data.candidates?.flatMap((candidate) => candidate.content?.parts || []) || [];
const imagePart = parts.find((part) => part.inlineData?.data || part.fileData?.fileUri);
if (!imagePart) {
const reasons = data.candidates?.map((candidate) => candidate.finishReason).filter(Boolean);
throw new Error(`请求完成但没有图片,finishReason=${reasons?.join(',') || 'unknown'}`);
}
if (imagePart.fileData?.fileUri) {
console.log('图片 URL:', imagePart.fileData.fileUri);
} else {
const mimeType = imagePart.inlineData.mimeType || 'application/octet-stream';
const extension = mimeType === 'image/jpeg'
? 'jpg'
: mimeType === 'image/webp'
? 'webp'
: 'png';
await writeFile(
`gemini-output.${extension}`,
Buffer.from(imagePart.inlineData.data, 'base64'),
);
console.log(`图片已保存为 gemini-output.${extension}`);
}
console.log('responseId:', data.responseId || null);
console.log('usageMetadata:', data.usageMetadata || null);
} finally {
clearTimeout(timer);
}11. Python 示例
import base64
import os
from pathlib import Path
import requests
BASE_URL = os.getenv("GEMINI_BASE_URL", "https://linyiapi.ai")
API_KEY = os.environ["GEMINI_API_KEY"]
MODEL = "gemini-3.1-flash-image"
payload = {
"contents": [
{
"role": "user",
"parts": [
{"text": "未来主义建筑群,清晨薄雾,超广角摄影,真实材质"}
],
}
],
"generationConfig": {
"responseDelivery": "uri",
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {
"aspectRatio": "16:9",
"imageSize": "2K",
},
},
}
response = requests.post(
f"{BASE_URL}/v1beta/models/{MODEL}:generateContent",
headers={
"x-goog-api-key": API_KEY,
"Content-Type": "application/json",
},
json=payload,
timeout=300,
)
data = response.json()
if not response.ok:
message = data.get("error", {}).get("message", data)
raise RuntimeError(f"HTTP {response.status_code}: {message}")
image_part = None
for candidate in data.get("candidates", []):
for part in candidate.get("content", {}).get("parts", []):
if part.get("inlineData", {}).get("data") or part.get("fileData", {}).get("fileUri"):
image_part = part
break
if image_part:
break
if not image_part:
reasons = [candidate.get("finishReason") for candidate in data.get("candidates", [])]
raise RuntimeError(f"请求完成但没有返回图片,finishReason={reasons}")
file_uri = image_part.get("fileData", {}).get("fileUri")
if file_uri:
print("图片 URL:", file_uri)
else:
inline_data = image_part["inlineData"]
mime_type = inline_data.get("mimeType", "application/octet-stream")
extension = {
"image/jpeg": "jpg",
"image/webp": "webp",
}.get(mime_type, "png")
Path(f"gemini-output.{extension}").write_bytes(
base64.b64decode(inline_data["data"])
)
print(f"图片已保存为 gemini-output.{extension}")
print("responseId:", data.get("responseId"))
print("usageMetadata:", data.get("usageMetadata"))12. 常见错误
Gemini 原生端点通常返回 Google 风格错误:
{
"error": {
"code": 429,
"message": "service rate limit exceeded",
"status": "RESOURCE_EXHAUSTED"
}
}| HTTP 状态 | 常见原因 | 建议 |
|---|---|---|
400 | 请求结构、画幅、分辨率、参考图 URL 或图片格式错误 | 按错误信息修正请求,不要直接重试 |
401 | API Key 缺失、无效或禁用 | 检查 Key 和请求头 |
402 / 403 | 余额、订阅、计费资格或权限不足 | 检查账户和分组权限 |
404 | 模型不存在,或当前 Key 分组未配置该模型 | 对照 /v1/models 与 /v1beta/models/{model} 检查模型 ID |
413 | 图生图请求体过大 | 压缩输入图片,或改用已开放的 URL 输入能力 |
429 | 用户并发限制或服务限流 | 优先遵循 Retry-After,否则指数退避并降低并发 / RPM |
500 | 服务内部错误 | 记录错误码和请求 ID,有限重试 |
502 | 请求转发失败或服务暂时不可用 | 退避重试,必要时联系管理员 |
503 | 服务容量暂时不足或过载 | 延迟重试并降低流量 |
504 | 请求处理超时 | 作为独立请求重新发起 |
遇到容量或暂时不可用错误时,请停止密集重试,并将 HTTP 状态、错误码、responseId 或请求 ID 提供给管理员。
13. 超时、重试和并发
客户端超时建议
| 分辨率 | 建议总超时 |
|---|---|
1K | 不低于 120 秒 |
2K | 不低于 180 秒 |
4K | 建议 300 秒 |
这只是接入建议,不代表固定 SLA。若请求还经过自有 Nginx、CDN 或 API 网关,需要同步调整这些组件的读取超时。
近期链路实测可作为前端交互设计参考,但不能视为 SLA:
| 场景 | 实测参考 |
|---|---|
Flash Lite 1K 单张 | 约 5~8 秒 |
Flash 1K 单张 | 约 8~16 秒 |
Pro 4K 单张 | 约 44 秒 |
并发 16、Flash 1K | p50 约 17.3 秒,p95 约 18.8 秒 |
容量繁忙时请求可能先进入队列,当前默认排队上限约为 90 秒。客户端总超时应覆盖“排队时间 + 生成耗时”,可按下面的方式估算:
客户端超时 ≥ 最大排队时间 + 对应分辨率的 p95 生成耗时 + 网络余量重试建议
建议重试:
429;如果响应包含Retry-After,优先按该响应头等待;502、503、504;- 网络中断、连接重置和读取超时;
- HTTP
200但没有图片时,可有限重试一次并保存原始响应。
通常不要重试:
400;401;- 明确的余额或权限错误;
- 请求参数或内容策略错误。
推荐最多重试 2~3 次,并使用指数退避:
第 1 次:1~2 秒随机抖动
第 2 次:3~5 秒随机抖动
第 3 次:8~12 秒随机抖动多张实时图片
实时接口当前按“一次请求一张主要图片”使用。需要多张时应拆成多个独立请求,并同时限制:
- 最大在途并发;
- 每分钟请求数(RPM);
- 单用户任务数;
- 超时与最大重试次数。
如果需要提交几十到数百条提示词并异步等待结果,请使用Gemini 批量生图 API。
14. 用量与计费
响应中的 usageMetadata 可用于分析 Token 和本次请求的 credits 消耗,但不一定等于最终货币扣费金额。当前图片响应可能包含 promptTokenCount、candidatesTokenCount、totalTokenCount 和 creditsConsumed;客户端不应假设一定存在 candidatesTokensDetails。
实际扣费可能受以下因素影响:
- 请求模型 ID 与实际映射模型;
1K、2K、4K图片档位;- 分组图片单价;
- 用户分组倍率和平台计费配置;
- 部署环境中的计费规则。
最终金额请以林易控制台的用量明细和账户余额变化为准。
进行质量或并发测试时,建议记录:
- 测试前余额;
- 测试后余额;
- 成功请求数;
- 实际返回图片数;
- 模型、分辨率和画幅;
- 余额差额;
- 单张成功图片平均成本。
用量记录可能异步落账,测试结束后可等待一段时间再核对最终金额。
15. 安全建议
- API Key 只保存在服务端环境变量或密钥管理系统;
- 不要在浏览器前端、移动端安装包或公开代码仓库中写入 Key;
- 日志不要打印完整 API Key 和完整图片 Base64;
- 校验输入图片 MIME 类型、文件大小和 Base64 合法性;
- URL 参考图只使用公网 HTTPS 地址;如 URL 包含访问签名,应限制签名权限和有效期;
- 保存响应时根据
inlineData.mimeType或fileData.mimeType选择扩展名,不要默认按 PNG 保存; - 使用 URI 交付时不要硬编码对象存储域名,并按业务需要及时归档图片;
- 为每个业务请求记录自己的 trace ID、请求时间、模型、分辨率和 HTTP 状态;
- 超时后不要在极短时间内重复创建大量相同请求。
16. 接入验收清单
- 能区分
/v1beta/models的 Gemini 能力目录和/v1/models的当前 Key 路由模型列表; - 能使用
x-goog-api-key或 Bearer 请求头鉴权; - 能完成一张
1K / 1:1文生图; - 能完成 Flash / Pro 的
2K和4K文生图; - 对 Flash Lite 仅提交
1K,不会发送2K/4K; - 能完成至少一次 Base64 参考图的图片编辑 / 图生图;
- 能使用
fileData.fileUri提交公网 HTTPS 参考图; - URL 参考图与
responseDelivery: "uri"组合时,可以实现 URL 输入、URL 输出; - 内网、本机、不可访问或非图片 URL 会被识别为
400参数错误; - 多参考图请求不超过 6 张,并限制 Base64 请求体或 URL 源文件大小;
- 能识别
inlineData.data与fileData.fileUri两种图片交付形式; - 能根据响应
mimeType保存 WebP / JPEG / PNG,不硬编码扩展名; - 能把 HTTP 200 但既没有 Base64 也没有图片 URL 的情况标记为失败;
- 日志记录
responseId,便于问题排查; - 已设置图片请求超时;
- 已对 429 和 5xx 实现有限次数指数退避;
- 已确认价格、余额、并发和 RPM;
- 日志不会泄露 API Key 或完整 Base64。
下一步
- 大量提示词异步生成:Gemini 批量生图 API
- 查询当前 Key 可用模型:模型广场
- 协议和 Base URL 说明:接入协议
- 查询请求用量:导出 Usage 使用明细
开通林易 API,立即用上 Claude / Codex 等主流 AI 工具
零门槛注册、套餐灵活、国内直连。支持 Claude Code、Codex CLI、Cursor、VS Code 插件、OpenCode、Cherry Studio 等工具接入。
前往注册