AI 视频
文生视频生成,支持状态轮询与取消。
1. 概览
https://api.infrai.cc/v1/videoAuthorization: Bearer $INFRAI_API_KEY# Call any /v1/video capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/video/... \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json"2. 方法 (7)
2.1video.generate
启动一个文生视频任务。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
prompt | string | 必填 | 目标视频的文本描述。 |
reference_image | string | 可选 | 可选参考图像 URL。 |
duration_seconds | number | 可选 | 片段时长(秒)。1–60default: 5 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | 可选 | 宽高比。default: "16:9" |
resolution | "720p" | "1080p" | "4k" | 可选 | 输出分辨率(720p/1080p/4k);按供应商能力门控。default: "720p" |
model | string | 可选 | 路由模式(auto / cheapest / smartest)让 infrai 自动选型,或直接指定模型 id 以锁定(如 "kling-v2"、"wan-t2v")。省略即 auto。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
VideoJob { job_id, state, video_url?, thumbnail_url?, error? }| 名称 | 类型 | 说明 |
|---|---|---|
job_id | string | async job的唯一标识符pattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | 当前生命周期状态 |
model | string | 用于生成的模型标识符 |
vendor | string | 处理此请求的供应商 |
prompt | string | 内容生成的文本提示 |
duration_seconds | integer | 生成视频时长(秒)≥ 1 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | 生成的图片或视频的宽高比(如 16:9) |
video_url | string | null | 生成的视频文件 URL |
thumbnail_url | string | null | 视频缩略图 URL |
cost_usd | number | null | 本次操作费用(美元)≥ 0 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
finished_at | string | null | ISO 8601 时间戳:the job finished(ISO 8601)format: date-time |
retention_days | integer | null | days to retain this resource数量≥ 0 |
parent_job_id | string | null | 衍生此作业的源作业(通过 video.extend / video.upscale / webhook 重跑派生);原始生成作业为 null。pattern: ^vid_[A-Za-z0-9]{20,}$ |
error | object | 供应商/网关错误详情;仅在 state 为 failed 时存在。 |
error.code | string | 来自 registry.yaml 的稳定标识符。 |
error.http_status | integer | Webhook 投递尝试的 HTTP 状态码400–599 |
error.message | string | 可读提示。 |
error.docs_url | string | 此错误码的文档 URLformat: uri |
error.code_detail | string | 子分类(如钱包上限原因)。 |
error.retryable | boolean | 错误是否可重试 |
error.retry_after_ms | integer | 建议重试延迟(毫秒)≥ 0 |
error.param | string | 验证失败的参数(如适用)。 |
error.trace_id | string | 分布式追踪标识符 |
error.request_id | string | 服务端分配的追踪请求标识符 |
metadata | object | 本次生成的成本/供应商/模型披露(成本透明契约面);选定供应商后存在。 |
metadata.request_id | string | UUID v7。 |
metadata.trace_id | string | 分布式追踪标识符 |
metadata.timestamp | string | 数据点的 Unix 时间戳format: date-time |
metadata.latency_ms | integer | 操作延迟(毫秒)≥ 0 |
metadata.entry_form | any | 入口格式(rest、mcp、sdk) |
metadata.cost_usd | number | 此操作成本(美元)≥ 0 |
metadata.cost_cny | number | 此请求成本(人民币)≥ 0 |
metadata.vendor | string | 适配器名称;引用 VendorRegistry。 |
metadata.vendor_region | "china" | "western" | 处理此请求的供应商区域 |
metadata.markup_pct | 0 | 0.05 | 供应商成本之上的加价百分比 |
metadata.cache_layer | "none" | "l1_hit" | "l1_miss" | "l2_hit" | "batch" | 服务此响应的缓存层 |
metadata.failover_info | object | 使用不同供应商时的故障转移详情 |
metadata.failover_info.primary_vendor | string | 尝试调用的主供应商 |
metadata.failover_info.actual_vendor | string | 实际处理请求的供应商(故障转移后) |
metadata.failover_info.primary_model | string | 尝试调用的主模型 |
metadata.failover_info.actual_model | string | 实际处理请求的模型(故障转移后) |
metadata.failover_info.cost_at_primary | number | 主供应商成本(美元)≥ 0 |
metadata.failover_info.cost_at_actual | number | 实际供应商成本(美元)≥ 0 |
metadata.failover_info.cost_multiplier | number | 故障转移导致的成本倍数≥ 0 |
metadata.failover_info.failover_reason | "VENDOR_TIMEOUT" | "VENDOR_DOWN" | "RATE_LIMIT_VENDOR" | "VENDOR_AUTH_ERROR" | 故障转移原因 |
metadata.failover_info.fallback_chain_depth | integer | 已遍历的故障转移链深度≥ 1 |
metadata.edge_pop | string | 服务此请求的地理 PoP。 |
metadata.worker_id | string | 处理此请求的 Worker 进程标识符 |
metadata.idempotent_replay | boolean | 为 true 表示此次写入复用了先前的幂等结果(Idempotency-Key 重放)。由网关设置;SDK 必须从 metadata 读取,而不是读取 header。 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/video/generate \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "hello"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/generate",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'prompt': 'hello'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "hello"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "hello"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"prompt": "hello"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/video/generate", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/generate"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"prompt\": \"hello\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/video/generate");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"prompt\": \"hello\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/generate");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"prompt\": \"hello\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/generate")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"prompt": "hello"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/video/generate")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"prompt": "hello"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.2video.status
轮询视频任务的状态。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | 任务标识。 |
返回
VideoJob| 名称 | 类型 | 说明 |
|---|---|---|
job_id | string | async job的唯一标识符pattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | 当前生命周期状态 |
progress_pct | integer | null | 异步操作进度百分比(0-100)0–100 |
eta_seconds | integer | null | 预估完成耗时(秒)≥ 0 |
current_step | string | null | 当前处理步骤的描述 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/status/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/status/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/status/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/status/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/status/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/status/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/status/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/status/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.3video.cancel
取消正在运行的视频任务。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | 任务标识。 |
返回
{ ok: boolean }| 名称 | 类型 | 说明 |
|---|---|---|
job_id | string | async job的唯一标识符pattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | 当前生命周期状态 |
model | string | 用于生成的模型标识符 |
vendor | string | 处理此请求的供应商 |
prompt | string | 内容生成的文本提示 |
duration_seconds | integer | 生成视频时长(秒)≥ 1 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | 生成的图片或视频的宽高比(如 16:9) |
video_url | string | null | 生成的视频文件 URL |
thumbnail_url | string | null | 视频缩略图 URL |
cost_usd | number | null | 本次操作费用(美元)≥ 0 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
finished_at | string | null | ISO 8601 时间戳:the job finished(ISO 8601)format: date-time |
retention_days | integer | null | days to retain this resource数量≥ 0 |
parent_job_id | string | null | 衍生此作业的源作业(通过 video.extend / video.upscale / webhook 重跑派生);原始生成作业为 null。pattern: ^vid_[A-Za-z0-9]{20,}$ |
error | object | 供应商/网关错误详情;仅在 state 为 failed 时存在。 |
error.code | string | 来自 registry.yaml 的稳定标识符。 |
error.http_status | integer | Webhook 投递尝试的 HTTP 状态码400–599 |
error.message | string | 可读提示。 |
error.docs_url | string | 此错误码的文档 URLformat: uri |
error.code_detail | string | 子分类(如钱包上限原因)。 |
error.retryable | boolean | 错误是否可重试 |
error.retry_after_ms | integer | 建议重试延迟(毫秒)≥ 0 |
error.param | string | 验证失败的参数(如适用)。 |
error.trace_id | string | 分布式追踪标识符 |
error.request_id | string | 服务端分配的追踪请求标识符 |
metadata | object | 本次生成的成本/供应商/模型披露(成本透明契约面);选定供应商后存在。 |
metadata.request_id | string | UUID v7。 |
metadata.trace_id | string | 分布式追踪标识符 |
metadata.timestamp | string | 数据点的 Unix 时间戳format: date-time |
metadata.latency_ms | integer | 操作延迟(毫秒)≥ 0 |
metadata.entry_form | any | 入口格式(rest、mcp、sdk) |
metadata.cost_usd | number | 此操作成本(美元)≥ 0 |
metadata.cost_cny | number | 此请求成本(人民币)≥ 0 |
metadata.vendor | string | 适配器名称;引用 VendorRegistry。 |
metadata.vendor_region | "china" | "western" | 处理此请求的供应商区域 |
metadata.markup_pct | 0 | 0.05 | 供应商成本之上的加价百分比 |
metadata.cache_layer | "none" | "l1_hit" | "l1_miss" | "l2_hit" | "batch" | 服务此响应的缓存层 |
metadata.failover_info | object | 使用不同供应商时的故障转移详情 |
metadata.failover_info.primary_vendor | string | 尝试调用的主供应商 |
metadata.failover_info.actual_vendor | string | 实际处理请求的供应商(故障转移后) |
metadata.failover_info.primary_model | string | 尝试调用的主模型 |
metadata.failover_info.actual_model | string | 实际处理请求的模型(故障转移后) |
metadata.failover_info.cost_at_primary | number | 主供应商成本(美元)≥ 0 |
metadata.failover_info.cost_at_actual | number | 实际供应商成本(美元)≥ 0 |
metadata.failover_info.cost_multiplier | number | 故障转移导致的成本倍数≥ 0 |
metadata.failover_info.failover_reason | "VENDOR_TIMEOUT" | "VENDOR_DOWN" | "RATE_LIMIT_VENDOR" | "VENDOR_AUTH_ERROR" | 故障转移原因 |
metadata.failover_info.fallback_chain_depth | integer | 已遍历的故障转移链深度≥ 1 |
metadata.edge_pop | string | 服务此请求的地理 PoP。 |
metadata.worker_id | string | 处理此请求的 Worker 进程标识符 |
metadata.idempotent_replay | boolean | 为 true 表示此次写入复用了先前的幂等结果(Idempotency-Key 重放)。由网关设置;SDK 必须从 metadata 读取,而不是读取 header。 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/video/cancel/ID \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "sample"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/cancel/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'job_id': 'sample'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"job_id": "sample"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/video/cancel/ID", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/cancel/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"job_id\": \"sample\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/video/cancel/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"job_id\": \"sample\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/cancel/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"job_id\": \"sample\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/cancel/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"job_id": "sample"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/video/cancel/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"job_id": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.4video.get
获取视频任务的完整详情(状态、视频地址、时长、分辨率、厂商、模型等)。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | 任务标识。 |
返回
VideoJob { job_id, state, video_url?, thumbnail_url?, duration_seconds, resolution, vendor, model, error? }| 名称 | 类型 | 说明 |
|---|---|---|
job_id | string | async job的唯一标识符pattern: ^vid_[A-Za-z0-9]{20,}$ |
state | "queued" | "running" | "succeeded" | "failed" | "cancelled" | "expired" | 当前生命周期状态 |
model | string | 用于生成的模型标识符 |
vendor | string | 处理此请求的供应商 |
prompt | string | 内容生成的文本提示 |
duration_seconds | integer | 生成视频时长(秒)≥ 1 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | 生成的图片或视频的宽高比(如 16:9) |
video_url | string | null | 生成的视频文件 URL |
thumbnail_url | string | null | 视频缩略图 URL |
cost_usd | number | null | 本次操作费用(美元)≥ 0 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
finished_at | string | null | ISO 8601 时间戳:the job finished(ISO 8601)format: date-time |
retention_days | integer | null | days to retain this resource数量≥ 0 |
parent_job_id | string | null | 衍生此作业的源作业(通过 video.extend / video.upscale / webhook 重跑派生);原始生成作业为 null。pattern: ^vid_[A-Za-z0-9]{20,}$ |
error | object | 供应商/网关错误详情;仅在 state 为 failed 时存在。 |
error.code | string | 来自 registry.yaml 的稳定标识符。 |
error.http_status | integer | Webhook 投递尝试的 HTTP 状态码400–599 |
error.message | string | 可读提示。 |
error.docs_url | string | 此错误码的文档 URLformat: uri |
error.code_detail | string | 子分类(如钱包上限原因)。 |
error.retryable | boolean | 错误是否可重试 |
error.retry_after_ms | integer | 建议重试延迟(毫秒)≥ 0 |
error.param | string | 验证失败的参数(如适用)。 |
error.trace_id | string | 分布式追踪标识符 |
error.request_id | string | 服务端分配的追踪请求标识符 |
metadata | object | 本次生成的成本/供应商/模型披露(成本透明契约面);选定供应商后存在。 |
metadata.request_id | string | UUID v7。 |
metadata.trace_id | string | 分布式追踪标识符 |
metadata.timestamp | string | 数据点的 Unix 时间戳format: date-time |
metadata.latency_ms | integer | 操作延迟(毫秒)≥ 0 |
metadata.entry_form | any | 入口格式(rest、mcp、sdk) |
metadata.cost_usd | number | 此操作成本(美元)≥ 0 |
metadata.cost_cny | number | 此请求成本(人民币)≥ 0 |
metadata.vendor | string | 适配器名称;引用 VendorRegistry。 |
metadata.vendor_region | "china" | "western" | 处理此请求的供应商区域 |
metadata.markup_pct | 0 | 0.05 | 供应商成本之上的加价百分比 |
metadata.cache_layer | "none" | "l1_hit" | "l1_miss" | "l2_hit" | "batch" | 服务此响应的缓存层 |
metadata.failover_info | object | 使用不同供应商时的故障转移详情 |
metadata.failover_info.primary_vendor | string | 尝试调用的主供应商 |
metadata.failover_info.actual_vendor | string | 实际处理请求的供应商(故障转移后) |
metadata.failover_info.primary_model | string | 尝试调用的主模型 |
metadata.failover_info.actual_model | string | 实际处理请求的模型(故障转移后) |
metadata.failover_info.cost_at_primary | number | 主供应商成本(美元)≥ 0 |
metadata.failover_info.cost_at_actual | number | 实际供应商成本(美元)≥ 0 |
metadata.failover_info.cost_multiplier | number | 故障转移导致的成本倍数≥ 0 |
metadata.failover_info.failover_reason | "VENDOR_TIMEOUT" | "VENDOR_DOWN" | "RATE_LIMIT_VENDOR" | "VENDOR_AUTH_ERROR" | 故障转移原因 |
metadata.failover_info.fallback_chain_depth | integer | 已遍历的故障转移链深度≥ 1 |
metadata.edge_pop | string | 服务此请求的地理 PoP。 |
metadata.worker_id | string | 处理此请求的 Worker 进程标识符 |
metadata.idempotent_replay | boolean | 为 true 表示此次写入复用了先前的幂等结果(Idempotency-Key 重放)。由网关设置;SDK 必须从 metadata 读取,而不是读取 header。 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/get/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/get/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/get/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/get/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/get/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/get/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/get/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/get/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.5video.delete
删除指定视频任务及其产物(幂等写)。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | 任务标识。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
{ ok: boolean }| 名称 | 类型 | 说明 |
|---|---|---|
job_id | string | null | 受影响的作业;批量操作(delete_all)为 null。pattern: ^vid_[A-Za-z0-9]{20,}$ |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X DELETE https://api.infrai.cc/v1/video/delete/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.delete(
"https://api.infrai.cc/v1/video/delete/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.infrai.cc/v1/video/delete/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/delete/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("DELETE", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("DELETE"), "https://api.infrai.cc/v1/video/delete/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/delete/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/delete/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.delete("https://api.infrai.cc/v1/video/delete/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.6video.download_url
为指定视频任务签发带过期时间的临时下载链接。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | 任务标识。 |
返回
{ url: string, expires_at: string }| 名称 | 类型 | 说明 |
|---|---|---|
job_id | string | async job的唯一标识符pattern: ^vid_[A-Za-z0-9]{20,}$ |
url | string | Infrai 托管的带签名、有时限的下载 URL。format: uri |
expires_at | string | 资源或令牌过期时间(ISO 8601)format: date-time |
size_bytes | integer | null | 资源大小(字节)≥ 0 |
content_type | string | null | 对象的 MIME 类型 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/download_url/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/download_url/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/download_url/ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/download_url/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/download_url/ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/download_url/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/download_url/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/download_url/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.7video.capabilities
查询各视频厂商支持的模型、分辨率、最大时长及扩展/超分能力。
返回
VideoCapabilities { vendors: Array<{ vendor, models, resolutions, max_duration_seconds, supports_extend, supports_upscale }> }| 名称 | 类型 | 说明 |
|---|---|---|
models | object[] | 提供的视频模型,每个定价(供应商、模型)行一个。 |
models[].vendor | string | - |
models[].model | string | - |
models[].region | string | null | - |
models[].max_seconds | integer | null | 供应商适配器强制的最大生成时长(超过则 DURATION_EXCEEDED);适配器不存在时为 null。≥ 1 |
models[].image_to_video | boolean | null | 供应商是否支持图生视频;适配器不存在时为 null。 |
resolutions | ("720p" | "1080p" | "4k")[] | 支持的分辨率键(也是 resolution_multiplier 的键)。 |
resolution_multiplier | object | 按分辨率的成本轴乘数(如 720p=1.0、1080p=2.0、4k=4.0)。 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/video/capabilities \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/capabilities",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/capabilities",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/capabilities",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/video/capabilities", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/video/capabilities"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/video/capabilities");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/video/capabilities");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/video/capabilities")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/video/capabilities")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}高级:指定 vendor
默认情况下 infrai 会把每次调用智能路由到最佳可用供应商——无需自己挑选 vendor。作为高级逃生口,本能力支持可选的 vendor 入参以锁定某个供应商。本能力当前所有可用 vendor 可通过该能力 id 对应的 discovery 端点实时获取——参见 discovery API。
GET /v1/discovery/{capability}video.generate
3. 全部能力
本模块全部已路由能力——完整的对外 REST 契约。上方方法是带讲解的入门示例,此表是完整参考。
video.cancelPOST /v1/video/cancel/{id}Cancel an in-progress video generation job.
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
job_id | string | 必填 | Id of the video job to cancel. |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
video.capabilitiesGET /v1/video/capabilitiesQuery each video provider's supported models, resolutions, max duration, and extend/upscale capabilities.
无请求参数。
video.deleteDELETE /v1/video/delete/{id}Delete a video job and its artifacts (idempotent write).
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
video.download_urlGET /v1/video/download_url/{id}Issue a time-limited, expiring download URL for a video job's output.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
video.generatePOST /v1/video/generateGenerate a video from a text or image prompt asynchronously (idempotent).
参数 (12)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
prompt | string | 必填 | Text prompt for content generation |
model | string | null | 可选 | Model selector. A specific video model id (e.g. 'wan-t2v'), OR a routing MODE: 'auto' (default, balanced value), 'cheapest' (lowest USD/s), 'smartest' (flagship). Null = auto. |
resolution | "720p" | "1080p" | "4k" | 可选 | Output resolution spec axis. Gated per-vendor. (SSOT: enums/VideoResolution)default: "720p" |
duration_seconds | integer | 可选 | Duration of generated video in seconds1–60default: 5 |
aspect_ratio | "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | 可选 | Aspect ratio for generated images or video (e.g. 16:9)default: "16:9" |
seed | integer | null | 可选 | Random seed for deterministic generation |
negative_prompt | string | null | 可选 | Negative prompt for excluding unwanted content |
reference_image | string | null | 可选 | URL or base64 for image-to-video. |
vendor | string | null | 可选 | Vendor that handled or will handle this request |
webhook_url | string | null | 可选 | Optional callback URL; declares an async delivery target at submit time (events from VideoEventType). Equivalent to a video.webhook.subscribe for this job.format: uri |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
store | boolean | 可选 | Opt in to RETAIN the produced asset/record in Infrai's own store (default false = stateless passthrough: process, return inline, keep nothing). When true, Infrai persists the asset, bills a self-hosted storage line item and applies a retention TTL — and only then do the *.list/get/delete read caps see it.default: false |
video.getGET /v1/video/get/{id}Retrieve a video job's full details (status, video URL, duration, resolution, provider, model).
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
video.statusGET /v1/video/status/{id}Query a video generation job's status and output URL.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
4. 完整示例
本模块的生产级端到端范例:先一次性配置,再运行业务流程,尽量覆盖本模块的多数 API。
单文件可运行 Python 程序(仅标准库、无 SDK):拷贝后填入 INFRAI_API_KEY 运行,即可按真实业务流逐步体验本模块核心 API——每一步都真实调用并计费,后续步骤复用前一步返回的真实字段。12 行 helper 就是全部集成代码。
#!/usr/bin/env python3
"""Infrai · ai-video — runnable real-app example (single file, zero deps).
Copy this file, set your key, run it: every step is a REAL call to
api.infrai.cc, billed at the real (tiny) per-call price, printing the
live JSON response. Get a key at https://infrai.cc/login (Google/
GitHub sign-in grants $2 free credit); add funds at
https://infrai.cc/billing. No SDK — the 12-line helper below is the
entire integration."""
import json
import os
from urllib import error, request
KEY = os.environ.get("INFRAI_API_KEY") or "ifr_..." # <- your key
BASE = "https://api.infrai.cc"
# Same raw HTTPS POST/GET as every per-method example on this page —
# wrapped once for reuse. There is nothing else to it: no SDK.
def infrai(method, path, body=None):
req = request.Request(
BASE + path, method=method,
data=json.dumps(body).encode() if body is not None else None,
headers={"Authorization": f"Bearer {KEY}",
"Content-Type": "application/json"})
try:
with request.urlopen(req, timeout=60) as r:
return json.loads(r.read())
except error.HTTPError as e:
return json.loads(e.read())
def show(label, resp):
print(f"\n== {label} ==")
print(json.dumps(resp, indent=2, ensure_ascii=False))
return resp
# 1) video.generate — POST /v1/video/generate · Generate a video from a text or image prompt asynchronously (idempotent). # NOTE: non-trivial real cost
r1 = show("video.generate", infrai("POST", "/v1/video/generate", {"prompt":"a timelapse of a city skyline at dusk","resolution":"1080p","duration_seconds":5}))
# 2) video.status — GET /v1/video/status/{id} · Query a video generation job's status and output URL.
id_2 = (r1.get("data") or {}).get("job_id") or ""
r2 = show("video.status", infrai("GET", f"/v1/video/status/{id_2}"))
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."# 1) Auth: every call is a raw HTTPS request to the Infrai gateway carrying
# only your project key. No SDK, no install.
# Get your key: sign in with Google/GitHub at https://infrai.cc/login for a
# project key + $2 free credit (email sign-in starts at $0). On 402
# INSUFFICIENT_CREDIT, add funds at https://infrai.cc/billing (or POST
# /v1/account/topup and open the returned checkout_url).
export INFRAI_API_KEY="ifr_..." # from https://infrai.cc/login
# 2) video.generate
curl -X POST https://api.infrai.cc/v1/video/generate \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "a timelapse of a city skyline at dusk", "model": "auto", "resolution": "1080p", "duration_seconds": 5, "aspect_ratio": "16:9"}'
# 3) video.status
curl -X GET https://api.infrai.cc/v1/video/status/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 4) video.cancel
curl -X POST https://api.infrai.cc/v1/video/cancel/ID \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "sample"}'
# 5) video.get
curl -X GET https://api.infrai.cc/v1/video/get/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 6) video.delete
curl -X DELETE https://api.infrai.cc/v1/video/delete/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 7) video.download_url
curl -X GET https://api.infrai.cc/v1/video/download_url/ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 1) Auth: every call is a raw HTTPS request carrying only your project key.
# No SDK to install — just the `requests` library.
import os, requests
BASE = "https://api.infrai.cc"
HEADERS = {
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
"Content-Type": "application/json",
}
# 2) video.generate
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/generate",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'prompt': 'a timelapse of a city skyline at dusk', 'model': 'auto', 'resolution': '1080p', 'duration_seconds': 5, 'aspect_ratio': '16:9'},
)
resp.raise_for_status()
print(resp.json())
# 3) video.status
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/status/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 4) video.cancel
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/video/cancel/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'job_id': 'sample'},
)
resp.raise_for_status()
print(resp.json())
# 5) video.get
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/get/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 6) video.delete
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.delete(
"https://api.infrai.cc/v1/video/delete/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 7) video.download_url
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/video/download_url/ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch().
const BASE = "https://api.infrai.cc";
const HEADERS = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) video.generate
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "a timelapse of a city skyline at dusk", "model": "auto", "resolution": "1080p", "duration_seconds": 5, "aspect_ratio": "16:9"}),
},
);
console.log(await resp.json());
// 3) video.status
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 4) video.cancel
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
console.log(await resp.json());
// 5) video.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 6) video.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 7) video.download_url
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch(), typed.
const BASE = "https://api.infrai.cc";
const HEADERS: Record<string, string> = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) video.generate
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/generate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"prompt": "a timelapse of a city skyline at dusk", "model": "auto", "resolution": "1080p", "duration_seconds": 5, "aspect_ratio": "16:9"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 3) video.status
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/status/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 4) video.cancel
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/cancel/ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"job_id": "sample"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 5) video.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/get/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 6) video.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/delete/ID",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 7) video.download_url
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/video/download_url/ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);