開發者文檔

影片生成

影片是一種非同步任務:送出請求、輪詢任務 ID、擷取結果。內容涵蓋任務逾期,以及計費如何結算。

Submitting a task

影片是本平台上唯一不採取請求-回應模式的呼叫方式。你送出一個 任務,會立即拿回一個識別碼,之後再收取結果。它沒有串流變體, 也沒有阻塞式變體 —— 輪詢是得知結果的唯一途徑。

1import os, requests23response = requests.post(4    "https://www.realrelay.ai/v1/video/generations",5    headers={"Authorization": f"Bearer {os.environ['REALRELAY_API_KEY']}"},6    json={7        "model": "alibaba/wan2.1-t2v-plus",8        "prompt": "A paper boat drifting down a rain gutter",9        "duration": 5,10    },11)1213task_id = response.json()["task_id"]14print(task_id)
1const response = await fetch("https://www.realrelay.ai/v1/video/generations", {2  method: "POST",3  headers: {4    Authorization: `Bearer ${process.env.REALRELAY_API_KEY}`,5    "Content-Type": "application/json",6  },7  body: JSON.stringify({8    model: "alibaba/wan2.1-t2v-plus",9    prompt: "A paper boat drifting down a rain gutter",10    duration: 5,11  }),12});1314const { task_id } = await response.json();15console.log(task_id);
1curl https://www.realrelay.ai/v1/video/generations \2  -H "Authorization: Bearer $REALRELAY_API_KEY" \3  -H "Content-Type: application/json" \4  -d '{5    "model": "alibaba/wan2.1-t2v-plus",6    "prompt": "A paper boat drifting down a rain gutter",7    "duration": 58  }'910# {"task_id": "task_9f2c...", "status": "queued"}

duration、width、 height、fps、 seed 與 image(一個 URL 或 base64 影格,供圖生影片模型使用)都可接受,而 metadata 則原封不動地攜帶廠商專屬欄位。 模型接受哪些時長與解析度因模型而異,並由供應商強制執行, 因此不受支援的組合會在送出時失敗,而不是在任務中失敗。

Polling for status

你拿回的 task_id 是我們的,不是供應商的。 請在你送出時所用的同一路徑上輪詢它:

1import os, time, requests23task_id = "task_9f2c..."4headers = {"Authorization": f"Bearer {os.environ['REALRELAY_API_KEY']}"}56while True:7    task = requests.get(8        f"https://www.realrelay.ai/v1/video/generations/{task_id}",9        headers=headers,10    ).json()1112    if task["status"] in ("completed", "failed"):13        break1415    time.sleep(10)1617if task["status"] == "failed":18    raise RuntimeError(task["error"]["message"])1920print(task["url"], task["format"])
1const task_id = "task_9f2c...";2const headers = {3  Authorization: `Bearer ${process.env.REALRELAY_API_KEY}`,4};56let task;7do {8  await new Promise((resolve) => setTimeout(resolve, 10_000));9  const response = await fetch(10    `https://www.realrelay.ai/v1/video/generations/${task_id}`,11    { headers },12  );13  task = await response.json();14} while (task.status !== "completed" && task.status !== "failed");1516if (task.status === "failed") throw new Error(task.error.message);1718console.log(task.url, task.format);
1curl https://www.realrelay.ai/v1/video/generations/task_9f2c... \2  -H "Authorization: Bearer $REALRELAY_API_KEY"34# in progress:5# {"task_id": "task_9f2c...", "status": "in_progress"}67# finished:8# {9#   "task_id": "task_9f2c...",10#   "status": "completed",11#   "url": "https://...",12#   "format": "mp4",13#   "metadata": { "duration": 5, "fps": 30, "width": 1280, "height": 720 }14# }1516# failed:17# {"task_id": "task_9f2c...", "status": "failed",18#  "error": { "code": 500, "message": "..." }}

status 會依序經過 queued → in_progress → completed,或止於 failed。請以秒為間隔輪詢,而非毫秒: 生成需要多久取決於供應商,輪詢得再頻繁也不會讓它更快完成。

Fetching the result

已完成的任務會帶有一個 url、一個 format,以及一段 metadata 區塊,描述實際產出的內容 —— 真實的時長、影格率與尺寸,這些可能與你所要求的不同。

1{2"task_id": "task_9f2c...",3"status": "completed",4"url": "https://...",5"format": "mp4",6"metadata": { "duration": 5, "fps": 30, "width": 1280, "height": 720 }7}

不要把那個 URL 當成持久的。它可能指向我們自己的代理、直接指向 供應商,或是一段內嵌的 data: 內容,視 模型而定 —— 而在前兩種情況下它會過期。任務完成時就把檔案下載 下來,並自行儲存。

Billing and failures

影片按次呼叫計價,並依你實際生成的內容調整:時長與解析度都是 價格的一部分。送出時會先掛上一筆費用,並在任務結束時結算, 因此最終金額可能與送出當下的估算不同。

  • 以 failed 結束的任務會自動退款。 你不需要主動要求。

  • 在平台的任務逾時時間內未完成的任務 —— 預設為 24 小時 —— 會被標記為 failed,並依同一規則退款。 任務絕不會被永遠擱置。

  • 只送出而從不輪詢,仍然會向你收費:無論你是否收取結果, 工作照樣執行並結算。

各模型的價格請見 目錄。