Seedance 2.5
ByteDance's newest video model: clips up to 30 seconds with sound, from a description, frames or references.
Seedance 2.5 is the newest ByteDance video model. It films 4 to 30 second clips in 480p, 720p and 1080p with sound: from a description, from the first and last frame, from references (up to 30 photos, 10 clips and 10 audio tracks), and it edits and continues your video.
Pick «Auto» length and the model decides: the price of 30 seconds is held and the rest comes back right after the video is ready.
One model, seedance-2.5 · ~4 min. The result follows the input fields (prompt, frames, references, video_mode, duration) — there are no separate «animate / edit» endpoints.
Features
prompt— up to 30000 charactersduration: "auto"/-1— model picks length (on the site: auto (-1))video_mode:auto·reference·edit·extendwatermark— "AI generated" markoutput_format:mp4(default) ormovreturn_last_frame— last-frame URL for chaininggenerate_audio— audio in the clipnsfw_check— check before chargeweb_search/tools: [{"type":"web_search"}]— fresh web grounding
Price
| Resolution | Price per second | With your video, per second |
|---|---|---|
| 480p | $0.125 | $0.075 |
| 720p | $0.281 | $0.169 |
| 1080p | $0.501 | $0.299 |
- Price = per-second price × clip length, rounded up to $0.001. Charged when the task is created and fully refunded if it fails.
- With your video, the seconds of the source clip are added to the seconds of the result.
- On the site — the auto (-1) tick next to the duration (not a list item). In the API:
duration: "auto"or-1lets the model choose the length, up to 30 s. On creation the price of 30 s is charged (plus your video seconds, if any). When the video is ready the price is recalculated from the real length and the difference goes straight back to your balance (history: «Refund for unused video seconds»). The final price iscostUsdin recordInfo, the length isdurationinresultJson. Withvideo_mode: "edit"the result is as long as your clip.
Media limits
| Type | Limits |
|---|---|
| Images | up to 30; JPG / PNG / WebP (also BMP / TIFF / GIF / HEIC via public https; or asset://… if you already have an id); upload via files/upload — up to 30 MB per file |
| Videos | up to 10; total ≤ 30 s (each clip 2…30 s); MP4 / MOV → MP4 on the server; upload ≤ 200 MB |
| Audio | up to 10; total ≤ 30 s; MP3 / WAV; upload ≤ 200 MB; audio-only (no photo/video) is allowed |
Photos — public https or upload; video and audio — files/upload only.
Task types and constraints
video_mode | What you need | Notes |
|---|---|---|
auto | prompt; media optional | default; the model picks reference / edit / extend |
reference | photo / video / audio references | character, place, motion, style |
edit | video_urls | length and aspect ratio follow your clip; clip ≥ 4 s |
extend | video_urls | continue the clip |
Field omni_reference_task_type is an alias of video_mode (accepted by the API).
Tip: with video_urls the site preselects aspect_ratio: adaptive and duration: auto / -1 (auto (-1) tick) — the model is picky about tiny duration mismatches. You can still set other values manually.
480p draft → 1080p final
- Create a task with
draft: true(resolution forced to480p). - Wait for
success, thenPOSTwithdraft_task_id= yourtaskId(nopromptor media). Final is1080p; reference-video seconds are not billed again. - Only
output_format,watermark,return_last_framemay change. Drafts last 7 days.draftanddraft_task_idare mutually exclusive.
On the site: «480p draft» tick; on recent works the 1080p button.
Parameters (field input)
| Parameter | Description | Values (default in bold) |
|---|---|---|
prompt | What happens in the clip: scene, motion, camera, light, style | text, up to 30000 chars |
first_frame_url | First frame: a photo link (https); the video starts from it | "https://…" |
last_frame_url | Last frame (optional, only together with the first one) | "https://…" |
image_urls | Reference photos (https) | ["https://…"], up to 30 |
video_urls | Your videos (MP4): upload them via files/upload first and pass the returned links | ["https://…"], up to 10 |
audio_urls | Audio (MP3): upload via files/upload first | ["https://…"], up to 10 |
video_mode | Task type for your video: auto (default) — the model works it out from the description, reference — reference, edit — edit (length and aspect ratio follow your video), extend — extend. Omitted = auto | auto (the model works it out) · reference (reference) · edit (edit) · extend (extend) |
resolution | Video resolution | 480p (standard) · 720p (high (HD)) · 1080p (Full HD) |
aspect_ratio | Aspect ratio | adaptive (matches your upload) · 16:9 (landscape) · 9:16 (portrait) · 1:1 (square) · 4:3 (traditional) · 3:4 (vertical traditional) · 21:9 (ultra-wide) |
duration | Video duration in seconds | 4 to 30 s, or auto / -1 (the model picks the length) (default 5) |
generate_audio | Video with sound | true false (default true) |
return_last_frame | Return the last-frame image URL (for continuing the clip) | true false (default false) |
output_format | Result container: mp4 (default) or mov | mp4 mov |
draft | Черновик 480p | true false (default false) |
web_search | Web search: fresh information from the internet (real places, events, products) | true false (default false) |
watermark | "AI generated" watermark on the video | true false (default false) |
nsfw_check | Content check: the description and photos are checked first; if not allowed, no task is created and nothing is charged | true false (default false) |
seed | Variant number: the same number with the same prompt gives a similar result; empty or -1 = random | -1…4294967295 |
trim_video_to | Trim each of your clips to N seconds: the beginning stays. Shorter clips are not changed | whole number, 2 to 30 |
trim_to_duration | Trim each of your clips to the chosen duration: the beginning stays. With duration: "auto" or video_mode: "edit" — to the model limit | true false (default false) |
auto_trim | If your clips together are longer than 30 s, trim them instead of returning an error (the longest first) | true false (default false) |
Examples
Prompt only
curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-2.5","input":{"prompt":"A drone flies over an autumn forest at sunrise, fog, cinematic","resolution":"720p","aspect_ratio":"adaptive","duration":"5"}}'
import os, requests
r = requests.post(
"https://mixmedia.tech/api/v1/jobs/createTask",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
json={
"model": "seedance-2.5",
"input": {
"prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
"resolution": "720p",
"aspect_ratio": "adaptive",
"duration": "5"
}
},
)
print(r.json()) # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"model": "seedance-2.5",
"input": {
"prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
"resolution": "720p",
"aspect_ratio": "adaptive",
"duration": "5"
}
}),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }
With a first frame
curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-2.5","input":{"prompt":"The character slowly turns to the camera, the wind moves the hair","first_frame_url":"https://mixmedia.tech/static/img/previews/gpt-t2i.jpg","resolution":"720p","duration":"5"}}'
import os, requests
r = requests.post(
"https://mixmedia.tech/api/v1/jobs/createTask",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
json={
"model": "seedance-2.5",
"input": {
"prompt": "The character slowly turns to the camera, the wind moves the hair",
"first_frame_url": "https://mixmedia.tech/static/img/previews/gpt-t2i.jpg",
"resolution": "720p",
"duration": "5"
}
},
)
print(r.json()) # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"model": "seedance-2.5",
"input": {
"prompt": "The character slowly turns to the camera, the wind moves the hair",
"first_frame_url": "https://mixmedia.tech/static/img/previews/gpt-t2i.jpg",
"resolution": "720p",
"duration": "5"
}
}),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }
With references
curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-2.5","input":{"prompt":"A drone flies over an autumn forest at sunrise, fog, cinematic","image_urls":["https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"],"resolution":"720p","aspect_ratio":"adaptive","duration":"5"}}'
import os, requests
r = requests.post(
"https://mixmedia.tech/api/v1/jobs/createTask",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
json={
"model": "seedance-2.5",
"input": {
"prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
"image_urls": [
"https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"
],
"resolution": "720p",
"aspect_ratio": "adaptive",
"duration": "5"
}
},
)
print(r.json()) # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"model": "seedance-2.5",
"input": {
"prompt": "A drone flies over an autumn forest at sunrise, fog, cinematic",
"image_urls": [
"https://mixmedia.tech/static/img/previews/gpt-t2i.jpg"
],
"resolution": "720p",
"aspect_ratio": "adaptive",
"duration": "5"
}
}),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }
With your video
curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-2.5","input":{"prompt":"Make the clip anime style, keep everything else","video_urls":["https://mixmedia.tech/files/<id>.mp4"],"video_mode":"edit","resolution":"720p","duration":"5"}}'
import os, requests
r = requests.post(
"https://mixmedia.tech/api/v1/jobs/createTask",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
json={
"model": "seedance-2.5",
"input": {
"prompt": "Make the clip anime style, keep everything else",
"video_urls": [
"https://mixmedia.tech/files/<id>.mp4"
],
"video_mode": "edit",
"resolution": "720p",
"duration": "5"
}
},
)
print(r.json()) # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"model": "seedance-2.5",
"input": {
"prompt": "Make the clip anime style, keep everything else",
"video_urls": [
"https://mixmedia.tech/files/<id>.mp4"
],
"video_mode": "edit",
"resolution": "720p",
"duration": "5"
}
}),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }
Trim your video
Your clips together: up to 30 s. No need to cut a long clip beforehand:
trim_to_duration: true— trim each clip to the chosenduration;trim_video_to: N— keep N seconds from the start;auto_trim: true— if the clips together are over the limit, cut them exactly to it instead of an error.
Trimming is free, and the price uses the trimmed seconds — fewer seconds cost less.
curl -X POST https://mixmedia.tech/api/v1/jobs/createTask \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-2.5","input":{"prompt":"Make the clip anime style, keep everything else","video_urls":["https://mixmedia.tech/files/<id>.mp4"],"video_mode":"edit","resolution":"720p","duration":"5","trim_to_duration":true,"auto_trim":true}}'
import os, requests
r = requests.post(
"https://mixmedia.tech/api/v1/jobs/createTask",
headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
json={
"model": "seedance-2.5",
"input": {
"prompt": "Make the clip anime style, keep everything else",
"video_urls": [
"https://mixmedia.tech/files/<id>.mp4"
],
"video_mode": "edit",
"resolution": "720p",
"duration": "5",
"trim_to_duration": True,
"auto_trim": True
}
},
)
print(r.json()) # {"code": 200, "data": {"taskId": "..."}}
const r = await fetch("https://mixmedia.tech/api/v1/jobs/createTask", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"model": "seedance-2.5",
"input": {
"prompt": "Make the clip anime style, keep everything else",
"video_urls": [
"https://mixmedia.tech/files/<id>.mp4"
],
"video_mode": "edit",
"resolution": "720p",
"duration": "5",
"trim_to_duration": true,
"auto_trim": true
}
}),
});
console.log(await r.json()); // { code: 200, data: { taskId: "..." } }
One uploaded file: up to 30 s. Without these options, clips that are too long return a 400 error with a hint.
Create and result
POST /api/v1/jobs/createTaskwithmodelandinput.- Poll
GET /api/v1/jobs/recordInfo?taskId=…every 3–5 s (or a callback).
Successful createTask (HTTP 200)
{
"code": 200,
"msg": "success",
"data": {
"taskId": "task_...",
"task_id": "task_...",
"status": "submitted"
}
}
Completed task (recordInfo)
{
"code": 200,
"msg": "success",
"data": {
"taskId": "task_...",
"task_id": "task_...",
"state": "success",
"status": "completed",
"costUsd": "0.384",
"refunded": false,
"resultJson": {
"videos": [
{
"url": "https://…/out.mp4"
}
],
"duration": 8
},
"lastFrameUrl": "https://…/last.jpg"
}
}
Aliases: task_id = taskId; status: pending / processing / completed / failed alongside state. Clip URL is in resultJson. size is an alias of aspect_ratio in input.
Photos can be any public https links or uploads via files/upload. Videos and audio — via files/upload only.
Error handling
API responses are JSON {"code", "msg", "data"}; errors also have a string error field (type). On /api/v1/* the HTTP status matches body code.
Example response bodies
400
{
"code": 400,
"msg": "input.duration: must be between 4 and 30, or \"auto\" / -1",
"data": null,
"error": "invalid_request_error"
}
401
{
"code": 401,
"msg": "Authentication failed. Please check your API key",
"data": null,
"error": "authentication_error"
}
402
{
"code": 402,
"msg": "Insufficient balance. Please top up and try again. Available: $0.01, required: $0.015. Top up at https://ai.aimixmedia.site/cabinet/billing",
"data": {
"balance": "0.0100",
"required": "0.0150",
"currency": "USD",
"topUpUrl": "https://mixmedia.tech/cabinet/billing"
},
"error": "payment_required"
}
429
{
"code": 429,
"msg": "Rate limit exceeded: 10 createTask/upload requests per 10 s per key. Retry after 8s",
"data": null,
"error": "rate_limit_error"
}
500
{
"code": 500,
"msg": "Internal server error",
"data": null,
"error": "server_error"
}
Codes on createTask / upload
| code | error | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_request_error | Invalid parameter or body | See msg |
| 400 | unsupported_model | Unknown model | Model list |
| 400 | nsfw_content_detected | Rejected by content check (nsfw_check) | Change the prompt or files |
| 401 | authentication_error | Missing or invalid key | Check the key |
| 402 | payment_required | Not enough balance | Top up |
| 403 | permission_error | No access | Contact support |
| 429 | rate_limit_error | Too many requests | Wait for Retry-After |
| 505 | model_disabled | Model temporarily disabled | Pick another |
| 500 | server_error | Our failure | Retry later |
Example msg values: Authentication failed. Please check your API key (401); Insufficient balance. Please top up and try again… (402).
Task errors (recordInfo)
If the task was created and then failed: state: "fail" (alias status: "failed"), failCode / failMsg, and error: { code, message, type }. Money is refunded (refunded: true).
| failCode | error.type | Meaning |
|---|---|---|
| 400 | nsfw_content_detected / invalid_request_error | Moderation / safety rules |
| 422 | invalid_request_error | The model rejected the parameters (length, mode, resolution, file) |
| 501 | server_error | The model could not generate (failMsg) |
| 504 | timeout_error | Timed out — retry |
| 500 / 503 | server_error | Service temporarily unavailable |
Common refusals for this model
durationout of range, orauto/-1when auto length is not supported (Seedance 2.5 only)resolution/aspect_ratio(size) /video_modenot in the list abovevideo_mode=editorextendwithoutvideo_urls; foredit— clip shorter than 4 s- Reference video/audio too long without
auto_trim/trim_*→400 nsfw_check: true— on reject immediate HTTP 400 (nsfw_content_detected); no task, no charge
Rate limits
| What | Limit |
|---|---|
| createTask and upload | 20 per 10 s per key |
| recordInfo / list / balance | 100 per 10 s per key |
Over the limit — HTTP 429 and Retry-After.