> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixroute.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Gemini 原生（圖片，串流）

> Gemini 原生圖片生成模型，streamGenerateContent 串流文字生圖與圖生圖

## 簡介

`streamGenerateContent` 是 Gemini 原生 `generateContent` 的串流版本。Nano Banana 對應 Google Gemini 原生圖片生成能力，包括 Nano Banana（`gemini-2.5-flash-image`）、Nano Banana 2（`gemini-3.1-flash-image`、`gemini-3.1-flash-image-preview`）與 Nano Banana Pro（`gemini-3-pro-image`）。呼叫 MixRoute 原生串流介面時，使用端點 `POST /v1/models/<model>:streamGenerateContent?alt=sse`，並傳入符合 Gemini 原生結構的 JSON Payload，支援文字生圖、圖生圖及多圖融合等能力。

串流介面會返回 Server-Sent Events（SSE），用戶端應逐行讀取 `data:` 事件內容，而不是將整個回應體當作單一 JSON 物件解析。

完整參數與多模型說明請參見 [圖片生成](/cn/api-reference/endpoint/image-generation)。

## 認證

Bearer Token，例如 `Bearer sk-xxxxxxxxxx`

## 支援的模型

| 模型 ID                            | 說明                                         |
| -------------------------------- | ------------------------------------------ |
| `gemini-2.5-flash-image`         | Nano Banana，高性價比文字生圖/圖生圖，輸出為固定 1024px 級尺寸  |
| `gemini-3.1-flash-image`         | Nano Banana 2，卓越畫質與速度平衡，支援 1K、2K、4K 輸出     |
| `gemini-3.1-flash-image-preview` | Nano Banana 2 預覽版，支援圖片生成測試                 |
| `gemini-3-pro-image`             | Nano Banana Pro，更高畫質與極強細節控制，支援 1K、2K、4K 輸出 |

## 基礎範例

<Tabs>
  <Tab title="文字生圖">
    ```bash theme={null}
    curl -X POST "https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse" \
      -H "Authorization: Bearer sk-xxxxxxxxxx" \
      -H "Content-Type: application/json" \
      --no-buffer \
      -d '{
        "contents": [
          {
            "role": "user",
            "parts": [
              {
                "text": "一隻可愛的橘色小貓坐在花園裡，陽光明媚，高品質攝影"
              }
            ]
          }
        ],
        "generationConfig": {
          "responseModalities": [
            "TEXT",
            "IMAGE"
          ],
          "imageConfig": {
            "aspectRatio": "16:9",
            "imageSize": "2K"
          }
        }
      }'
    ```
  </Tab>

  <Tab title="圖生圖">
    ```bash theme={null}
    curl -X POST "https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse" \
      -H "Authorization: Bearer sk-xxxxxxxxxx" \
      -H "Content-Type: application/json" \
      --no-buffer \
      -d '{
        "contents": [
          {
            "role": "user",
            "parts": [
              {
                "text": "根據這張圖生成一張俯瞰廣州塔的圖片"
              },
              {
                "inlineData": {
                  "mimeType": "image/png",
                  "data": "iVBORw0KGgoAAA..."
                }
              }
            ]
          }
        ],
        "generationConfig": {
          "responseModalities": [
            "TEXT",
            "IMAGE"
          ],
          "imageConfig": {
            "aspectRatio": "16:9",
            "imageSize": "2K"
          }
        }
      }'
    ```
  </Tab>
</Tabs>

## 請求參數

<ParamField path="model" type="string" required>
  Gemini 原生（圖片）模型識別碼，位於 URL 路徑中，如 `gemini-3.1-flash-image` 或 `gemini-3-pro-image`。
</ParamField>

<ParamField query="alt" type="string">
  串流回應格式。傳入 `sse` 時，介面會以 Server-Sent Events 返回串流 `GenerateContentResponse` 資料。
</ParamField>

<ParamField body="contents" type="array" required>
  原生對話或圖片內容列表。

  <Expandable title="contents 子欄位">
    <ParamField body="contents[].role" type="string">
      角色識別，通常為 `"user"`。
    </ParamField>

    <ParamField body="contents[].parts" type="array" required>
      內容區塊列表。每個元素可以是文字提示詞（`{"text": "..."}`）或內嵌媒體資料（`{"inlineData": {"mimeType": "...", "data": "<BASE64>"}}`）。

      <Expandable title="parts 子欄位">
        <ParamField body="contents[].parts[].inlineData" type="object">
          內嵌媒體資料物件。

          <Expandable title="inlineData 子欄位">
            <ParamField body="contents[].parts[].inlineData.mimeType" type="string">
              媒體類型的 MIME 格式，如 `"image/png"`、`"image/jpeg"`、`"image/webp"` 等。
            </ParamField>

            <ParamField body="contents[].parts[].inlineData.data" type="string">
              圖片資料的 Base64 編碼字串（不含前綴）。
            </ParamField>
          </Expandable>
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="generationConfig" type="object">
  生成設定參數。

  <Expandable title="generationConfig 子欄位">
    <ParamField body="generationConfig.responseModalities" type="array">
      回應模態。如傳入該欄位，需包含 `"IMAGE"`；常用寫法為 `["TEXT", "IMAGE"]`。
    </ParamField>

    <ParamField body="generationConfig.imageConfig" type="object">
      圖片生成設定。

      <Expandable title="imageConfig 子欄位">
        <ParamField body="generationConfig.imageConfig.aspectRatio" type="string">
          輸出圖片的寬高比。`gemini-2.5-flash-image` 與 `gemini-3-pro-image` 支援 `"1:1"`、`"2:3"`、`"3:2"`、`"3:4"`、`"4:3"`、`"4:5"`、`"5:4"`、`"9:16"`、`"16:9"`、`"21:9"`；`gemini-3.1-flash-image` 系列另外支援 `"1:4"`、`"4:1"`、`"1:8"`、`"8:1"`。
        </ParamField>

        <ParamField body="generationConfig.imageConfig.imageSize" type="string">
          輸出解析度或尺寸級別。`gemini-2.5-flash-image` 不使用該欄位，依寬高比返回固定 1024px 級尺寸；`gemini-3.1-flash-image` 系列與 `gemini-3-pro-image` 支援 `"1K"`、`"2K"`、`"4K"`。
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

更多參數與各模型差異請參見 [圖片生成](/cn/api-reference/endpoint/image-generation)。

## 回應格式

介面返回 SSE 串流。每個 `data:` 事件的內容是一個 JSON 格式的 `GenerateContentResponse` 實例；圖片可能以一個或多個 Base64 編碼的 `inlineData` 形式出現在某個或多個 chunk 的 `candidates` 中。用戶端應逐行讀取 SSE，並分別解析每個 `data:` 之後的 JSON。

| 欄位                                                 | 類型      | 說明                                             |
| -------------------------------------------------- | ------- | ---------------------------------------------- |
| `data`                                             | string  | SSE 事件資料列，內容為一個 JSON `GenerateContentResponse` |
| `candidates[].content.parts[].text`                | string  | 模型返回的文字片段                                      |
| `candidates[].content.parts[].inlineData.mimeType` | string  | 圖片 MIME 類型（如 `image/png`）                      |
| `candidates[].content.parts[].inlineData.data`     | string  | 圖片的 Base64 編碼資料                                |
| `candidates[].finishReason`                        | string  | 生成結束原因，如 `"STOP"`                              |
| `usageMetadata.promptTokenCount`                   | integer | 輸入 token 數                                     |
| `usageMetadata.candidatesTokenCount`               | integer | 輸出 token 數（圖片 token）                           |
| `modelVersion`                                     | string  | 實際使用的模型版本                                      |
| `responseId`                                       | string  | 回應唯一識別碼                                        |

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse' \
    --header 'Authorization: Bearer sk-xxxxxxxxxx' \
    --header 'Content-Type: application/json' \
    --no-buffer \
    --data '{
      "contents": [
        {
          "role": "user",
          "parts": [
            {
              "text": "一隻可愛的橘色小貓坐在花園裡"
            }
          ]
        }
      ],
      "generationConfig": {
        "responseModalities": [
          "TEXT",
          "IMAGE"
        ],
        "imageConfig": {
          "aspectRatio": "16:9",
          "imageSize": "2K"
        }
      }
    }'
  ```

  ```python Python theme={null}
  import json
  import requests

  url = "https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse"
  headers = {
      "Authorization": "Bearer sk-xxxxxxxxxx",
      "Content-Type": "application/json"
  }
  payload = {
      "contents": [
          {
              "role": "user",
              "parts": [
                  {
                      "text": "一隻可愛的橘色小貓坐在花園裡"
                  }
              ]
          }
      ],
      "generationConfig": {
          "responseModalities": [
              "TEXT",
              "IMAGE"
          ],
          "imageConfig": {
              "aspectRatio": "16:9",
              "imageSize": "2K"
          }
      }
  }

  with requests.post(url, json=payload, headers=headers, stream=True) as response:
      response.raise_for_status()
      for line in response.iter_lines(decode_unicode=True):
          if not line or not line.startswith("data: "):
              continue
          chunk = json.loads(line.removeprefix("data: "))
          print(chunk)
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk-xxxxxxxxxx',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      contents: [
        {
          role: "user",
          parts: [
            {
              text: "一隻可愛的橘色小貓坐在花園裡"
            }
          ]
        }
      ],
      generationConfig: {
        responseModalities: [
          "TEXT",
          "IMAGE"
        ],
        imageConfig: {
          aspectRatio: "16:9",
          imageSize: "2K"
        }
      }
    })
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";

  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split("\n");
    buffer = lines.pop() ?? "";

    for (const line of lines) {
      if (!line.startsWith("data: ")) continue;
      const chunk = JSON.parse(line.slice("data: ".length));
      console.log(chunk);
    }
  }

  if (buffer.startsWith("data: ")) {
    const chunk = JSON.parse(buffer.slice("data: ".length));
    console.log(chunk);
  }
  ```

  ```php PHP theme={null}
  <?php
  $client = new GuzzleHttp\Client();
  $response = $client->post('https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse', [
      'headers' => [
          'Authorization' => 'Bearer sk-xxxxxxxxxx',
          'Content-Type' => 'application/json',
      ],
      'stream' => true,
      'json' => [
          'contents' => [
              [
                  'role' => 'user',
                  'parts' => [
                      [
                          'text' => '一隻可愛的橘色小貓坐在花園裡'
                      ]
                  ]
              ]
          ],
          'generationConfig' => [
              'responseModalities' => [
                  'TEXT',
                  'IMAGE'
              ],
              'imageConfig' => [
                  'aspectRatio' => '16:9',
                  'imageSize' => '2K'
              ]
          ]
      ]
  ]);

  $body = $response->getBody();
  $buffer = '';
  while (!$body->eof()) {
      $buffer .= $body->read(8192);
      $lines = explode("\n", $buffer);
      $buffer = array_pop($lines);
      foreach ($lines as $line) {
          if (str_starts_with($line, 'data: ')) {
              print_r(json_decode(substr($line, 6), true));
          }
      }
  }

  if (str_starts_with($buffer, 'data: ')) {
      print_r(json_decode(substr($buffer, 6), true));
  }
  ```

  ```go Go theme={null}
  package main

  import (
      "bufio"
      "bytes"
      "encoding/json"
      "fmt"
      "net/http"
      "strings"
  )

  func main() {
      payload := map[string]interface{}{
          "contents": []interface{}{
              map[string]interface{}{
                  "role": "user",
                  "parts": []interface{}{
                      map[string]interface{}{
                          "text": "一隻可愛的橘色小貓坐在花園裡",
                      },
                  },
              },
          },
          "generationConfig": map[string]interface{}{
              "responseModalities": []string{
                  "TEXT",
                  "IMAGE",
              },
              "imageConfig": map[string]interface{}{
                  "aspectRatio": "16:9",
                  "imageSize":   "2K",
              },
          },
      }
      body, _ := json.Marshal(payload)
      req, _ := http.NewRequest("POST", "https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse", bytes.NewBuffer(body))
      req.Header.Set("Authorization", "Bearer sk-xxxxxxxxxx")
      req.Header.Set("Content-Type", "application/json")

      resp, _ := http.DefaultClient.Do(req)
      defer resp.Body.Close()

      reader := bufio.NewReader(resp.Body)
      for {
          line, err := reader.ReadString('\n')
          if len(line) > 0 {
              line = strings.TrimSuffix(line, "\n")
              line = strings.TrimSuffix(line, "\r")
          }
          if strings.HasPrefix(line, "data: ") {
              fmt.Println(strings.TrimPrefix(line, "data: "))
          }
          if err != nil {
              break
          }
      }
  }
  ```

  ```java Java theme={null}
  import java.net.http.*;
  import java.net.URI;

  HttpClient client = HttpClient.newHttpClient();
  String json = """
      {
          "contents": [
              {
                  "role": "user",
                  "parts": [
                      {
                          "text": "一隻可愛的橘色小貓坐在花園裡"
                      }
                  ]
              }
          ],
          "generationConfig": {
              "responseModalities": [
                  "TEXT",
                  "IMAGE"
              ],
              "imageConfig": {
                  "aspectRatio": "16:9",
                  "imageSize": "2K"
              }
          }
      }
      """;
  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse"))
      .header("Authorization", "Bearer sk-xxxxxxxxxx")
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(json))
      .build();

  HttpResponse<java.util.stream.Stream<String>> response = client.send(
      request,
      HttpResponse.BodyHandlers.ofLines()
  );

  response.body()
      .filter(line -> line.startsWith("data: "))
      .forEach(line -> System.out.println(line.substring("data: ".length())));
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'

  uri = URI('https://api.mixroute.ai/v1/models/gemini-3.1-flash-image:streamGenerateContent?alt=sse')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri)
  request['Authorization'] = 'Bearer sk-xxxxxxxxxx'
  request['Content-Type'] = 'application/json'
  request.body = {
    contents: [
      {
        role: 'user',
        parts: [
          {
            text: '一隻可愛的橘色小貓坐在花園裡'
          }
        ]
      }
    ],
    generationConfig: {
      responseModalities: [
        'TEXT',
        'IMAGE'
      ],
      imageConfig: {
        aspectRatio: '16:9',
        imageSize: '2K'
      }
    }
  }.to_json

  http.request(request) do |response|
    buffer = ''
    response.read_body do |chunk|
      buffer << chunk
      lines = buffer.split("\n")
      buffer = lines.pop || ''

      lines.each do |line|
        line = line.delete_suffix("\r")
        next unless line.start_with?('data: ')

        puts JSON.parse(line.delete_prefix('data: '))
      end
    end

    if buffer.start_with?('data: ')
      puts JSON.parse(buffer.delete_prefix('data: '))
    end
  end
  ```
</RequestExample>

<ResponseExample>
  ```text Response theme={null}
  data: {"candidates":[{"content":{"role":"model","parts":[{"text":"正在生成圖片。"}]}}],"modelVersion":"gemini-3.1-flash-image","responseId":"stream-response-id"}

  data: {"candidates":[{"content":{"role":"model","parts":[{"inlineData":{"mimeType":"image/png","data":"iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIA..."}}]},"finishReason":"STOP"}],"usageMetadata":{"promptTokenCount":13,"candidatesTokenCount":1680,"totalTokenCount":1693,"promptTokensDetails":[{"modality":"TEXT","tokenCount":13}],"candidatesTokensDetails":[{"modality":"IMAGE","tokenCount":1680}]},"modelVersion":"gemini-3.1-flash-image","responseId":"stream-response-id"}
  ```
</ResponseExample>
