跳到正文
openrouter blog·· 2026-08-17精選AI 評分67

OpenRouter Image Generation: A Code-First API Tutorial 圖片生成 API 教學

OpenRouter Image Generation: A Code-First API Tutorial

AI 導讀

OpenRouter Image Generation API 推出統一的端點與金鑰機制,讓開發者透過單一請求格式呼叫多款圖片生成模型。

  • 核心端點:透過 POST /api/v1/images 傳送請求,並在 data[0].b64_json 接收 Base64 編碼的圖片資料。
推薦理由

原文提供使用統一介面呼叫多模型圖片生成與參考圖應用的完整程式碼,讀者可據此快速整合 API 至現有專案。

正文 · AI 翻譯

將影像生成加入應用程式會變得更困難,當你需要支援多個供應商時。許多供應商的數十個影像模型使用不同的端點、資料格式、控制項以及計費模式,費用依每張影像、每百萬畫素或每個 token 計算。

我們以專用的 Image generation API 解決此整合問題,該 API 在支援的模型中使用統一的請求格式與單一金鑰。

Tl;dr

  • 一個 API 與一個金鑰即可透過 POST /api/v1/images 連線到支援的影像模型。
  • 緩衝回應會將產生的影像放在 data[0].b64_json,你可以將其解碼並儲存到本機。
  • 相容的模型可透過 input_references 接收可選的參考影像。

本指南將協助你建立可執行的 Python 與 JavaScript 流程,先傳送提示文字、解碼並儲存回傳的影像,接著將參考影像傳送至端點並儲存產生的變體。

先決條件

開始前,請先準備以下專案:

  • 一個擁有餘額的 OpenRouter 帳號。沒有影像模型屬於免費層級,因此每一次請求都會扣除餘額。你將在第一步建立 API 金鑰。
  • Python 3 搭配 requests 套件,或 Node 18+ 內建 fetch。

第一步:取得金鑰並選擇影像模型

在 keys page 建立金鑰,然後在你將執行指令碼的同一個終端機輸出它。

export OPENROUTER_API_KEY="sk-or-v1-..."

從 image models collection 選擇一個模型。讓我們以 bytedance-seed/seedream-4.5 作為第一次執行。

你可以透過更改模型字串在支援影像的模型之間切換。可選的控制項(如解析度、多重輸出與參考輸入)因模型而異,請在加入前檢查功能紀錄。若要依工作、引數支援與價格縮小目錄,請參閱 choosing an image generation model。

在執行時偵測,GET /api/v1/images/models 會回傳可支援影像的 slug 與支援的引數。每個模型亦有包含供應商特定功能與定價的端點紀錄。此教學不需要這些端點,但當指令碼成為產品功能時會很有用。

第二步:傳送第一個影像請求

向 https://openrouter.ai/api/v1/images 傳送 POST 請求。影像 API 需要兩個主體欄位。model 選擇可支援影像的模型,而 prompt 描述你想要的影像。請在 Bearer 標頭中使用你的 OpenRouter 金鑰進行驗證。

Python

import os
import requests

response = requests.post(
    "https://openrouter.ai/api/v1/images",
    headers={
        "Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "bytedance-seed/seedream-4.5",
        "prompt": "A studio product photo of a matte black travel mug on a light gray background",
    },
    timeout=120,
)

if not response.ok:
    raise RuntimeError(f"{response.status_code}: {response.text}")

result = response.json()

在解析前檢查 response.ok 可保持 API 錯誤可見,而不是將其轉成後續令人困惑的缺少欄位錯誤。

JavaScript

const response = await fetch("https://openrouter.ai/api/v1/images", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "bytedance-seed/seedream-4.5",
    prompt: "A studio product photo of a matte black travel mug on a light gray background",
  }),
});

if (!response.ok) {
  throw new Error(`${response.status} ${await response.text()}`);
}

const result = await response.json();

明確的錯誤檢查保留回應主體,通常其中包含你需要修正請求的詳細資訊。

影像位於回應的哪裡?

成功的緩衝回應呈現以下簡化結構:

{
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAA...",
      "media_type": "image/png"
    }
  ],
  "usage": {
    "cost": 0.0123
  }
}

示例費用僅示範欄位結構,並非實際價格。

data 為陣列,因為一次請求可能回傳多個結果。第一張影像位於 data[0].b64_json。該值包含 base64 編碼的位元組,而非託管 URL。media_type 在我們能識別輸出格式時才會出現。可選的 usage.cost 值會在可用時報告完成請求的費用。

目前,非空的 b64_json 值即表示生成成功。下一步將這些位元組轉成本機影像檔。

第三步:解碼並儲存 output.png

回應顯示生成成功,但影像仍以 base64 文字存在 JSON 中。下一步是將 b64_json 解碼為位元組並將其寫入磁碟。以下兩段程式碼重複該請求,方便你單獲執行任一檔案。

Python

將此儲存為 generate.py:

import base64
import os
import requests

response = requests.post(
    "https://openrouter.ai/api/v1/images",
    headers={
        "Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "bytedance-seed/seedream-4.5",
        "prompt": "A studio product photo of a matte black travel mug on a light gray background",
    },
    timeout=120,
)

if not response.ok:
    raise RuntimeError(f"{response.status_code}: {response.text}")

result = response.json()
images = result.get("data") or []

if not images or not images[0].get("b64_json"):
    raise RuntimeError("The response did not contain image data")

image_bytes = base64.b64decode(images[0]["b64_json"])

with open("output.png", "wb") as output_file:
    output_file.write(image_bytes)

print("Saved output.png")

cost = result.get("usage", {}).get("cost")
if cost is not None:
    print(f"Request cost: ${cost}")

base64.b64decode 將回應字串轉換為原始二進點陣圖像資料。使用 wb 開啟目標可防止 Python 將這些位元組視為文字。

JavaScript

將此儲存為 generate.mjs:

import { writeFile } from "node:fs/promises";

const response = await fetch("https://openrouter.ai/api/v1/images", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "bytedance-seed/seedream-4.5",
    prompt: "A studio product photo of a matte black travel mug on a light gray background",
  }),
});

if (!response.ok) {
  throw new Error(`${response.status} ${await response.text()}`);
}

const result = await response.json();

if (!result.data?.[0]?.b64_json) {
  throw new Error("The response did not contain image data");
}

await writeFile("output.png", Buffer.from(result.data[0].b64_json, "base64"));

console.log("Saved output.png");
if (result.usage?.cost !== undefined) {
  console.log(`Request cost: $${result.usage.cost}`);
}

Buffer.from(..., "base64") 執行相同的轉換,而 writeFile 儲存產生的位元組。

從包含該檔案的目錄執行任一版本:

python3 generate.py

對於 JavaScript,使用:

node generate.mjs

成功執行會列印 Saved output.png。成本行僅在回應包含 usage.cost 時才會出現。

輸出格式依模型而異。有些模型會回傳 JPEG 或 WebP 位元組而非 PNG。若格式對您重要,請從回應中讀取 media_type 並選擇相符的檔案副檔名。

步驟 4:新增參考影像

參考影像提供模型可供參考的視覺素材,而非僅依賴提示。它是透過 input_references 新增的。

對於本機檔案,請讀取位元組,將其編碼為 base64,並在前面加上正確的媒體型別以建立資料 URL。

將影像檔案 product.jpg 放置於與指令碼相同的專案資料夾中,然後建立檔案 reference.py:

import base64
import os

import requests

with open("product.jpg", "rb") as reference_file:
    reference_base64 = base64.b64encode(reference_file.read()).decode("utf-8")

reference_data_url = f"data:image/jpeg;base64,{reference_base64}"

response = requests.post(
    "https://openrouter.ai/api/v1/images",
    headers={
        "Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "openai/gpt-image-1",
        "prompt": (
            "Keep the product shape and materials. Place it on a warm stone "
            "surface with soft morning light and a clean commercial style."
        ),
        "input_references": [
            {
                "type": "image_url",
                "image_url": {
                    "url": reference_data_url,
                },
            }
        ],
    },
    timeout=120,
)

if not response.ok:
    raise RuntimeError(f"{response.status_code}: {response.text}")

result = response.json()
images = result.get("data") or []

if not images or not images[0].get("b64_json"):
    raise RuntimeError("The response did not contain image data")

variation_bytes = base64.b64decode(images[0]["b64_json"])

with open("variation.png", "wb") as output_file:
    output_file.write(variation_bytes)

print("Saved variation.png")

從相同目錄執行它:

python3 reference.py

此模式適用於產品照片變化,因為來源影像能保留可辨識的物件,而提示則改變環境、照明或呈現方式。

參考影像支援與可接受的參考數量因模型端點而異。在依賴此功能前,請檢查端點紀錄並確認 input_references 出現在 supported_parameters 中。

步驟 5:使請求可重複使用

一旦請求可靠運作,將不常變動的設定移至本機設定檔。將模型 slug、供應商路由、逾時時間與輸出目錄一起保留。將提示、參考影像與使用者控制留在請求中,以便每張影像可變更。

故障排除與成本說明

大多數失敗在記錄 HTTP 狀態碼及非 2xx 時的回應主體時即可明顯,於閱讀任何影像欄位之前。成功時跳過主體,因為它以 base64 傳送整張影像。以下五項為本教學請求可能遇到的錯誤。欲瞭解完整的 Image API 錯誤訊息及其含義,請參閱 模型說明書的故障排除區段。

  • 缺少 data[0].b64_json。 先檢查回應主體。確認您已向 /api/v1/images 傳送 POST 請求並選擇了支援影像的模型。
  • 401 回應。 確保流程能讀取 OPENROUTER_API_KEY。檢查變數是否存在(不要印出其值),然後從執行指令碼的終端機匯出它。
  • 402 回應。 您可用餘額為或低於 Image API 在每次請求前檢查的固定 $1 最低額度,無論影像本身成本為何。
  • 參考請求失敗。 確認模型支援 input_references 並檢查影像 URL。本機 JPEG 必須使用以 data:image/jpeg;base64, 開頭的有效資料 URL。
  • 意外成本。 在執行批次前檢查端點的定價。如有可用,請於測試執行期間記錄 usage.cost 與模型 slug 及輸出檔名。

常見問題

我可以使用 OpenRouter 產生影像嗎?

可以。向 /api/v1/images 傳送 POST 請求,並提供支援影像的模型、提示及您的 OpenRouter API 金鑰。回應包含 base64 影像資料,您可解碼並儲存至本機。

如何使用 API 產生影像?

以 Bearer 標頭授權請求,然後傳送模型與提示。檢查回應狀態,解碼 data[0].b64_json,並將產生的位元組寫入影像檔。

如何透過提示產生 AI 影像?

描述提示的主題、環境、構圖、照明與風格。僅在相容模型應編輯或變化現有影像時使用 input_references。

哪個 API 最適合影像生成?

比較影像品質、控制、參考影像支援、延遲與價格。當您想使用單一 API 金鑰並為多個影像模型使用統一的請求格式時,OpenRouter 是最佳選擇。

參考資料

來源:openrouter blog · openrouter.ai