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
Geração de vídeo Wan3.0
- Modelo de vídeo de referência all-in-one Alibaba Cloud Wanxiang 3.0
- Texto-para-vídeo / primeiro frame / primeiro+último frame / referência multimodal / referência por arquivo ou link
- Resolução 480P / 720P / 1080P, duração 2–30 segundos
- Suporta imagens, vídeo, áudio, documentos e páginas web públicas como referências
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"
}
}
Autenticação
string
obrigatório
Todos os endpoints exigem autenticação Bearer TokenObtenha sua API Key na página de gerenciamento de API Keys:
Authorization: Bearer YOUR_API_KEY
Modos de geração
O nome do modelo é fixo emwan3.0-video. Os modos são selecionados pelos campos da requisição:
| Modo | Entradas típicas |
|---|---|
| Texto-para-vídeo | apenas prompt |
| Vídeo a partir do primeiro frame | um item em image_urls (família frame) |
| Primeiro + último frame | dois itens em image_urls, ou image_with_roles com first_frame / last_frame |
| Vídeo de referência | imagens / vídeos / áudio de referência; o prompt pode usar rótulos no estilo “图1 / 视频1 / 音频1” |
| Referência por arquivo / página | file_url ou link_url (prompt opcional) |
Parâmetros da requisição
Básicos
string
obrigatório
Valor fixo:
wan3.0-videoboolean
padrão:"false"
Define se o conteúdo deve ser moderado antes do envio da tarefa de vídeo.
true: verificar prompts e imagens de entrada comomni-moderation-latestfalseou omitido: não enviar solicitação de moderação, sem custo nem latência adicionais de moderação (padrão)
string
Descrição textual. Obrigatório a menos que campos de mídia sejam fornecidos (pelo menos um entre prompt ou mídia).
- Máx. 20.000 caracteres; o excesso é truncado automaticamente (sem erro)
- No modo de referência, use “图N / 视频N / 音频N” para endereçar assets; os índices seguem a ordem dentro de cada tipo de mídia
string
padrão:"1080P"
Resolução de saída (sem distinção de maiúsculas/minúsculas)
480P720P1080P(padrão, preço mais alto)
Omitir
resolution cobra em 1080P. Passe 480P ou 720P explicitamente quando o custo importar.string
padrão:"adaptive"
Proporção.
aspect_ratio também é aceito.adaptive(padrão)16:9/4:3/1:1/3:4/9:16
integer
padrão:"5"
Duração em segundos:
2–30: duração de saída fixa (padrão5)-1: a duração é definida pelo modelo
Com vídeo de referência: duração total de entrada + saída ≤ 30 s. Com
duration: -1, a duração escolhida pelo modelo ainda deve respeitar esse limite.boolean
padrão:"true"
Se a saída inclui faixa de áudio. Padrão
true. O preço é o mesmo com ou sem áudio.integer
Semente aleatória em
[0, 2147483647]boolean
padrão:"false"
Se deve adicionar marca d’água. Padrão
falsestring
Como
image_urls sem papel explícito são classificadas:frame— família primeiro/último framereference— família de referência
Entradas de mídia
string[]
Array de URLs de imagem. A atribuição de papéis segue as regras de exclusão mútua.URL pública ou Base64 (
data:image/png;base64,...).object[]
Imagens com papéis explícitos. Cada item:
url: endereço da imagemrole:first_frame/last_frame/reference_image(aliases comuns aceitos)
string[]
Vídeos de referência, até 5 clips; cada um 1–15 s, total ≤ 15 s
string[]
Áudio de referência, até 5 clips; cada um 1–15 s, total ≤ 15 s
string
Áudio de referência único (forma de valor único de
audio_urls)string
URL de documento de referência, no máximo 1. Não pode ser combinado com
link_url.Formatos incluem 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, no máximo 1. Apenas páginas sem login. Não pode ser combinado com
file_url.Exclusão mútua das famílias de mídia
A mídia pertence a uma de duas famílias e não deve ser misturada (validado antes do envio → 400, sem tarefa, sem cobrança):| Família | Membros | Significado |
|---|---|---|
| Família frame | first_frame, last_frame | Primeiro / último frame estrito do vídeo |
| Família de referência | reference_image, reference_video, reference_audio, file, link | O modelo interpreta o conteúdo livremente |
Como image_urls sem papel explícito são atribuídas
- Se
generation_typeestiver definido → usá-lo (frame/reference) - Caso contrário, se a requisição já tiver entradas da família de referência (
video_urls/audio_urls/audio_url/file_url/link_url) → tratar comoreference_image - Caso contrário → família frame: primeiro item
first_frame, segundolast_frame(igual awan2.7)
image_with_roles quando precisar de controle explícito.
Limites e formatos de mídia
| Tipo | Limites |
|---|---|
| Primeiro / último frame | ≤ 1 cada |
| Imagens de referência | ≤ 10 |
| Vídeo de referência | ≤ 5 clips, 1–15 s cada, total ≤15 s; mp4/mov; borda 240–4096 px, proporção ≤8:1, ≤100 MB |
| Áudio de referência | ≤ 5 clips, 1–15 s cada, total ≤15 s; wav/mp3; ≤15 MB |
| Imagens | JPEG/JPG/PNG (sem alpha) / BMP / WEBP; borda 240–8000 px, proporção ≤8:1, ≤20 MB |
| Documentos | ≤100 MB, ≤50 páginas |
| Páginas web | URLs públicas, sem login |
Exemplos de requisição
Texto-para-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 a partir do primeiro frame
{
"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
}
Primeiro + último frame
{
"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
}
Referência 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
}
Comvideo_urlspresente,image_urlssem papel explícito classificam-se automaticamente como imagens de referência; definirgeneration_type: "reference"fica mais claro.
Vídeo de referência por arquivo
prompt pode ser omitido; a geração é conduzida pelo documento:
{
"model": "wan3.0-video",
"file_url": "https://example.com/glass.pptx",
"resolution": "480P",
"duration": 10
}
Vídeo de referência 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
}
Cobrança
Por segundo × resolução (alinhado ao preço oficial). Áudio ligado/desligado não altera o preço:| Resolução | Preço unitário | 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 |
- O padrão é 1080P (mais caro); passe
480P/720Pquando o custo for sensível - Segundos faturáveis: para
2–30, adurationsolicitada; para-1, os segundos reais de saída audio: true/falsenão afeta o preço
Limites e observações
| Item | Observações |
|---|---|
| Duração | Inteiro 2–30, ou -1 (o modelo define a duração) |
| Com entrada de vídeo | Duração total dos vídeos de entrada + duração de saída ≤ 30 s |
| Latência | Tipicamente 1–5 minutos; mais longo para clips longos |
| URL do resultado | Espelhada no CDN da plataforma após sucesso para acesso de longo prazo |
| Prompt | ≤20.000 caracteres; excesso truncado |
Erros comuns
Todos são 400 síncronos (sem tarefa, sem cobrança):| Caso | O que fazer |
|---|---|
| Misturar famílias frame e referência | Escolher uma família via generation_type, ou definir papéis com image_with_roles |
file_url e link_url juntos | Escolher um |
duration inválido | Apenas 2–30 ou -1 |
| Resolução não suportada (ex. 4K) | Apenas 480P / 720P / 1080P |
| Mais de 10 imagens de referência | Reduzir para ≤10 |
prompt vazio e mídia vazia | Fornecer pelo menos um |
Resposta
integer
Código de status; 200 em caso de sucesso
array
Consultar resultadosA geração de vídeo é assíncrona. Consulte Obter status da tarefa ou
GET /v1/videos/generations/{task_id}.Intervalo recomendado 5–10 segundos; a geração normalmente leva 1–5 minutos. Em caso de sucesso, use as URLs em result.videos.