最近在做一个营销短视频自动化的小工具,需要在服务端按文案批量产出视频。调研了一圈,最后把生成端交给了 Omni Flash——它是一个网页版(web-based)AI 视频生成器,基于 Google 的视频模型,text-to-video、image-to-video 都支持,16:9 / 9:16 比例随选,模型和算力都在云端。最关键的是它开放了 REST API,可以直接在服务端调用,本地不用跑任何模型。
这篇文章把整个对接流程梳理一遍:从拿 Key、鉴权,到创建任务、轮询结果,附 Node.js 和 Python 两份能直接跑的代码。
一、先拿到 API Key
接口走 Bearer Token 鉴权,所以第一步是拿自己的 Key。
打开 Omni Flash 官网,登录后进入账户页(account),就能生成并复制属于你的 API Key,形如 sk-xxxxxxxxxxxxxxxx。建议存进环境变量,别硬编码进代码里:
export OMNI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
二、鉴权方式
所有请求都在 Header 里带上 Token:
Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Key 缺失或无效会直接返回 401。
三、可用模型
接口是多模型设计,靠一个 model_id 字段切换不同能力:
| Model ID | 能力 | 产物 |
|---|---|---|
| omni-flash | 文/图生视频 | video_url |
| omni-pro | 文/图生视频 | video_url |
| seedance-2 | 文/图生视频 | video_url |
| gpt-image-2 | 文/图生图 | image_url |
| nano-banana-2 | 文/图生图 | image_url |
视频类输出 video_url,图像类输出 image_url。
四、创建任务
POST /api/v1/tasks/create
请求体:
{
"model_id": "omni-flash",
"prompt": "a serene zen garden at sunrise, ultra detailed",
"image_urls": [],
"aspect_ratio": "16:9"
}
字段说明:
model_id(必填):选用的模型prompt:文本描述image_urls:图生视频 / 图生图时传入的图片地址数组,纯文生留空aspect_ratio:输出比例,如16:9、9:16
响应:
{
"code": 200,
"msg": "提交成功,等待生成",
"data": {
"task_id": "abcdef123456",
"request_id": "kie_xxxxxxxxxxxx",
"credits": 15
}
}
注意:这是异步接口,提交成功只代表任务进了队列,真正的产物要靠下一步轮询拿。credits 是这次任务扣的积分。
五、轮询查询结果
GET /api/v1/tasks/{task_id}
{
"code": 200,
"msg": "ok",
"data": {
"task_id": "abcdef123456",
"task_status": 3,
"task_type": "video",
"model_id": "omni-flash",
"image_url": null,
"video_url": "https://your-cdn.com/result.mp4",
"audio_url": null,
"credits": 15,
"created_at": 1730000000
}
}
task_status 状态机:
| 值 | 含义 |
|---|---|
| 1 | 排队中 |
| 2 | 生成中 |
| 3 | 成功 |
| 4 | 失败 |
拿到 3 就去对应的 video_url / image_url 取产物;4 表示失败。有个细节挺贴心:失败的任务会自动退还积分,所以重试逻辑不用担心重复扣费。
六、完整示例
Node.js
const BASE = "https://omniflash.net/api/v1";
const KEY = process.env.OMNI_API_KEY;
const headers = {
"Authorization": `Bearer ${KEY}`,
"Content-Type": "application/json",
};
async function createTask(prompt) {
const res = await fetch(`${BASE}/tasks/create`, {
method: "POST",
headers,
body: JSON.stringify({
model_id: "omni-flash",
prompt,
image_urls: [],
aspect_ratio: "16:9",
}),
});
const json = await res.json();
if (json.code !== 200) throw new Error(json.msg);
return json.data.task_id;
}
async function waitForResult(taskId, { interval = 5000, timeout = 300000 } = {}) {
const start = Date.now();
while (Date.now() - start < timeout) {
const res = await fetch(`${BASE}/tasks/${taskId}`, { headers });
const { data } = await res.json();
if (data.task_status === 3) return data.video_url || data.image_url;
if (data.task_status === 4) throw new Error("生成失败");
await new Promise((r) => setTimeout(r, interval));
}
throw new Error("轮询超时");
}
(async () => {
const id = await createTask("a serene zen garden at sunrise, ultra detailed");
const url = await waitForResult(id);
console.log("产物地址:", url);
})();
Python
import os, time, requests
BASE = "https://omniflash.net/api/v1"
HEADERS = {
"Authorization": f"Bearer {os.environ['OMNI_API_KEY']}",
"Content-Type": "application/json",
}
def create_task(prompt: str) -> str:
r = requests.post(f"{BASE}/tasks/create", headers=HEADERS, json={
"model_id": "omni-flash",
"prompt": prompt,
"image_urls": [],
"aspect_ratio": "16:9",
})
data = r.json()
if data["code"] != 200:
raise RuntimeError(data["msg"])
return data["data"]["task_id"]
def wait_for_result(task_id: str, interval=5, timeout=300) -> str:
start = time.time()
while time.time() - start < timeout:
data = requests.get(f"{BASE}/tasks/{task_id}", headers=HEADERS).json()["data"]
if data["task_status"] == 3:
return data["video_url"] or data["image_url"]
if data["task_status"] == 4:
raise RuntimeError("生成失败")
time.sleep(interval)
raise TimeoutError("轮询超时")
if __name__ == "__main__":
tid = create_task("a serene zen garden at sunrise, ultra detailed")
print("产物地址:", wait_for_result(tid))
七、几个工程上的注意点
- 轮询间隔:视频生成比图片慢,建议 5s 起步,配合最大超时(比如 5 分钟)兜底,别写成裸死循环。
- 错误码区分:
code为200是成功,0是业务失败(看msg),401是鉴权问题,三类分开处理排查会快很多。 - 积分与退款:扣费发生在提交时,失败自动退;批量任务做重试时不用担心重复计费。
- 图生视频:先把图片上传到可公网访问的地址,再把 URL 放进
image_urls,配合prompt描述运动和镜头即可。
小结
整体对接成本很低:一个创建接口 + 一个查询接口,标准的「提交 - 轮询」异步模型,半小时就能跑通。因为 Omni Flash 本身是网页版(web-based)生成器,模型和算力都在云端,服务端只负责发请求、收 URL,特别适合做批量化、自动化的视频生产管线。需要 Key 的话,登录官网账户页就能拿到自己的那一把,照着上面的代码直接接就行。