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

OpenRouter 影片生成 API:程式碼優先指引

OpenRouter Video Generation API: A Code-First Guide

AI 導讀

OpenRouter 透過統一的非同步影片生成 API,讓開發者一次提交、輪詢、下載即可支援 Seedance、Veo、Wan 等多款模型。

  • 工作流程:POST /api/v1/videos 提交工作 → 監控 job‑status → 下載 MP4。
推薦理由

統一的非同步 API 讓多模型影片生成變簡單,利於快速測試與成本掌控。

正文 · AI 翻譯

將影片生成加入應用程式時,若只測試單一模型,流程相當簡單。但若想嘗試其他模型,複雜度就會顯現。每個供應商可能擁有不同的端點、請求引數、工作狀態、輪詢邏輯以及輸出格式。這使得簡單的模型切換變成另一個需要建置與維護的整合。

我們把這個工作流程放在 一個非同步影片 API 後面。你向 POST /api/v1/videos 提交提示,收到工作 ID,持續輪詢直到生成完成,然後下載完成的影片。

在本指南中,我們將從頭到尾構建這個流程。先使用 Seedance 提交工作,安全輪詢,儲存 MP4,接著以相同方式整合 Veo 和 Wan。

簡而言之

  • 一個端點,支援多個影片模型。透過 POST /api/v1/videos 使用 Seedance、Veo、Wan 以及其他支援的模型進行生成。
  • 工作流程為非同步。提交工作,輪詢其狀態,然後下載完成的影片。
  • 透過更改模型識別碼來切換模型。部分模型特定設定,例如持續時間與長寬比,仍需依模型調整,詳見第 4 步,但端點、授權、輪詢迴圈與下載邏輯不會改變。

為何非同步 API 比其他方案更佳

影片生成所需時間長於一般 API 回應。模型必須產生並協調多個畫格,維持畫格間的視覺一致性,並且有時會產生相配的音訊。根據模型與請求設定,整個過程可能從數秒到數分鐘不等。

整段時間保持原始 HTTP 請求開啟非常脆弱。瀏覽器會話可能關閉,無伺服器函式可能達到執行限制,或代理可能在影片尚未完成前逾時。

非同步 API 將提交與完成分離:

  1. 提交生成請求。
  2. 立即收到工作 ID。
  3. 單獨檢查工作狀態。
  4. 生成完成後下載影片。

你的應用程式可以在模型在背景執行時繼續運作。亦可於重新啟動後恢復工作,因為生成是附著於持久工作 ID,而非長時間連線。

直接與單一供應商整合

若你已知想使用的模型且不預期會改變,直接與供應商整合可行。你會使用供應商的授權、請求格式、工作狀態、輪詢端點以及輸出回應。

當你想比較另一個模型時,額外工作才會顯現。新的供應商可能使用不同的欄位名稱來表示持續時間與解析度,或回傳不同的工作物件及不同的終端狀態。它也可能需要另一種下載完成資產的方法。此時你的應用程式就需要第二個客戶端、另一組環境變數,以及更多供應商特定的錯誤處理。

這種做法本身並無錯誤。只是表示切換模型是整合變更,而非設定變更,這使實驗變慢並隨著模型清單增長而提高維護成本。

在本機執行影片模型

本機生成可讓你擁有最高控制權。你可以選擇模型權重、客製化工作流程、將資產保留在自身環境內,並避免為每一次生成支付託管供應商費用。

這種控制伴隨著基礎設施的責任。您需要適當的 GPU 容量以及正確的 Python 與 CUDA 相依套件。您還需要足夠的儲存空間和每個模型族群的執行環境。更高解析度和更長影片會增加記憶體與處理需求,另外加入另一模型可能需要下載更多權重或維護另一工作流程。

對於已經擁有 GPU 基礎設施或需要本地處理的團隊而言,這可能值得。當您目標是快速加入影片生成並測試多個模型時,這是一個較重的起點。託管的 OpenRouter 路徑移除了大部分設定,這正是本指南其餘部分所涵蓋的。

透過 OpenRouter 使用單一託管 API

我們保持支援影片模型的生成生命週期一致。無論選擇的模型是 Seedance、Veo、Wan 或目錄中的其他模型,應用程式都使用相同的 API 金鑰、POST /api/v1/videos 端點、工作狀態流程與輸出檢索流程。

模型仍有不同的功能。某些模型可能支援更長的時長,而另一些則提供額外的長寬比、更高解析度、音訊生成或供應商特定控制。我們透過影片模型端點呈現這些差異,而非將所有模型強行套用相同功能集。

這樣即可得到穩定的整合,同時不隱藏各模型的差異。您的應用程式可以查詢目前的功能、構建有效請求,並在不替換周邊工作基礎設施的情況下切換模型。

先決條件與設定

您只需要 OpenRouter API 金鑰以及能夠傳送 HTTP 請求的工具。此處範例使用 Python 搭配 requests 與 TypeScript 搭配內建 fetch API,但此工作流程可在任何能傳送 HTTP 請求的語言中使用。

先從您的 OpenRouter 帳號建立 API 金鑰,然後將其存入環境變數,而非直接寫入原始碼:

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

對於 Python 範例,如果尚未安裝 requests,請安裝:

pip install requests

OpenRouter 以 bearer token 驗證 API 請求。在 Python 中,我們將一次定義共用值,並在整個指南中重複使用:

import os
import requests

API_KEY = os.environ["OPENROUTER_API_KEY"]
BASE_URL = "https://openrouter.ai/api/v1"

HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

提交工作前,您也可以 查詢影片模型端點 以檢視目前可用的模型及其支援專案:

curl "https://openrouter.ai/api/v1/videos/models" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY"

回應包含各模型支援的時長、解析度、長寬比、幀影像支援、音訊功能、定價 SKU 與供應商特定引數。這比假設一個影片模型接受的設定同樣適用於另一個模型更可靠。

步驟 1:提交影片生成工作

向 /api/v1/videos 傳送 POST 請求,並指定影片模型。請包含描述您想要生成內容的 prompt。

model 在每一次請求中必填,prompt 在文字轉影片時必填。僅支援以影像輸入生成影片的模型可省略。若選擇的模型支援,您亦可提供可選設定,如時長、解析度、長寬比、音訊生成、參考影像及種子。

我們將在整個指南中使用相同的 prompt:

PROMPT = (
    "A paper boat drifting down a rain-slicked gutter at night, "
    "neon reflections, slow tracking shot, cinematic lighting"
)

以下函式使用 Seedance 2.0 提交工作:

def submit_video(model: str, prompt: str) -> dict:
    response = requests.post(
        f"{BASE_URL}/videos",
        headers=HEADERS,
        json={
            "model": model,
            "prompt": prompt,
            "duration": 4,
            "resolution": "720p",
            "aspect_ratio": "16:9",
            "generate_audio": False,
        },
        timeout=60,
    )

    response.raise_for_status()
    return response.json()


job = submit_video(
    model="bytedance/seedance-2.0",
    prompt=PROMPT,
)

print("Job ID:", job["id"])
print("Status:", job["status"])
print("Polling URL:", job["polling_url"])

對應的 cURL 請求為:

curl "https://openrouter.ai/api/v1/videos" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bytedance/seedance-2.0",
    "prompt": "A paper boat drifting down a rain-slicked gutter at night, neon reflections, slow tracking shot, cinematic lighting",
    "duration": 4,
    "resolution": "720p",
    "aspect_ratio": "16:9",
    "generate_audio": false
  }'

成功的請求回傳 HTTP 202 Accepted。回應代表背景工作,而非完成影片:

{
  "id": "job-abc123",
  "status": "pending",
  "polling_url": "https://openrouter.ai/api/v1/videos/job-abc123"
}

在繼續之前先儲存回傳的工作 ID。若程式重新啟動,您應能繼續追蹤現有工作,而非重新提交並支付額外生成費用。

步驟 2:輪詢工作直到完成

Step 1 中回傳的 polling_url 指向與 GET /api/v1/videos/{id} 相同的工作資源,它們是同一個端點。影片工作可經歷以下狀態:

狀態含義
pending工作已被接受,正在等待執行
in_progress供應商正在產生影片
completed影片已準備好可下載
failed產生失敗
cancelled工作已被取消
expired工作超過允許的存活時間

你的輪詢迴圈應在 completed 時返回,並在 failed、cancelled 或 expired 時以錯誤停止。否則,應用程式可能會持續檢查永遠不會產生影片的工作。

檔案化回應會將 polling_url 回傳為完整 URL。以下的 urljoin 呼叫是防禦式程式碼,也能處理相對路徑,因此迴圈無論哪種情況都能運作:

import time
from urllib.parse import urljoin

TERMINAL_ERROR_STATES = {
    "failed",
    "cancelled",
    "expired",
}


def poll_video(
    initial_job: dict,
    interval: float = 30.0,
    timeout: float = 3600.0,
) -> dict:
    """Poll until the video completes or reaches an error state."""

    polling_url = urljoin(
        "https://openrouter.ai",
        initial_job["polling_url"],
    )

    deadline = time.monotonic() + timeout
    job = initial_job

    while True:
        status = job["status"]
        print("Status:", status)

        if status == "completed":
            return job

        if status in TERMINAL_ERROR_STATES:
            error = job.get("error") or "No error details were returned."
            raise RuntimeError(
                f"Video generation ended with status '{status}': {error}"
            )

        if status not in {"pending", "in_progress"}:
            raise RuntimeError(
                f"Received unexpected job status: {status}"
            )

        if time.monotonic() >= deadline:
            raise TimeoutError(
                f"Job {job['id']} did not complete within "
                f"{timeout} seconds."
            )

        time.sleep(interval)

        response = requests.get(
            polling_url,
            headers={
                "Authorization": f"Bearer {API_KEY}",
            },
            timeout=30,
        )

        response.raise_for_status()
        job = response.json()


completed_job = poll_video(job)

此迴圈包含兩項保護措施,快速範例常忽略。首先,它處理所有檔案化的終端狀態,而不僅僅等待 completed。其次,它設定一小時的逾時,避免工作無限期留在程序中。值得注意的一個邊緣案例:因為逾時檢查在每次休眠前進行,而非休眠後,工作在最壞情況下可能會超過一次輪詢間隔的名義逾時,才被迴圈捕捉。對於背景工作而言,這是一個不錯的折衷。如果你需要硬性上限,請在從休眠喚醒後立即再次檢查逾時。

我們目前的指引使用 30 秒輪詢間隔。影片工作通常需要約 30 秒至數分鐘,且每秒檢查不會讓供應商更快完成。上述間隔與逾時上限皆為操作指引,而非端點本身的檔案化合約,請依照自己的工作負載調整。

相同的輪詢流程,使用 TypeScript:

type VideoJobStatus =
  | "pending"
  | "in_progress"
  | "completed"
  | "failed"
  | "cancelled"
  | "expired";

type VideoJob = {
  id: string;
  polling_url: string;
  status: VideoJobStatus;
  error?: string;
  unsigned_urls?: string[];
};

const apiKey = process.env.OPENROUTER_API_KEY;

if (!apiKey) {
  throw new Error("OPENROUTER_API_KEY is not set");
}

const terminalErrorStates = new Set<VideoJobStatus>([
  "failed",
  "cancelled",
  "expired",
]);

async function pollVideo(
  initialJob: VideoJob,
  intervalMs = 30_000,
  timeoutMs = 3_600_000,
): Promise<VideoJob> {
  const pollingUrl = new URL(
    initialJob.polling_url,
    "https://openrouter.ai",
  );

  const deadline = Date.now() + timeoutMs;
  let job = initialJob;

  while (true) {
    console.log(`Status: ${job.status}`);

    if (job.status === "completed") {
      return job;
    }

    if (terminalErrorStates.has(job.status)) {
      throw new Error(
        job.error ?? `Video generation ${job.status}`,
      );
    }

    if (Date.now() >= deadline) {
      throw new Error(
        `Video job ${job.id} did not complete before the timeout`,
      );
    }

    await new Promise((resolve) =>
      setTimeout(resolve, intervalMs),
    );

    const response = await fetch(pollingUrl, {
      headers: {
        Authorization: `Bearer ${apiKey}`,
      },
    });

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

    job = (await response.json()) as VideoJob;
  }
}

將失敗的狀態 請求 與失敗的影片 工作 分開處理。輪詢時的臨時逾時並不表示產生本身失敗。請重試同一工作 ID 的狀態請求,而非提交新工作。

步驟 3:檢索並儲存影片

當狀態變為 completed 時,工作回應包含已填充的 unsigned_urls 陣列。每個條目指向工作已驗證的內容端點:

GET /api/v1/videos/{jobId}/content?index=0

索引預設為 0。只有當模型返回多個影片輸出時才需要更改。儘管欄位名稱如此,這些 URL 並非預簽名,請像輪詢時一樣在 Authorization 標頭中傳送 API 金鑰。

以下輔助程式在存在未簽名 URL 時使用第一個,若極少情況下不存在,則從工作 ID 重新構造內容 URL。

def download_video(
    job: dict,
    output_path: str = "out.mp4",
    index: int = 0,
) -> None:
    unsigned_urls = job.get("unsigned_urls") or []

    download_url = (
        unsigned_urls[index]
        if len(unsigned_urls) > index
        else (
            f"{BASE_URL}/videos/"
            f"{job['id']}/content?index={index}"
        )
    )

    with requests.get(
        download_url,
        headers={
            "Authorization": f"Bearer {API_KEY}",
        },
        stream=True,
        timeout=180,
    ) as response:
        response.raise_for_status()

        with open(output_path, "wb") as output_file:
            for chunk in response.iter_content(
                chunk_size=1024 * 1024
            ):
                if chunk:
                    output_file.write(chunk)

    print(f"Saved {output_path}")


download_video(completed_job)

以分塊方式串流回應可避免在寫入磁碟前將整個 MP4 載入記憶體。

以下是 TypeScript 等效程式。請注意,此版本將下載緩衝到記憶體,而非直接串流到磁碟,對於短片來說沒問題,但若經常下載長或高解析度影片,建議改為使用管道串流:

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

async function downloadVideo(
  job: VideoJob,
  outputPath = "out.mp4",
  index = 0,
): Promise<void> {
  const downloadUrl =
    job.unsigned_urls?.[index] ??
    `https://openrouter.ai/api/v1/videos/` +
      `${job.id}/content?index=${index}`;

  const response = await fetch(downloadUrl, {
    headers: {
      Authorization: `Bearer ${apiKey}`,
    },
  });

  if (!response.ok) {
    throw new Error(
      `Download failed: ${response.status} ` +
      `${await response.text()}`,
    );
  }

  const videoBuffer = Buffer.from(
    await response.arrayBuffer(),
  );

  await writeFile(outputPath, videoBuffer);
  console.log(`Saved ${outputPath}`);
}

此時,你已在磁碟上擁有生成的 MP4。請將完成的影片移至你控制的儲存位置,而非將產生端點視為永久檔案主機。完成的工作也可能包含一個 usage 物件,內含最終成本,這是回應主體的一部分,無論你使用哪種語言:

usage = completed_job.get("usage") or {}

print("Generation cost:", usage.get("cost"))
print("Used BYOK:", usage.get("is_byok"))

將該值與內部工作記錄一起儲存,以便追蹤每次產生的實際成本。

步驟 4:一行切換模型

提交、輪詢與下載函式並未繫結於 Seedance。若要使用其他支援的影片模型,只需更改模型識別碼:

# Seedance
MODEL = "bytedance/seedance-2.0"

# Veo
# MODEL = "google/veo-3.1"

# Wan
# MODEL = "alibaba/wan-2.7"

job = submit_video(
    model=MODEL,
    prompt=PROMPT,
)

completed_job = poll_video(job)
download_video(completed_job)

端點、驗證、回應結構、狀態處理以及下載邏輯在三者之間保持相同。自動遷移不到的是每個可選設定。切換模型只需改一行程式碼,但並不保證任何特定的時長、解析度或畫面比例組合在新模型上皆能驗證。此設定恰好在本指南所涵蓋的三個模型之間可攜帶:

{
  "duration": 4,
  "resolution": "720p",
  "aspect_ratio": "16:9",
  "generate_audio": false
}

撰寫時,即時模型端點顯示 Seedance 2.0、Veo 3.1 與 Wan 2.7 均支援該特定組合:四秒、720p、16:9。這是三個範例之間共用的設定,並非聲稱每個設定在所有模型上都相同。超出此範圍時差異會迅速顯現:

  • Veo 3.1 目前支援四秒、六秒及八秒的時長。
  • Seedance 2.0 目前支援四至十五秒的時長以及額外的畫面比例。
  • Wan 2.7 目前支援兩至十秒的時長以及 720p 或 1080p 的解析度。

五秒的請求在 Seedance 與 Wan 上會驗證通過,但在 Veo 上會失敗。這也是為什麼您的應用程式應在提交請求前查詢 /api/v1/videos/models,而不是假設一個模型接受的設定在另一個模型上也能使用。上述數字在依賴前值得再次與即時端點核對,因為模型功能會變化。

同一端點也會暴露 allowed_passthrough_parameters 供模型特定功能使用。這些是您允許在請求的 provider.options 物件內傳送的鍵,該物件以供應商 slug 為鍵,例如 provider.options["google-vertex"].parameters。僅轉發提供者支援的選項,未識別的鍵則會被丟棄。以 Veo 為例,目前列出了 negativePrompt 與 enhancePrompt 等控制項,而 Wan 則暴露 negative_prompt 與 prompt_extend 等選項。

進入正式環境前值得了解的幾點

上述程式碼足以產生並下載一段影片。當此流程投入正式環境後,問題就會改變:您需要控制成本、區分工作失敗與網路失敗、避免重複處理,並在提交程式結束後持續追蹤工作。

擴充前先檢查成本

影片生成價格因模型與設定而異。時長、解析度、音訊生成以及供應商的計費方式皆會影響最終成本。本地生成完全改變了成本結構,沒有每段影片費用,但需要實際的前期硬體與維護費用。託管 API 讓成本保持變動且與使用量掛鉤,根據您的使用量以及是否已擁有硬體,成本會較便宜或較昂貴。

不要在應用程式中建立單一的通用成本公式。查詢 /api/v1/videos/models 並閱讀所選模型的 pricing_skus,再顯示估算或提交大型批次。工作完成時,回應可包含 usage 物件,內含該生成的實際成本:

{
  "usage": {
    "cost": 0.5,
    "is_byok": false
  }
}

在執行大型批次前,先使用目前模型資料估算成本,然後將估算值與已完成工作的實際 usage.cost 值進行比較。這也能協助您發現因較高解析度、較長時長、生成音訊或不同模型所造成的意外變化。

處理失敗而不產生重複工作

失敗的輪詢 請求 與失敗的影片生成 工作 並不相同。即使供應商仍在生成影片,您的應用程式在檢查狀態時仍可能失去連線。如果您立即再次提交提示,兩個工作都可能完成,結果您會得到兩支影片並被收取兩筆費用,雖然只是一個使用者請求。

在提交成功後立即持久化 OpenRouter 工作 ID。一個有用的工作紀錄可能包含以下欄位:

{
  "internal_request_id": "req_9f21",
  "openrouter_job_id": "job-abc123",
  "model": "bytedance/seedance-2.0",
  "status": "pending",
  "attempt_number": 1,
  "submitted_at": "2026-07-27T12:00:00Z",
  "output_location": null,
  "cost": null,
  "error": null
}

當狀態請求因超時、連線錯誤或暫時性伺服器回應失敗時,使用現有的工作 ID 重試狀態請求。僅在工作本身達到 failed、cancelled 或 expired 並且您的應用程式重試策略允許再次嘗試時,才建立新的生成。

將工作重試與輪詢重試分開。輪詢重試會再次檢查相同的工作,而生成重試則會產生一個新的付費工作。限制生成重試次數,並保留同一內部請求所建立的每個工作 ID,這樣在需要調查重複輸出、供應商失敗或意外成本時,您就能擁有完整紀錄。

在輪詢停止擴充套件時使用 Webhook

輪詢 是指令碼、原型與少量工作的良好預設方式。當您的應用程式可能同時執行數百個生成時,它的效率會降低。

若要自動接收結果,提交工作時請包含一個 HTTPS callback_url:

{
  "model": "bytedance/seedance-2.0",
  "prompt": "A paper boat drifting through neon reflections",
  "duration": 4,
  "resolution": "720p",
  "aspect_ratio": "16:9",
  "callback_url": "https://example.com/webhooks/openrouter-video"
}

您可以為單一請求設定回呼,或為工作區設定預設回呼。請求層級的值會優先於工作區預設。

當工作達到終端狀態時,我們會傳送 Webhook。每次傳送都包含一個 X-OpenRouter-Idempotency-Key,例如:

job-abc123-completed

在處理事件前先儲存該值。若 Webhook 再次傳送,您的處理程式即可辨識該工作已被處理,避免重複下載影片或重複啟動下一個工作流程。

當設定了 Webhook 簽名機密時,請求還會包含一個 X-OpenRouter-Signature。在解析或重新序列化之前,請先使用原始請求主體驗證簽名。生產環境的處理程式應該儲存新的工作狀態,快速回傳成功回應,並將下載、轉碼或儲存工作交由背景工作者處理。

在耐久儲存中追蹤併發工作

提交與等待是分離的操作,因此您的應用程式可同時執行多個影片工作。不要為每個工作啟動無限輪詢迴圈。使用受限的工作者池或工作佇列,並控制可同時執行的狀態請求與下載數量。

在 Python 中,您可以使用執行緒池或非同步工作佇列處理有限數量的工作。在 TypeScript 中,受限併發佇列比直接將數千個輪詢承諾傳遞給 Promise.all() 更安全。

實際實作不如以下規則重要:

  1. 在開始輪詢前儲存每個工作 ID。
  2. 限制活躍的輪詢與下載運算元量。
  3. 工作者重啟後恢復未完成的工作。
  4. 不要僅因應用程式重啟就重新提交工作。
  5. 完成後即時將影片移至您自己的儲存。

工作 ID 是您應用程式與已進行中的生成之間的耐久連結。將其視為應用程式狀態的一部分,而非僅存在於單一執行程序中的值。

將上述全部整合

我們已經說明瞭四個步驟,無論你指向哪一個模型,這些步驟都不會改變。你只需要使用 POST /api/v1/videos 提交請求,輪詢 GET /api/v1/videos/{id},同時監控所有四個終端狀態,下載結果,並在想切換不同模型時改變一個字串。

一旦非同步生命週期設定正確,模型就變成一個設定,而非架構決策,無論你使用本文提到的三個模型還是之後新增的任何模型。

如果你想先做一個起點,瀏覽影片模型目錄,可以在決定之前並排檢視價格與功能。

常見問題

OpenRouter 支援影片生成嗎?

是的,透過專用的非同步 API。你將提示送至 POST /api/v1/videos,輪詢 GET /api/v1/videos/{id} 直到狀態為 completed,然後下載結果。支援的模型包括 Seedance、Veo、Wan 等,均透過相同的端點。

如何使用 API 從文字產生影片?

傳送 POST 請求至 /api/v1/videos,包含模型與提示。你會收到一個工作 ID 以及一個 polling_url,而非影片本身。輪詢直到狀態達到 completed,然後從 unsigned_urls 或 /content 端點下載。

如何輪詢非同步影片生成工作?

以約 30 秒為間隔呼叫 GET /api/v1/videos/{id},直到狀態達到終端狀態:completed、failed、cancelled 或 expired。設定一個逾時上限,避免卡住的工作永遠掛起你的流程。

OpenRouter 支援哪些影片模型?

目錄包含 Seedance、Veo、Wan 等模型,且持續擴充。查詢 GET /api/v1/videos/models 可取得目前列表,以及各模型支援的解析度、時長、寬高比與傳遞引數。

我可以在不重寫程式碼的情況下切換影片模型嗎?

可以。請求格式、驗證與輪詢迴圈在所有模型中相同,僅 model 欄位不同。模型特定引數仍透過 provider.options 傳遞給供應商。

在本地生成 AI 影片還是透過 API 更划算?

本地生成在支付硬體費用後,每個片段不再收費,但需要具備強大的 GPU、相依套件管理,以及每個模型族別獨立設定。託管 API 以每次生成收費,且完全省去 GPU 與設定。哪種更便宜取決於你的使用量以及你是否已擁有硬體。

AI 影片生成需要多久?

通常介於三十秒到數分鐘之間,取決於模型、解析度與片長。這也是 API 以非同步方式而非同步呼叫的原因。

影片生成是否符合零資料保留?

不行。非同步檢索步驟需要暫時保留生成的輸出以便下載,因此啟用零資料保留的請求不會被路由至影片生成。

來源:openrouter blog · openrouter.ai