curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan3.0-video",
prompt: "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
resolution: "720P",
size: "16:9",
duration: 5,
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "Недопустимые параметры запроса",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Ошибка аутентификации, проверьте ваш API-ключ",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Недостаточный баланс аккаунта, пополните счёт и повторите попытку",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Слишком много запросов, повторите попытку позже",
"type": "rate_limit_error"
}
}
Wan3.0
Генерация видео Wan3.0
- Универсальная референс-модель видео Alibaba Cloud Wanxiang 3.0 (единая точка входа)
- Текст-в-видео / первый кадр / первый+последний кадр / мультимодальный референс / файл или веб-страница
- Разрешение 480P / 720P / 1080P, длительность 2–30 секунд
- Поддержка изображений, видео, аудио, документов и публичных веб-страниц как референсов
POST
/
v1
/
videos
/
generations
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan3.0-video",
prompt: "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
resolution: "720P",
size: "16:9",
duration: 5,
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "Недопустимые параметры запроса",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Ошибка аутентификации, проверьте ваш API-ключ",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Недостаточный баланс аккаунта, пополните счёт и повторите попытку",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Слишком много запросов, повторите попытку позже",
"type": "rate_limit_error"
}
}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "wan3.0-video",
prompt: "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
resolution: "720P",
size: "16:9",
duration: 5,
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop",
"resolution": "720P",
"size": "16:9",
"duration": 5,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "Недопустимые параметры запроса",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Ошибка аутентификации, проверьте ваш API-ключ",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Недостаточный баланс аккаунта, пополните счёт и повторите попытку",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Слишком много запросов, повторите попытку позже",
"type": "rate_limit_error"
}
}
Авторизация
string
обязательно
Все эндпоинты требуют аутентификации по Bearer TokenПолучите API Key на странице управления API Key:
Authorization: Bearer YOUR_API_KEY
Режимы генерации
Имя модели —wan3.0-video или wan3.0-video-prime (параметры одинаковые). Режим выбирается по полям запроса:
| Режим | Типичные входные данные |
|---|---|
| Текст-в-видео | только prompt |
| Видео по первому кадру | один элемент в image_urls (семейство кадров) |
| Первый + последний кадр | два элемента в image_urls или image_with_roles с first_frame / last_frame |
| Референс-видео | референсные изображения / видео / аудио; в промпте можно использовать метки вида «图1 / 视频1 / 音频1» |
| Файл / страница | file_url или link_url (prompt необязателен) |
Параметры запроса
Базовые
string
обязательно
Имя модели генерации видео. Допустимые значения:
wan3.0-videowan3.0-video-prime
boolean
по умолчанию:"false"
Выполнять ли проверку содержимого перед отправкой задачи генерации видео.
true: проверить промпты и входные изображения с помощьюomni-moderation-latestfalseили параметр не указан: не отправлять запрос на проверку, без дополнительных затрат и задержки (по умолчанию)
string
Текстовое описание. Обязательно, если не переданы медиа-поля (нужно хотя бы одно: prompt или медиа).
- Максимум 20 000 символов; превышение обрезается автоматически (без ошибки)
- В режиме референса используйте «图N / 视频N / 音频N» для обращения к активам; индексы идут внутри каждого типа медиа
string
по умолчанию:"1080P"
Выходное разрешение (без учёта регистра)
480P720P1080P(по умолчанию, самая высокая цена)
Если не указать
resolution, тарификация идёт по 1080P. При чувствительности к стоимости явно передавайте 480P или 720P.string
по умолчанию:"adaptive"
Соотношение сторон. Также принимается
aspect_ratio.adaptive(по умолчанию)16:9/4:3/1:1/3:4/9:16
integer
по умолчанию:"5"
Длительность в секундах:
2–30: фиксированная длина (по умолчанию5)-1: длительность выбирает модель
При входном референсном видео: суммарная длительность входа + выход ≤ 30 с. При
duration: -1 выбранная моделью длина всё равно должна укладываться в это ограничение.boolean
по умолчанию:"true"
Включать ли аудиодорожку в выход. По умолчанию
true. Цена одинакова с аудио и без.integer
Случайное зерно в диапазоне
[0, 2147483647]boolean
по умолчанию:"false"
Добавлять ли водяной знак. По умолчанию
falsestring
Как классифицировать «голые»
image_urls:frame— семейство первого/последнего кадраreference— семейство референсов
Медиа-входы
string[]
Массив URL изображений. Роли назначаются по правилам взаимного исключения.Только публичные URL.
object[]
Изображения с явными ролями. Каждый элемент:
url: адрес изображенияrole:first_frame/last_frame/reference_image(принимаются распространённые псевдонимы)
string[]
Референсные видео, до 5 клипов; каждый 1–15 с, суммарно ≤ 15 с
string[]
Референсное аудио, до 5 клипов; каждый 1–15 с, суммарно ≤ 15 с
string
Одно референсное аудио (одиночная форма
audio_urls)string
URL референсного документа, не более 1. Нельзя сочетать с
link_url.Форматы: docx / doc / xlsx / xls / pptx / ppt / pdf / txt / key / pages / numbers / md и др., ≤100 МБ, ≤50 страниц.string
URL публичной веб-страницы, не более 1. Только страницы без входа. Нельзя сочетать с
file_url.Взаимное исключение семейств медиа
Медиа относится к одному из двух семейств и не должно смешиваться (проверка до submit → 400, без задачи и без списания):| Семейство | Участники | Смысл |
|---|---|---|
| Семейство кадров | first_frame, last_frame | Строгий первый / последний кадр видео |
| Семейство референсов | reference_image, reference_video, reference_audio, file, link | Модель свободно интерпретирует содержимое |
Как назначаются «голые» image_urls
- Если задан
generation_type→ использовать его (frame/reference) - Иначе, если в запросе уже есть входы семейства референсов (
video_urls/audio_urls/audio_url/file_url/link_url) → считатьreference_image - Иначе → семейство кадров: первый элемент
first_frame, второйlast_frame(как уwan2.7)
image_with_roles.
Лимиты и форматы медиа
| Тип | Ограничения |
|---|---|
| Первый / последний кадр | ≤ 1 каждый |
| Референсные изображения | ≤ 10 |
| Референсное видео | ≤ 5 клипов, 1–15 с каждый, суммарно ≤15 с; mp4/mov; сторона 240–4096 px, соотношение ≤8:1, ≤100 МБ |
| Референсное аудио | ≤ 5 клипов, 1–15 с каждый, суммарно ≤15 с; wav/mp3; ≤15 МБ |
| Изображения | JPEG/JPG/PNG (без альфы) / BMP / WEBP; сторона 240–8000 px, соотношение ≤8:1, ≤20 МБ |
| Документы | ≤100 МБ, ≤50 страниц |
| Веб-страницы | Публичные URL без входа |
Примеры запросов
Текст-в-видео
{
"model": "wan3.0-video",
"prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
"resolution": "720P",
"size": "16:9",
"duration": 5
}
Видео по первому кадру
{
"model": "wan3.0-video",
"prompt": "The person in the frame starts freestyle rapping, camera slowly pushes in",
"image_urls": ["https://example.com/first.png"],
"resolution": "720P",
"duration": 5
}
Первый + последний кадр
{
"model": "wan3.0-video",
"prompt": "Smile gradually becomes laughter, background light shifts from cool to warm",
"image_urls": [
"https://example.com/first.png",
"https://example.com/last.jpg"
],
"duration": 5
}
image_with_roles:
{
"model": "wan3.0-video",
"prompt": "Smile gradually becomes laughter",
"image_with_roles": [
{"url": "https://example.com/first.png", "role": "first_frame"},
{"url": "https://example.com/last.jpg", "role": "last_frame"}
],
"duration": 5
}
Мультимодальный референс
{
"model": "wan3.0-video",
"prompt": "视频1抱着图1,在图3的椅子上弹奏一支舒缓的乡村民谣,并说道:\"今天的阳光真好。\"",
"generation_type": "reference",
"image_urls": [
"https://example.com/object1.jpg",
"https://example.com/object2.png",
"https://example.com/chair.png"
],
"video_urls": ["https://example.com/role.mp4"],
"resolution": "480P",
"duration": 5
}
При наличииvideo_urls«голые»image_urlsавтоматически относятся к референсным изображениям; явноеgeneration_type: "reference"делает намерение яснее.
Видео по файлу
prompt можно опустить; генерация идёт по содержимому документа:
{
"model": "wan3.0-video",
"file_url": "https://example.com/glass.pptx",
"resolution": "480P",
"duration": 10
}
Видео по веб-странице
{
"model": "wan3.0-video",
"prompt": "Turn this article into a short educational video",
"link_url": "https://example.com/article/123",
"duration": 15
}
Тарификация
За секунду × разрешение (по официальному прайс-листу). Вкл./выкл. аудио цену не меняет:| Разрешение | Цена за ед. | 5 с | 30 с |
|---|---|---|---|
| 480P | ¥0.30 / с | ¥1.50 | ¥9.00 |
| 720P | ¥0.60 / с | ¥3.00 | ¥18.00 |
| 1080P | ¥1.20 / с | ¥6.00 | ¥36.00 |
- По умолчанию 1080P (самый дорогой); при чувствительности к стоимости передавайте
480P/720P - Тарифицируемые секунды: при
2–30— запрошенныйduration; при-1— фактические секунды выхода audio: true/falseне влияет на цену
Ограничения и замечания
| Пункт | Примечание |
|---|---|
| Длительность | Целое 2–30 или -1 (длину выбирает модель) |
| С видео на входе | Сумма длительности входного видео + выходной длительности ≤ 30 с |
| Задержка | Обычно 1–5 минут; для длинных клипов дольше |
| URL результата | После успеха зеркалируется на CDN платформы для долгосрочного доступа |
| Промпт | ≤20 000 символов; превышение обрезается |
Частые ошибки
Все — синхронный 400 (без задачи, без списания):| Случай | Что делать |
|---|---|
| Смешение семейств кадров и референсов | Выберите одно семейство через generation_type или задайте роли через image_with_roles |
Одновременно file_url и link_url | Выберите одно |
Неверный duration | Только 2–30 или -1 |
| Неподдерживаемое разрешение (напр. 4K) | Только 480P / 720P / 1080P |
| Более 10 референсных изображений | Сократите до ≤10 |
Пустые prompt и медиа | Укажите хотя бы одно |
Response
integer
Код статуса; 200 при успехе
array
Запрос результатовГенерация видео асинхронна. Опрашивайте Получение статуса задачи или
GET /v1/videos/generations/{task_id}.Рекомендуемый интервал 5–10 секунд; генерация обычно занимает 1–5 минут. При успехе используйте URL из result.videos.