동영상
비동기 작업 모델을 사용하여 비디오 클립을 생성합니다. 프롬프트를 제출하고, 상태를 폴링하고, 결과를 가져옵니다.
비디오 생성은 비동기 방식입니다: prompt를 제출하고, task id를 받고, 그 status를 polling한 다음, 완성된 클립을 가져옵니다. text-to-video, image-to-video, reference 모드 모두 하나의 request 형태를 공유합니다.
요청할 수 있는 길이, 해상도, aspect ratio는 선택한 모델에 따라 달라집니다 — 고정된 집합을 가정하지 말고 models endpoint에서 다시 읽어오세요.
비디오 생성은 백그라운드에서 실행되며 스트리밍 렌더링이 없습니다. 흐름은 항상 다음과 같습니다. 작업 생성 → 상태 폴링 → MP4 다운로드. 작업은 24시간 후에 만료됩니다.
1. 작업 만들기
작업을 제출하고 task ID를 반환합니다. 비용은 길이 × 모델의 초당 가격으로 추정되며 작업이 처리될 때 정산됩니다.
https://api.airforce/v1/video/generations비디오 모델
…· live| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Required | Video model ID. Use /v1/models and filter by output_modalities.includes("video"). |
| prompt | string | Required | Scene description. |
| mode | string | Optional | "text" (default), "image" (animate a first-frame image), "reference" (style transfer from one or more frames). |
| duration_seconds | integer | Optional | Clip length. Range depends on the model — typically 5, 8 or 10 s. Defaults to the model's minimum. |
| aspect_ratio | string | Optional | "16:9", "9:16", "1:1", "4:3" — must be in the model's supported list. |
| quality | string | Optional | "480p", "720p", "1080p" — must be in the model's supported list. |
| input_images | array | Optional | [{ url? } | { b64_json? }] — required for "image" and "reference" modes. |
그 외의 모든 키(예: seed, sound)는 업스트림 제공자에게 있는 그대로 전달됩니다 — 여기서 검증되지 않으며 지원 여부는 모델에 따라 다릅니다.
예
텍스트-비디오
curl https://api.airforce/v1/video/generations \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "wan-2.6",
"prompt": "A red fox darting across snowy hills at dawn",
"duration_seconds": 8,
"aspect_ratio": "16:9",
"quality": "720p",
"sound": true
}'이미지-비디오(첫 번째 프레임)
curl https://api.airforce/v1/video/generations \
-H "Authorization: Bearer sk-air-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-1",
"mode": "image",
"prompt": "Camera pulls back as the dragon takes off",
"duration_seconds": 5,
"aspect_ratio": "16:9",
"input_images": [{"url": "https://example.com/dragon.jpg"}]
}'응답
| Parameter | Type | Required | Description |
|---|---|---|---|
| task_id | string | Optional | Persistent task identifier. Use it on every follow-up endpoint. |
| status | string | Optional | "queued" right after creation. |
| model | string | Optional | Echo of requested model. |
| created | integer | Optional | Unix timestamp. |
| expires_at | integer | Optional | Unix timestamp after which the result is purged (exactly created + 86400). |
| progress | integer | Optional | 0 right after creation. |
| cost_cents | number | Optional | Estimated cost for the job. Final billing is settled when the job is processed. |
{
"task_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "queued",
"model": "wan-2.6",
"created": 1715000000,
"expires_at": 1715086400,
"progress": 0,
"cost_cents": 320
}2. 상태 폴링
5~15초마다 폴링합니다. 작업은 일반적으로 기간과 모델에 따라 30초~4분 내에 완료됩니다. 상태가 "완료"로 전환되면 동일한 엔드포인트가 결과 URL을 반환합니다.
https://api.airforce/v1/video/tasks/:task_id| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | Optional | "queued" | "processing" | "completed" | "failed" | "expired". |
| progress | integer | Optional | 0–100 while processing. |
| result_url | string | Optional | MP4 download URL once status is "completed", set by the upstream provider. Valid until expires_at. |
| error | string | Optional | Failure message. Set (non-null) when status is "failed". |
| cost_cents | number | Optional | Cost for the job, settled when it is processed. |
{
"task_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "completed",
"progress": 100,
"result_url": "https://.../video.mp4",
"model": "wan-2.6",
"duration_seconds": 8,
"expires_at": 1715086400,
"cost_cents": 320
}2b. 스트림 진행(선택사항)
서버에서 보낸 이벤트 스트림을 사용하여 폴링 루프를 건너뜁니다. 진행률 변경당 하나의 이벤트를 내보내고 작업이 종료 상태가 되면 닫힙니다. GET 엔드포인트와 동일한 페이로드 형태.
https://api.airforce/v1/video/tasks/:task_id/streamevent: state
data: {"task_id":"f47ac10b-...","status":"processing","progress":12}
event: state
data: {"task_id":"f47ac10b-...","status":"processing","progress":58}
event: state
data: {"task_id":"f47ac10b-...","status":"completed","progress":100,"result_url":"https://.../video.mp4"}
event: done
data: [DONE]3. 나열 및 삭제
https://api.airforce/v1/video/tasks최근 작업을 반환합니다(최신 작업부터). 대시보드에서 기록 보기를 렌더링하는 데 유용합니다.
가장 최근 task를 최대 100개까지 최신순으로 { "data": [ ...tasks ] } 형태로 반환합니다. 쿼리 매개변수는 없으니 — 클라이언트 측에서 필터링하고 페이지를 매기세요.
curl https://api.airforce/v1/video/tasks \
-H "Authorization: Bearer sk-air-YOUR_API_KEY"https://api.airforce/v1/video/tasks/:task_id작업 기록을 기록에서 제거합니다.
멱등적입니다 — 항상 { "deleted": true }를 반환합니다. 이는 사용자의 기록 항목만 삭제하며, 저장된 미디어를 별도로 제거하지는 않습니다.
비용 및 제약
각 비디오 모델은 읽을 수 있는 기능 메타데이터를 노출합니다. /v1/models:
| Parameter | Type | Required | Description |
|---|---|---|---|
| video_caps.aspect_ratios | array | Optional | Allowed aspect_ratio values. |
| video_caps.qualities | array | Optional | Allowed quality values. |
| video_caps.min_duration_s / max_duration_s | integer | Optional | Allowed range for duration_seconds. |
| video_caps.modes | array | Optional | Subset of ["text", "image", "reference"] supported. |
| video_caps.price_per_second_cents | integer | Optional | Cost = duration_seconds × this value. |
- Cost is estimated at creation and settled when the job is processed; failed or expired tasks are not charged.
- Max 4 concurrent video tasks per API key.
- Result URLs are pre-signed and stop working at
expires_at. Download or copy the MP4 to your own storage if you need it longer.
엔드투엔드 스크립트
async function generateVideo(prompt) {
const create = await fetch('https://api.airforce/v1/video/generations', {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'wan-2.6',
prompt,
duration_seconds: 8,
aspect_ratio: '16:9',
quality: '720p',
}),
}).then(r => r.json());
const { task_id } = create;
// Poll until done.
while (true) {
await new Promise(r => setTimeout(r, 8_000));
const task = await fetch(
`https://api.airforce/v1/video/tasks/${task_id}`,
{ headers: { Authorization: `Bearer ${API_KEY}` } },
).then(r => r.json());
if (task.status === 'completed') return task.result_url;
if (task.status === 'failed' || task.status === 'expired') {
throw new Error(task.error ?? task.status);
}
}
}