Video generation (per-second models)
Create image-to-video, first/last-frame, reference, avatar and video-tool tasks with POST /v1/videos, poll them, download the result and pay per second of output.
On this page
The video models listed under Models → Video run as asynchronous tasks on POST /v1/videos and are priced per second of output video. You create a task, poll it, then download the file. Failed and cancelled tasks are not charged.
| Step | Request |
|---|---|
| Get a price estimate (optional) | POST /v1/videos with "dry_run": true |
| Create a task | POST /v1/videos |
| Check status | GET /v1/videos/{id} |
| Download | GET /v1/videos/{id}/content |
| Cancel | POST /v1/videos/{id}/cancel |
#Inputs
Image, video and audio inputs are public https:// URLs or base64 data URIs (data:image/png;base64,...), up to 50 MB each and 80 MB for the whole request body.
Video models need a first frame. Pass it as image. If you only have a text idea, create the frame with an image model first and pass its URL. A text-only request returns 400 with "image is required".
#Create a task
curl https://bigmodel.io/v1/videos \
-H "Authorization: Bearer $BIGMODEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: lantern-take-1" \
-d '{
"model": "seedance-2.0-fast",
"prompt": "The lantern drifts slowly to the right, mist moving over the water",
"image": "https://example.com/lantern.png",
"seconds": 5,
"resolution": "720p"
}'import os, time, requests
BASE = "https://bigmodel.io/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['BIGMODEL_API_KEY']}"}
task = requests.post(f"{BASE}/videos", headers={**HEADERS, "Idempotency-Key": "lantern-take-1"}, json={
"model": "seedance-2.0-fast",
"prompt": "The lantern drifts slowly to the right, mist moving over the water",
"image": "https://example.com/lantern.png",
"seconds": 5,
}).json()
while task["status"] in ("queued", "running"):
time.sleep(10)
task = requests.get(f"{BASE}/videos/{task['id']}", headers=HEADERS).json()
print(task["status"], task.get("output", {}).get("url"), task.get("cost_usd"))An accepted task returns 202, a Location header and:
{"id": "6f1c...", "object": "video", "model": "seedance-2.0-fast", "status": "queued", "created_at": 1760000000, "estimated_cost_usd": 0.4272}#Video model fields
| Field | Notes |
|---|---|
model |
Required. |
prompt |
What happens in the shot. |
image |
Required: the first frame. first_frame is accepted as an alias. |
last_frame |
Optional end frame, on models with first/last frame. Needs image. |
reference_images, reference_videos, reference_audios |
Arrays of inputs on models that take references. With references, image counts as one more reference image. |
seconds |
Output length (duration is an alias). Default 5, kept within the model's range. |
resolution |
One of the model's resolutions, such as 720p. Default 720p when the model has it. |
aspect_ratio |
For example 16:9 or 9:16. size like 1280x720 also sets it. |
audio |
true or false on models with native audio. |
seed |
Integer, for repeatable results where the model supports it. |
Each model's range of seconds, resolutions and reference limits is shown in the catalog. A value outside them returns 400 with the allowed values.
#Avatar and video tools
The same endpoint runs avatar and tool models:
| Model | Inputs |
|---|---|
infinitetalk |
image (a portrait) or video (one person), plus input_audio (the voice track) |
latentsync, latentsync-music |
video (one person, face visible) and input_audio |
wan-animate-2 |
image (a person), video (the motion to copy), or both |
video-upscale, seedvr2-upscale |
video; target_resolution 1080p (default) or 2k on video-upscale |
video-to-clay |
video; mode clay_masked (default), clay or sculpt; keep_audio |
Avatar models are charged by the length of the voice track (or the video), tools by the input video's length.
#Estimate the price first
Add "dry_run": true to the same body. Nothing is generated and nothing is charged; inputs are still read so the estimate can use their length.
curl https://bigmodel.io/v1/videos \
-H "Authorization: Bearer $BIGMODEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "seedance-2.0-fast", "image": "https://example.com/lantern.png", "seconds": 5, "dry_run": true}'{"object": "quote", "model": "seedance-2.0-fast", "unit": "per_second", "estimated_units": 5, "estimated_cost_usd": 0.4272}#Retry safely with Idempotency-Key
Send an Idempotency-Key header (up to 200 characters) when you create a task. If the response is lost and you send the request again with the same key and API key, you get the original task back instead of a second generation. Use a new key for each new video.
#Check status and download
curl https://bigmodel.io/v1/videos/TASK_ID \
-H "Authorization: Bearer $BIGMODEL_API_KEY"
curl -L -o video.mp4 https://bigmodel.io/v1/videos/TASK_ID/content \
-H "Authorization: Bearer $BIGMODEL_API_KEY"status is queued, running, succeeded, failed or canceled. Poll every 5 to 15 seconds. While running, progress may show 0–100. A succeeded task has output: {"type": "video", "url": "...", "expires_in": 86400} and cost_usd, the amount charged. A failed task has error.message.
/content redirects (302) to the file; with curl use -L. The link in output.url works without an API key for 24 hours, and each status call returns a fresh one. Save the file if you need it longer. Any API key on the same account can read the task.
POST /v1/videos/TASK_ID/cancel asks the model to stop. The call returns the task; it moves to canceled shortly after, unless it had already finished. Tasks that do not finish within 3 hours end as failed and are not charged.
#How you are charged
When you create a task, your balance must cover the estimate on top of tasks still running. The charge is made when the task succeeds, based on the video actually produced, so cost_usd can differ slightly from estimated_cost_usd. It appears in Usage. Each model's price is on Pricing.
Some video models are priced by output resolution (for example Seedance 2.0 Fast: 480p and 720p differ). Without resolution, 720p is used where the model offers it. Each model page lists the price per resolution, and dry_run quotes the resolution you send.
#Verify the setup
Send the dry-run example with your own first-frame URL. A 200 quote means your key can use the model. Then create the task and poll it until succeeded.
#Troubleshooting
400 "image is required". Video models animate a first frame. Pass image; create one with an image model if needed.
400 "seconds must be between …" or "resolution must be one of …". The value is outside the model's limits. Use one from the message or the catalog.
400 "… could not be read". An input URL is not public https://, or the data URI is malformed or over 50 MB.
402 insufficient_balance. Your balance, minus tasks still running, does not cover the estimate. Top up in Billing.
403 permission_error. The key is not in a group. Assign it to one in API keys.
404 model_not_available. The model is not offered to this key, or it belongs on another endpoint (speech and music use /v1/audio/*).
404 not_found_error. The task ID is wrong or belongs to another account.
409 not_ready on /content. The task has not succeeded yet. Keep polling.
503 api_error. Generation is temporarily unavailable. Retry with the same Idempotency-Key.
#Related
- Image generation to make first frames.
- Text to speech for voice tracks for avatar models.
- Music, sound effects & audio tools.
Updated · View as Markdown