一些中转站的大香蕉支持 openai chat 和 gemini generateContent 的 api 调用
chat 可以在对话里直接说比例,但是图像分辨率不能指定(有些给了额外参数,有些没有)。

用 gemini 自己的 generateContent 不知道为什么一些在 cherrystudio 里用不会生图,只会回复文本。。。
大香蕉 gemini generateContent 接口格式 ts 生图小脚本1

大香蕉 gemini generateContent 接口格式 ts 生图小脚本1

(返回 token 才 184。。。就是没图了。。。)


但是调 api 却是好的.. 很神奇
写了个脚本,给大家参考一下.(脚本本身挺简单的,就是有几个参数要自己找下)。
依赖:

pnpm add @google/genai
pnpm add dotenv #直接写key 不需要用到.env不需要 

文件名(这个工具类脚本项目里一开始就有。。用了就直接粘过来了):
src\utils\filename.ts

export function generateFilename(extension: string): string {
  const now = new Date();

  // Format date components const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, "0");
  const day = String(now.getDate()).padStart(2, "0");
  const hours = String(now.getHours()).padStart(2, "0");
  const minutes = String(now.getMinutes()).padStart(2, "0");
  const seconds = String(now.getSeconds()).padStart(2, "0");
  const milliseconds = String(now.getMilliseconds()).padStart(3, "0");

  // Format: YYYYMMDD_HHMMSS_MS.ext return `${year}${month}${day}_${hours}${minutes}${seconds}_${milliseconds}.${extension}`;
}

export function generateFilenameWithPrefix(extension: string,
prefix?: string
): string { const timestamp = generateFilename(extension); if (prefix) { return `${prefix}_${timestamp}`; } return timestamp; } export function generateFilenameSimple(extension: string): string { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, "0"); const day = String(now.getDate()).padStart(2, "0"); const hours = String(now.getHours()).padStart(2, "0"); const minutes = String(now.getMinutes()).padStart(2, "0"); const seconds = String(now.getSeconds()).padStart(2, "0"); return `${year}${month}${day}_${hours}${minutes}${seconds}.${extension}`; } export default { generateFilename, generateFilenameWithPrefix, generateFilenameSimple, };

src\paint\generate.ts

import { GoogleGenAI } from "@google/genai";
import * as fs from "node:fs";
import dotenv from "dotenv";

import path from "path";
import { generateFilenameWithPrefix } from "../utils/filename.js";
// 不用.env这一行不需要
dotenv.config();

interface GenerateImageOptions {
  textPrompt: string;
  aspectRatio: string;
  resolution: string;
  referenceImage?: string[];
}

async function generateImage({ textPrompt, aspectRatio, resolution, referenceImage }: GenerateImageOptions,
resultDir: string
) { letif (referenceImage && referenceImage.length > 0) { for (constof referenceImage) { constreadFileSync(image); const base64Image = imageData.toString("base64"); imageContents.push({ inlineData: { data: base64Image, mimeType: "image/png", }, }); } } const ai = new GoogleGenAI({ httpOptions: { // 换成你中转站的网址 不需要/v1beta baseUrl: "https://xxxx", // 直接跑就把key直接写在里面 headers: { Authorization: "Bearer " + process.env.GOOGLE_API_KEY! }, }, }); const prompt = [ { text: textPrompt, }, ...imageContents, ]; const response = await ai.models.generateContent({ model: "gemini-3-pro-image-preview", contents: prompt, config: { responseModalities: ["TEXT", "IMAGE"], : { aspectRatio: aspectRatio, : resolution, }, }, }); if (!response.candidates) { throw new Error("No candidates found"); } const parts = response.candidates[0]?.content?.parts; if (!parts) { throw new Error("No parts found"); } for (const part of parts) { if (part.text) { console.log(part.text); } else if (part.inlineData) { constinlineData.data; if (!imageData) { throw new Error("No image data found"); } const buffer = Buffer.from(imageData, "base64"); const filePath = path.join( resultDir, generateFilenameWithPrefix("png", "gemini") ); fs.writeFileSync(filePath, buffer); console.log(`Image saved as ${filePath}`); } } } export default generateImage;

调用:

import path from "path";
import { fileURLToPath } from "url";
import generateImage from "./generate.js";
import { existsSync, mkdirSync } from "fs";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 改成自己的目录 这里是相对跑的这个ts文件的位置 const resultDir = path.join(__dirname, "../../paint-result");

const aspectRatio = "16:9";
const resolution = "2K";
const textPrompt = `EVA中的明日香,凌波丽;凉宫春日系列中的长门有希;机动战舰中的星野琉璃(参考图片就是星野琉璃, 参考参考图画);Fate中的Saber。

她们并肩坐在草坪上,草地上有发光的萤火虫和五颜六色的花朵。身后是夜空,银河繁星闪烁,。

烟花在夜空中绽放。烟花的光芒映照在她们的脸庞上。

天空中用金色和红色的烟花轨迹写着"新年快乐"四个大字。

她们微笑着,面向镜头。草坪四周摆放着彩色的灯笼、礼物盒和香槟酒杯,充满新年气息。

画风参考参考图,精致细腻的动画画风。
`
; // 用String.raw因为windows下直接拖入vscode还是用的\ 懒得转了直接raw吧 // 不需要参考图 写 = []就行 const referenceImage: string[] = [ String.raw`c:\Users\ooo\Downloads\琉璃.jpg`, ]; existsSync(resultDir) || mkdirSync(resultDir, { recursive: true }); generateImage( { textPrompt, aspectRatio, resolution, referenceImage, }, resultDir );

(想着本身就是复制谷歌文档里的 就只需要小改动没出动 ai 改 古法编程一个脚本改了快 20 分钟 哭死

祝佬们新年快乐~


📌 转载信息
原作者:
blacksein
转载时间:
2026/1/1 15:49:32