用一套 REST API 把 AI 视频生成接进你的项目:Omni Flash 对接实战

5 阅读4分钟

最近在做一个营销短视频自动化的小工具,需要在服务端按文案批量产出视频。调研了一圈,最后把生成端交给了 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:99: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))

七、几个工程上的注意点

  1. 轮询间隔:视频生成比图片慢,建议 5s 起步,配合最大超时(比如 5 分钟)兜底,别写成裸死循环。
  2. 错误码区分code200 是成功,0 是业务失败(看 msg),401 是鉴权问题,三类分开处理排查会快很多。
  3. 积分与退款:扣费发生在提交时,失败自动退;批量任务做重试时不用担心重复计费。
  4. 图生视频:先把图片上传到可公网访问的地址,再把 URL 放进 image_urls,配合 prompt 描述运动和镜头即可。

小结

整体对接成本很低:一个创建接口 + 一个查询接口,标准的「提交 - 轮询」异步模型,半小时就能跑通。因为 Omni Flash 本身是网页版(web-based)生成器,模型和算力都在云端,服务端只负责发请求、收 URL,特别适合做批量化、自动化的视频生产管线。需要 Key 的话,登录官网账户页就能拿到自己的那一把,照着上面的代码直接接就行。