OpenRouter 调用 Gemini Flash Image 生成图片
问题
网上很多教程的请求格式都是错的,aspect_ratio 参数不生效,始终生成 1:1 的图片。
正确的请求格式
TypeScript 类型定义
typescript
1234567891011121314
interface OpenRouterImageRequest {
model: string;
modalities: string[];
messages: Array<{
role: string;
content: Array<{
type: string;
text?: string;
}>;
}>;
image_config: {
aspect_ratio: '16:9' | '3:2' | '4:3' | '1:1';
};
}
完整代码
typescript
123456789101112131415161718192021222324252627282930313233343536
async function generateImage(prompt: string, ratio: string = '16:9') {
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
'X-Title': 'My App', // 可选
},
body: JSON.stringify({
model: 'google/gemini-2.5-flash-image-preview',
modalities: ['text', 'image'],
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: prompt,
},
],
},
],
image_config: {
aspect_ratio: ratio,
},
}),
});
const data = await response.json();
// 提取 base64 图片
const imageUrl = data.choices[0].message.images[0].image_url.url;
const base64Match = imageUrl.match(/data:image\/\w+;base64,(.+)/);
return base64Match[1];
}
保存图片
typescript
12345678
import sharp from 'sharp';
const base64 = await generateImage('一只可爱的机器人', '16:9');
const buffer = Buffer.from(base64, 'base64');
await sharp(buffer)
.webp({ quality: 85 })
.toFile('./output.webp');
关键点
1. 请求格式的 3 个要点
typescript
123456789101112131415161718
// ✅ 正确
{
modalities: ['text', 'image'], // 必须有
messages: [{
content: [{ type: 'text', ... }] // content 必须是数组
}],
image_config: { // 嵌套在这里
aspect_ratio: '16:9'
}
}
// ❌ 错误
{
messages: [{
content: '文本' // 错误: 不是数组
}],
aspect_ratio: '16:9' // 错误: 位置不对
}
2. 响应结构
typescript
12345678910111213141516171819
// 响应格式
{
choices: [{
message: {
images: [{
type: 'image_url',
image_url: {
url: 'data:image/png;base64,...' // 这里是图片
}
}]
}
}]
}
// 正确提取
const imageUrl = data.choices[0].message.images[0].image_url.url;
// ❌ 错误: images 不是字符串数组
const imageUrl = data.choices[0].message.images[0]; // 这是对象!
3. 支持的宽高比
-
16:9- 横版 (1344x768) -
3:2- 横版 (1344x896) -
4:3- 横版 (1344x1008) -
1:1- 方形 (1024x1024) -
9:16- 竖版 (768x1344)
完整示例
typescript
1234567891011121314151617181920212223242526272829303132333435363738394041
import sharp from 'sharp';
async function generateAndSave(prompt: string, outputPath: string) {
// 1. 调用 API
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
},
body: JSON.stringify({
model: 'google/gemini-2.5-flash-image-preview',
modalities: ['text', 'image'],
messages: [{
role: 'user',
content: [{ type: 'text', text: prompt }],
}],
image_config: {
aspect_ratio: '16:9',
},
}),
});
if (!response.ok) {
throw new Error(`API 错误: ${response.status}`);
}
// 2. 提取 base64
const data = await response.json();
const imageUrl = data.choices[0].message.images[0].image_url.url;
const base64 = imageUrl.match(/data:image\/\w+;base64,(.+)/)[1];
// 3. 保存文件
const buffer = Buffer.from(base64, 'base64');
await sharp(buffer).webp({ quality: 85 }).toFile(outputPath);
console.log('✅ 图片已保存:', outputPath);
}
// 使用
await generateAndSave('一只机器人在写代码', './robot.webp');
常见错误
错误 1: content 不是数组
typescript
1234567891011
// ❌ 错误
messages: [{
role: 'user',
content: '生成图片'
}]
// ✅ 正确
messages: [{
role: 'user',
content: [{ type: 'text', text: '生成图片' }]
}]
错误 2: aspect_ratio 位置错误
typescript
123456789101112131415
// ❌ 错误
{
model: '...',
messages: [...],
aspect_ratio: '16:9' // 无效!
}
// ✅ 正确
{
model: '...',
messages: [...],
image_config: {
aspect_ratio: '16:9' // 在这里!
}
}
错误 3: 响应解析错误
typescript
1234567
// ❌ 错误
const imageUrl = data.choices[0].message.images[0];
if (imageUrl.startsWith('data:image')) { ... } // TypeError!
// ✅ 正确
const imageUrl = data.choices[0].message.images[0].image_url.url;
if (imageUrl.startsWith('data:image')) { ... } // OK
成本
- 价格: $0.04/张
- 速度: 5-10 秒
- 模型:
google/gemini-2.5-flash-image-preview