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": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
Wan3.0
Generación de vídeo Wan3.0
- Modelo de vídeo de referencia todo en uno Alibaba Cloud Wanxiang 3.0
- Texto a vídeo / primer fotograma / primer+último fotograma / referencia multimodal / referencia de archivo o enlace
- Resolución 480P / 720P / 1080P, duración 2–30 segundos
- Admite imágenes, vídeo, audio, documentos y páginas web públicas como referencias
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": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"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": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
Autenticación
string
requerido
Todos los endpoints requieren autenticación Bearer TokenObtenga su API Key en la página de gestión de API Keys:
Authorization: Bearer YOUR_API_KEY
Modos de generación
El nombre del modelo eswan3.0-video o wan3.0-video-prime (mismos parámetros). Los modos se seleccionan mediante los campos de la solicitud:
| Modo | Entradas típicas |
|---|---|
| Texto a vídeo | solo prompt |
| Vídeo desde el primer fotograma | un elemento en image_urls (familia frame) |
| Primer + último fotograma | dos elementos en image_urls, o image_with_roles con first_frame / last_frame |
| Vídeo de referencia | imágenes / vídeos / audio de referencia; el prompt puede usar etiquetas al estilo “图1 / 视频1 / 音频1” |
| Referencia de archivo / página | file_url o link_url (prompt opcional) |
Parámetros de la solicitud
Básicos
string
requerido
Nombre del modelo de generación de video. Valores permitidos:
wan3.0-videowan3.0-video-prime
boolean
predeterminado:"false"
Indica si se debe moderar el contenido antes de enviar la tarea de vídeo.
true: revisar los prompts y las imágenes de entrada conomni-moderation-latestfalseu omitido: no enviar una solicitud de moderación, sin coste ni latencia de moderación adicionales (predeterminado)
string
Descripción textual. Obligatorio a menos que se proporcionen campos de medios (al menos uno entre prompt o medios).
- Máx. 20.000 caracteres; el exceso se trunca automáticamente (sin error)
- En modo de referencia, use “图N / 视频N / 音频N” para referirse a los assets; los índices siguen el orden dentro de cada tipo de medio
string
predeterminado:"1080P"
Resolución de salida (no distingue mayúsculas/minúsculas)
480P720P1080P(predeterminado, precio más alto)
Omitir
resolution factura a 1080P. Pase 480P o 720P explícitamente cuando el coste importe.string
predeterminado:"adaptive"
Relación de aspecto. También se acepta
aspect_ratio.adaptive(predeterminado)16:9/4:3/1:1/3:4/9:16
integer
predeterminado:"5"
Duración en segundos:
2–30: duración de salida fija (predeterminado5)-1: la duración la decide el modelo
Con vídeo de referencia: duración total de entrada + salida ≤ 30 s. Con
duration: -1, la duración elegida por el modelo también debe cumplir esta restricción.boolean
predeterminado:"true"
Si la salida incluye pista de audio. Predeterminado
true. El precio es el mismo con o sin audio.integer
Semilla aleatoria en
[0, 2147483647]boolean
predeterminado:"false"
Si se debe añadir una marca de agua. Predeterminado
falsestring
Cómo se clasifican los
image_urls sin rol explícito:frame— familia de primer/último fotogramareference— familia de referencia
Entradas de medios
string[]
Array de URL de imágenes. La asignación de roles sigue las reglas de exclusión mutua.Solo URL públicas.
object[]
Imágenes con roles explícitos. Cada elemento:
url: dirección de la imagenrole:first_frame/last_frame/reference_image(se aceptan alias comunes)
string[]
Vídeos de referencia, hasta 5 clips; cada uno 1–15 s, total ≤ 15 s
string[]
Audio de referencia, hasta 5 clips; cada uno 1–15 s, total ≤ 15 s
string
Audio de referencia único (forma de valor único de
audio_urls)string
URL de documento de referencia, como máximo 1. No se puede combinar con
link_url.Formatos: docx / doc / xlsx / xls / pptx / ppt / pdf / txt / key / pages / numbers / md, ≤100 MB, ≤50 páginas.string
URL de página web pública, como máximo 1. Solo páginas sin inicio de sesión. No se puede combinar con
file_url.Exclusión mutua de familias de medios
Los medios pertenecen a una de dos familias y no deben mezclarse (validado antes del envío → 400, sin tarea, sin cargo):| Familia | Miembros | Significado |
|---|---|---|
| Familia frame | first_frame, last_frame | Primer / último fotograma estricto del vídeo |
| Familia de referencia | reference_image, reference_video, reference_audio, file, link | El modelo interpreta el contenido libremente |
Cómo se asignan los image_urls sin rol
- Si
generation_typeestá definido → usarlo (frame/reference) - Si no, y la solicitud ya tiene entradas de la familia de referencia (
video_urls/audio_urls/audio_url/file_url/link_url) → tratar comoreference_image - Si no → familia frame: primer elemento
first_frame, segundolast_frame(igual quewan2.7)
image_with_roles cuando necesite control explícito.
Límites y formatos de medios
| Tipo | Límites |
|---|---|
| Primer / último fotograma | ≤ 1 cada uno |
| Imágenes de referencia | ≤ 10 |
| Vídeo de referencia | ≤ 5 clips, 1–15 s cada uno, total ≤15 s; mp4/mov; borde 240–4096 px, relación ≤8:1, ≤100 MB |
| Audio de referencia | ≤ 5 clips, 1–15 s cada uno, total ≤15 s; wav/mp3; ≤15 MB |
| Imágenes | JPEG/JPG/PNG (sin alpha) / BMP / WEBP; borde 240–8000 px, relación ≤8:1, ≤20 MB |
| Documentos | ≤100 MB, ≤50 páginas |
| Páginas web | URL públicas, sin inicio de sesión |
Ejemplos de solicitud
Texto a vídeo
{
"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
}
Vídeo desde el primer fotograma
{
"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
}
Primer + último fotograma
{
"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
}
Referencia multimodal
{
"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
}
Convideo_urlspresente, losimage_urlssin rol se clasifican automáticamente como imágenes de referencia; definirgeneration_type: "reference"es más claro.
Vídeo de referencia por archivo
prompt puede omitirse; la generación se basa en el documento:
{
"model": "wan3.0-video",
"file_url": "https://example.com/glass.pptx",
"resolution": "480P",
"duration": 10
}
Vídeo de referencia por página web
{
"model": "wan3.0-video",
"prompt": "Turn this article into a short educational video",
"link_url": "https://example.com/article/123",
"duration": 15
}
Facturación
Por segundo × resolución (alineado con el precio oficial). El audio activado/desactivado no cambia el precio:| Resolución | Precio unitario | 5 s | 30 s |
|---|---|---|---|
| 480P | ¥0.30 / s | ¥1.50 | ¥9.00 |
| 720P | ¥0.60 / s | ¥3.00 | ¥18.00 |
| 1080P | ¥1.20 / s | ¥6.00 | ¥36.00 |
- El valor predeterminado es 1080P (el más caro); pase
480P/720Pcuando el coste sea sensible - Segundos facturables: para
2–30, ladurationsolicitada; para-1, los segundos reales de salida audio: true/falseno afecta al precio
Límites y notas
| Elemento | Notas |
|---|---|
| Duración | Entero 2–30, o -1 (el modelo decide la duración) |
| Con entrada de vídeo | Duración total de los vídeos de entrada + duración de salida ≤ 30 s |
| Latencia | Típicamente 1–5 minutos; más larga para clips largos |
| URL del resultado | Reflejada en el CDN de la plataforma tras el éxito para acceso a largo plazo |
| Prompt | ≤20.000 caracteres; exceso truncado |
Errores comunes
Todos son 400 síncronos (sin tarea, sin cargo):| Caso | Qué hacer |
|---|---|
| Mezclar familias frame y de referencia | Elija una familia mediante generation_type, o defina roles con image_with_roles |
file_url y link_url juntos | Elija uno |
duration no válido | Solo 2–30 o -1 |
| Resolución no admitida (p. ej. 4K) | Solo 480P / 720P / 1080P |
| Más de 10 imágenes de referencia | Reduzca a ≤10 |
prompt vacío y medios vacíos | Proporcione al menos uno |
Respuesta
integer
Código de estado; 200 en caso de éxito
array
Consultar resultadosLa generación de vídeo es asíncrona. Consulte Obtener estado de la tarea o
GET /v1/videos/generations/{task_id}.Intervalo recomendado 5–10 segundos; la generación suele tardar 1–5 minutos. En caso de éxito, use las URL en result.videos.