Use Nano Banana Pro, Nano Banana 2 or GPT Image 2 / 2.5 for SillyTavern's Image Generation extension at about $0.037 per image, through a small local adapter.
SillyTavern has no built-in VELIN source, and you cannot plug VELIN in by pasting a key. VELIN is its own async REST API, not a Stable Diffusion server. The workaround is a tiny local adapter (about 80 lines of Node, no dependencies) that pretends to be a Stable Diffusion WebUI backend. SillyTavern talks to the adapter on 127.0.0.1:7861; the adapter calls VELIN, polls until the image is ready and returns it as base64.
export VELIN_API_KEY=your_key then node velin-sd-adapter.mjs. It prints VELIN adapter on http://127.0.0.1:7861.http://127.0.0.1:7861, then press Connect.gpt-image-2.5-flare, gpt-image-2.5-sunburst, gpt-image-2, nano-banana-2 and nano-banana-pro). Generate an image from the chat as usual.Save as velin-sd-adapter.mjs. It maps the width and height SillyTavern sends to the nearest VELIN aspect ratio, always requests 1K (the price is the same at any resolution, so change resolution if you want more), and ignores sampler, steps and other Stable Diffusion settings, which do not apply.
#!/usr/bin/env node
// Minimal "Stable Diffusion WebUI"-style adapter for SillyTavern -> VELIN.
// Node 18+, no dependencies.
// export VELIN_API_KEY=your_key
// node velin-sd-adapter.mjs # listens on http://127.0.0.1:7861
import http from "node:http";
const BASE = process.env.VELIN_BASE_URL || "https://72agi.com";
const KEY = process.env.VELIN_API_KEY;
const PORT = Number(process.env.PORT || 7861);
if (!KEY) { console.error("Set VELIN_API_KEY first"); process.exit(1); }
const auth = { Authorization: `Bearer ${KEY}` };
const MODELS = ["gpt-image-2.5-flare", "gpt-image-2.5-sunburst", "gpt-image-2",
"nano-banana-2", "nano-banana-pro"];
let model = MODELS[0];
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// width x height -> nearest supported VELIN aspect ratio
const RATIOS = { "1:1": 1, "16:9": 16 / 9, "9:16": 9 / 16, "4:3": 4 / 3, "3:4": 3 / 4, "3:2": 1.5, "2:3": 2 / 3 };
function nearestRatio(w, h) {
const r = w / h;
return Object.entries(RATIOS).sort((a, b) => Math.abs(a[1] - r) - Math.abs(b[1] - r))[0][0];
}
async function generate(prompt, w, h) {
const form = new FormData();
form.set("prompt", prompt);
form.set("model", model);
form.set("size", nearestRatio(w, h));
form.set("resolution", "1K");
const res = await fetch(`${BASE}/api/generate`, { method: "POST", headers: auth, body: form });
const body = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(`submit HTTP ${res.status}: ${body.error ?? ""}`);
for (let i = 0; i < 180; i++) { // poll every 5 s, up to 15 min
await sleep(5000);
const job = await (await fetch(`${BASE}/api/task/${body.id}`, { headers: auth })).json();
if (job.status === "succeeded") {
const img = await fetch(BASE + job.url, { headers: auth });
return Buffer.from(await img.arrayBuffer()).toString("base64");
}
if (job.status === "failed") throw new Error(`failed (not charged): ${job.error}`);
}
throw new Error("timed out");
}
const json = (res, code, obj) => {
res.writeHead(code, { "Content-Type": "application/json" });
res.end(JSON.stringify(obj));
};
http.createServer(async (req, res) => {
const path = new URL(req.url, "http://x").pathname;
let raw = "";
for await (const c of req) raw += c;
const body = raw ? JSON.parse(raw) : {};
try {
if (path === "/sdapi/v1/options" && req.method === "POST") {
if (MODELS.includes(body.sd_model_checkpoint)) model = body.sd_model_checkpoint;
return json(res, 200, {});
}
if (path === "/sdapi/v1/options") return json(res, 200, { sd_model_checkpoint: model });
if (path === "/sdapi/v1/sd-models") return json(res, 200, MODELS.map((m) => ({ title: m, model_name: m })));
if (path === "/sdapi/v1/samplers") return json(res, 200, [{ name: "Euler" }]);
if (path === "/sdapi/v1/schedulers") return json(res, 200, [{ name: "Automatic" }]);
if (path === "/sdapi/v1/upscalers") return json(res, 200, [{ name: "None" }]);
if (path === "/sdapi/v1/latent-upscale-modes") return json(res, 200, []);
if (path === "/sdapi/v1/sd-vae" || path === "/sdapi/v1/sd-modules") return json(res, 200, []);
if (path === "/sdapi/v1/progress") return json(res, 200, { progress: 0, state: { job_count: 0 } });
if (path === "/sdapi/v1/interrupt") return json(res, 200, {});
if (path === "/sdapi/v1/txt2img" && req.method === "POST") {
const b64 = await generate(body.prompt, body.width || 1024, body.height || 1024);
return json(res, 200, { images: [b64], parameters: {}, info: "{}" });
}
json(res, 404, { error: "not found" });
} catch (e) {
console.error(e.message);
json(res, 500, { error: e.message });
}
}).listen(PORT, "127.0.0.1", () => console.log(`VELIN adapter on http://127.0.0.1:${PORT}`));
127.0.0.1 only.429.generate.py or generate.mjs, or the n8n workflow.No. SillyTavern's Image Generation extension talks to a fixed list of providers, and VELIN is not one of them. The adapter on this page makes VELIN look like a Stable Diffusion WebUI server, which SillyTavern already supports.
VELIN is asynchronous (submit a task, poll for the result), returns a URL path rather than base64, and sends no CORS headers. The adapter runs on your machine, does the polling and hands SillyTavern a base64 image.
The key stays in the adapter's environment variable on your own machine. Do not put it in a character card, preset or shared SillyTavern config. The key also signs in to your account, so treat it like a password.
Typically about 45 to 100 seconds depending on the model; 4K and many reference images take longer. The API is asynchronous: submit a task, then poll for the result.
No. Credits are reserved when you submit a task and refunded automatically if it fails.
Top up with USDT on the billing page; the balance is credited automatically. Card payments are coming soon.
Free tests are available on request: message @ayan8866e on Telegram. There are no automatic free credits.
Want a free test, higher rate limits or volume pricing? Message @ayan8866e on Telegram. Free tests are on request; there are no automatic free credits.
Nano Banana and Gemini are trademarks of Google. GPT Image is a trademark of OpenAI. VELIN is an independent service and is not affiliated with or endorsed by either company. Competitor prices are quoted from the linked public pages on the date shown and may change.