본문으로 이동
CHINZYSUPER INTELLIGENCE INFRASTRUCTURE
콘솔 ↗

API 가이드

영상 생성

영상 작업: 제출, 조회, 다운로드

영상은 비동기이며 제출 시 작업 ID를 반환합니다. 생성에 사용한 동일 API 키로 조회하고 성공 후 결과 URL을 읽으세요. Studio H3 영상과 Seedance API는 별도 생성 경로입니다.

요청 및 출력

model과 content는 필수입니다. ratio, duration, generate_audio, seed는 모델 지원에 맞춰 설정하세요. content는 텍스트·이미지·영상·음성 블록을 포함할 수 있습니다. 제한과 예제는 아래 참조를 확인하세요.

결과 저장 및 과금

영상 링크에는 만료 시간이 있으니 바로 저장하세요. 공급자가 보고한 토큰 사용량으로 첫 성공 조회 시 한 번 정산합니다. 반복 조회는 중복 과금하지 않습니다. 가격은 실시간 목록을 참고하세요.

코드의 필드명, 모델 별칭, API 경로는 개발에 사용하도록 원문을 유지합니다.

전체 기술 참조 (영어)

Reference

Generate video

Video models work differently from chat completions. Generation is asynchronous: you submit a task, get back a task id, and poll for the result. Currently the only video model is doubao-seedance-2-0-pro (ByteDance Seedance 2.0 Pro on Volcengine Ark).

1. Endpoints

MethodPathPurpose
POSThttps://chinzy.com/v1/videos/tasksSubmit a generation task. Returns { "id": "cgt-..." } immediately.
GEThttps://chinzy.com/v1/videos/tasks/{taskId}Poll task status. Returns the upstream payload verbatim.

Both endpoints take the same Authorization: Bearer tsk_... header you use with chat completions. See Use your API key if you don't have a key yet.

Task lifecycle. Status moves through queued → running → succeeded (or failed, cancelled, expired). Typical render time is 60–180 seconds for a 4-second 720p clip.

2. Submit a task

curl

curl https://chinzy.com/v1/videos/tasks \
  -H "Authorization: Bearer $TOKEN_RELAY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2-0-pro",
    "content": [
      {"type": "text", "text": "a calm sunset over rolling hills --rs 720p --dur 4"}
    ],
    "ratio": "16:9"
  }'

Request fields

FieldTypeNotes
modelstringRequired. Use doubao-seedance-2-0-pro. (Other video aliases will appear here as they ship.)
contentarrayRequired. Each item is a typed block: text, image_url, video_url, or audio_url. Inline base64 data URLs are accepted.
ratiostringAspect ratio: 16:9, 9:16, 4:3, 3:4, 21:9, 1:1, or adaptive.
resolutionstring480p, 720p, 1080p, or 2K. You can also pass it inline in the prompt as --rs 1080p.
durationnumber4–15 seconds. Inline form: --dur 5.
generate_audiobooleanWhether to render an audio track alongside the video.
seednumberOptional reproducibility seed.

3. Poll until done

# poll-loop.sh
TASK_ID="cgt-..."

while true; do
  RESP=$(curl -s "https://chinzy.com/v1/videos/tasks/$TASK_ID" \
    -H "Authorization: Bearer $TOKEN_RELAY_KEY")
  STATUS=$(echo "$RESP" | jq -r .status)
  echo "[\$(date +%T)] $STATUS"
  case "$STATUS" in
    succeeded)
      echo "$RESP" | jq -r .content.video_url
      break
      ;;
    failed|cancelled|expired)
      echo "$RESP" | jq -r .error
      exit 1
      ;;
  esac
  sleep 10
done

Python

import os, time, requests

BASE = "https://chinzy.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['TOKEN_RELAY_KEY']}"}

def submit(prompt: str, *, ratio="16:9", resolution="720p", duration=4):
    r = requests.post(f"{BASE}/videos/tasks", headers=HEADERS, json={
        "model": "doubao-seedance-2-0-pro",
        "content": [{"type": "text", "text": prompt}],
        "ratio": ratio, "resolution": resolution, "duration": duration,
    })
    r.raise_for_status()
    return r.json()["id"]

def wait(task_id: str, *, timeout=600, interval=10):
    deadline = time.time() + timeout
    while time.time() < deadline:
        r = requests.get(f"{BASE}/videos/tasks/{task_id}", headers=HEADERS)
        r.raise_for_status()
        body = r.json()
        if body["status"] == "succeeded":
            return body["content"]["video_url"]
        if body["status"] in ("failed", "cancelled", "expired"):
            raise RuntimeError(body.get("error") or body["status"])
        time.sleep(interval)
    raise TimeoutError(task_id)

task_id = submit("a calm sunset over rolling hills")
url = wait(task_id)
print(url)

Node.js

const BASE = 'https://chinzy.com/v1';
const headers = { Authorization: `Bearer ${process.env.TOKEN_RELAY_KEY}` };

async function submit(prompt) {
  const r = await fetch(`${BASE}/videos/tasks`, {
    method: 'POST',
    headers: { ...headers, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model: 'doubao-seedance-2-0-pro',
      content: [{ type: 'text', text: prompt }],
      ratio: '16:9',
      resolution: '720p',
      duration: 4,
    }),
  });
  if (!r.ok) throw new Error(await r.text());
  return (await r.json()).id;
}

async function wait(taskId, { interval = 10_000, timeoutMs = 600_000 } = {}) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const r = await fetch(`${BASE}/videos/tasks/${taskId}`, { headers });
    if (!r.ok) throw new Error(await r.text());
    const body = await r.json();
    if (body.status === 'succeeded') return body.content.video_url;
    if (['failed', 'cancelled', 'expired'].includes(body.status)) {
      throw new Error(body.error?.message ?? body.status);
    }
    await new Promise((res) => setTimeout(res, interval));
  }
  throw new Error('timeout');
}

const taskId = await submit('a calm sunset over rolling hills');
console.log(await wait(taskId));

4. The video URL

On succeeded the response includes content.video_url — a direct MP4 link to ByteDance object storage. Two things to know about it:

  • It expires after 24 hours. Download or re-host the file inside that window. Don't store the signed URL itself long-term.
  • It bypasses the relay. The download is direct client-to-Volcengine; we never see those bytes, so no relay bandwidth or wallet charge applies to fetching the result.

5. Pricing & metering

Video is billed by tokens, the same way the chat models are. The token count is reported in the usage.total_tokens field of the succeeded response. As a rough guide, a 4-second 720p clip is ≈ 87,000 tokens (~¥0.58 at the current resale rate). 1080p and longer clips scale roughly linearly.

Settlement happens at the moment of the first poll that observes succeeded. Subsequent polls are free — the relay idempotently skips re-charging a task it has already settled.

6. Ownership & access

A task is bound to the API key that created it. The video URL is only retrievable by the same key, for 7 days. After 7 days the task itself falls out of the upstream history and the relay returns 404; download anything you need before then.

7. Common errors

StatusMeaningFix
400Body missing model or content, or one of them is malformed.Confirm content is a non-empty array of typed blocks.
403 (on GET)You're polling a task created by a different API key.Use the same key that created the task. If you rotated keys, re-submit the task.
404Task id is unknown to the relay (typo, expired after 7 days, or created against a different deployment).Resubmit; verify the id matches the one returned at create.
503The Volcengine Ark backend is unavailable, or DOUBAO_API_KEY isn't configured on this deployment.Retry with backoff; if persistent, check your status page.

Found something missing or wrong in this doc? Open an issue or ping an admin.