GPT-6 Sol y Claude Opus 5.5 ya disponiblesGPT-6 Sol por la mitad del precio de 5.6 Sol

Wan 3.0 API: text-to-video e image-to-video en Python

Un solo script generó los dos clips: el código, los tiempos reales y el precio por segundo de Alibaba.

Kiki, OmniaKey COO8 min de lectura
En esta página

Wan 3.0 funciona en Alibaba Cloud Model Studio como wan3.0-video y la versión más rápida wan3.0-video-prime. Todas las llamadas son asíncronas: creas una tarea, consultas el ID y descargas el MP4. Nuestro script de Python generó un clip de 5 segundos en 720P a partir de texto en 2 min 42 s y otro a partir de una foto en 3 min 20 s, los dos con sonido.

  1. Pon la clave en OMNIAKEY_API_KEY.
  2. Haz POST a https://api.omniakey.com/v1/media/tasks con el modelo, la operación, el prompt, los parámetros y un Idempotency-Key nuevo.
  3. Consulta GET /v1/media/tasks/{id} hasta que el estado diga succeeded y descarga assets[0].url en ese momento.

¿Existe una API oficial de Wan 3.0 y qué modelo conviene usar?

Sí. Alibaba Cloud Model Studio es la API oficial, con wan3.0-video y wan3.0-video-prime (referencia actualizada el 15 de octubre de 2026). Su llamada de creación necesita la cabecera X-DashScope-Async: enable, y Alibaba indica DashScope SDK 2.0.1 o posterior para Python.

Alibaba Model StudioOmniaKey
Ambos IDsSíSí
Cabecera asíncronaSíNo
Enlace del vídeo24 horasCerca de 1 hora, renovable
FacturaciónPor segundoPor segundo
PythonDashScope SDKBiblioteca estándar

Los dos IDs comparten una sola forma de cuerpo, y el modelo elige el modo según el medio que envíes. El script de abajo ejecuta wan3.0-video y la línea MODEL lo cambia. No ejecutamos Wan 3.0 Prime, que la documentación de OmniaKey describe con las mismas capacidades en aproximadamente la mitad del tiempo (comprobado el 31 de octubre de 2026).

¿Qué necesitas antes de la primera llamada?

Tres cosas, y la primera es la clave.

  1. Una clave de API de OmniaKey, exportada en tu shell:

    bash
    export OMNIAKEY_API_KEY="your-key"
    
  2. Python 3. El script solo importa la biblioteca estándar, así que python3 lo ejecuta tal cual.

  3. Para image to video, un primer fotograma: un JPEG de unos 1024 px de ancho, o una URL HTTPS pública. El script rechaza un archivo de más de 700,000 bytes, porque Base64 añade un tercio y el límite del cuerpo es 1 MiB (documentación, comprobada el 31 de octubre de 2026).

¿Qué parámetros importan?

Siete campos hacen casi todo el trabajo, y cada uno es un valor dentro de parameters.

ParámetroQué hacePor defecto
DurationDuración del clip, segundos5
ResolutionNivel de tamaño1080P
RatioForma del fotogramaadaptive
AudioPista de sonidoon
SeedAyuda a repetir-1
Prompt extendReescribe tu prompton
WatermarkAñade una marcaoff

El script fija duration, resolution y ratio. Pide 720P cuando el valor por defecto de Alibaba es 1080P, que a precios de lista cuesta el doble por segundo.

¿Cómo es el código de Python?

El script de abajo se ejecutó sin cambios el 31 de octubre de 2026: solo biblioteca estándar, los dos modos y una línea MODEL que cambiar.

python
import base64
import json
import os
import time
import urllib.error
import urllib.request
import uuid

API = "https://api.omniakey.com/v1/media/tasks"
KEY = os.environ["OMNIAKEY_API_KEY"]
MODEL = "wan3.0-video"

def request(method, url, body=None, extra_headers=None):
    headers = {"Authorization": f"Bearer {KEY}", "User-Agent": "omniakey-example/1"}
    data = None
    if body is not None:
        headers["Content-Type"] = "application/json"
        data = json.dumps(body).encode()
    headers.update(extra_headers or {})
    req = urllib.request.Request(url, data=data, headers=headers, method=method)
    with urllib.request.urlopen(req, timeout=120) as resp:
        return json.load(resp)

def poll(url, attempts=5):
    for attempt in range(attempts):
        try:
            return request("GET", url)
        except urllib.error.HTTPError as err:
            if err.code < 500 or attempt == attempts - 1:
                raise
        except urllib.error.URLError:
            if attempt == attempts - 1:
                raise
        time.sleep(5 * (attempt + 1))

def run_task(body, out_path):
    task = request("POST", API, body, {"Idempotency-Key": str(uuid.uuid4())})["id"]
    print("task", task, flush=True)
    for _ in range(180):  # 5-second polls, up to 15 minutes
        time.sleep(5)
        state = poll(f"{API}/{task}")
        if state["status"] not in ("queued", "processing"):
            break
    else:
        raise TimeoutError(f"{task} is still {state['status']}: poll it again later, do not resubmit")
    if state["status"] != "succeeded":
        raise RuntimeError(state.get("error") or state["status"])
    asset_url = state["assets"][0]["url"]  # signed link: short-lived, so download now
    req = urllib.request.Request(asset_url, headers={"User-Agent": "omniakey-example/1"})
    with urllib.request.urlopen(req, timeout=300) as resp, open(out_path, "wb") as f:
        f.write(resp.read())
    return task

def text_to_video(prompt, out_path, duration=5, resolution="720P", ratio="16:9"):
    body = {
        "model": MODEL,
        "type": "video",
        "operation": "text_to_video",
        "input": {"prompt": prompt},
        "parameters": {"duration": duration, "resolution": resolution, "ratio": ratio},
    }
    return run_task(body, out_path)

def image_to_video(prompt, image_path, out_path, duration=5, resolution="720P"):
    with open(image_path, "rb") as f:
        raw = f.read()
    if len(raw) > 700_000:  # base64 adds a third, and the whole body must stay under 1 MiB
        raise ValueError("first frame too large: save it as a JPEG about 1024 px wide")
    frame = "data:image/jpeg;base64," + base64.b64encode(raw).decode()
    body = {
        "model": MODEL,
        "type": "video",
        "operation": "image_to_video",
        "input": {"prompt": prompt, "media": [{"type": "first_frame", "url": frame}]},
        "parameters": {"duration": duration, "resolution": resolution, "ratio": "adaptive"},
    }
    return run_task(body, out_path)

if __name__ == "__main__":
    print("done", text_to_video(
        "A blacksmith hammers a glowing horseshoe on an anvil in a dark forge. Sparks fly at each "
        "strike and light his leather apron. The camera slowly pushes in. Sound of the hammer ringing "
        "on steel and the fire crackling. No dialogue, no music, no text.",
        "forge.mp4",
    ))
    print("done", image_to_video(
        "Image 1 is the first frame. The paper boat drifts slowly to the right across the puddle. "
        "Light rain makes small ripples and the cafe lights shimmer in the water. The camera stays "
        "low and still. Sound of light rain. No dialogue, no music, no text.",
        "boat.jpg",
        "boat-drifts.mp4",
    ))

Qué hace cada parte:

  • run_task acuña un Idempotency-Key nuevo para cada trabajo. Reenviar la misma clave con el mismo cuerpo devuelve la tarea original y nunca cobra dos veces (documentación, comprobada el 31 de octubre de 2026).
  • Consulta cada 5 segundos hasta 15 minutos y después lanza TimeoutError.
  • Un timeout significa consultar el mismo ID más tarde; un reenvío acuña una clave nueva, crea un segundo trabajo y lo factura.
  • Descarga la primera URL del recurso en el acto, porque el enlace firmado dura poco.
  • image_to_video rechaza un fotograma de más de 700,000 bytes: Base64 añade un tercio y el límite del cuerpo es 1 MiB.
  • La llamada de imagen fija el ratio en adaptive, así el clip sigue la forma de la foto.

Esto es lo que imprimió:

text
task task_<id>
done task_<id>
task task_<id>
done task_<id>

¿Qué produjeron las dos llamadas?

Los dos archivos volvieron como MP4 de 5.04 segundos, 150 fotogramas a 30 fps, H.264 y una pista AAC estéreo a 44.1 kHz.

Text to video: la fragua

Cuatro fotogramas del clip de la fragua de Wan 3.0
Text to video, 5 s en 720P: fotogramas en 0.3, 2.2, 3.5 y 4.7 segundos.

El clip sigue el prompt: un herrero con camisa oscura y delantal de cuero golpea una herradura naranja incandescente, las chispas estallan a los 2.2 segundos y la cámara se acerca un poco. El fallo es una marca de taller con letras ilegibles en el yunque, aunque el prompt pedía que no hubiera texto. Del inicio al archivo pasaron 2 min 42 s; el MP4 es de 1280×720 y 6.6 MB.

Image to video: el barco de papel

La foto del primer fotograma y tres fotogramas del clip del barco de papel de Wan 3.0
Image to video: la foto que enviamos (arriba a la izquierda) y el clip en 1.6, 3.5 y 4.7 segundos.

El primer fotograma era una foto que hicimos con Nano Banana 2.1, un barco de papel rojo sobre un charco de lluvia, reducida a un JPEG de 1024×571 y 158 KB y enviada en línea como data URL. El clip mantiene esa luz de atardecer y los adoquines mojados, mueve el barco de izquierda a derecha como se pidió, hace ondas a los 1.6 segundos y mantiene la cámara baja y quieta. Volvió en 1284×716 porque adaptive siguió la forma de la foto, en 3 min 20 s y 7.4 MB.

¿Está activado el sonido y funciona "no music"?

El sonido está activado por defecto. Gemini 3.8 Flash describió la pista de la fragua como un tintineo metálico, sin voz ni música, y la del barco de papel como una melodía de piano melancólica y tranquila, aunque ese prompt terminaba en "no music". La guía de prompts de Alibaba (actualizada el 16 de octubre de 2026) recomienda escribir "No BGM" o "No background music", y nuestro prompt no usó ninguna de las dos.

Con "audio": false el archivo solo lleva pista de vídeo: nuestro trabajo de farol de 2 segundos en 480P no tenía pista de sonido, y Alibaba cobra lo mismo en ambos casos.

ClipTiempoTamañoSonido
Forja (texto)2 min 42 s1280×720Tintineo, sin música
Barco de papel (imagen)3 min 20 s1284×716Piano pese a "no music"
Linterna, sin audio4 min 36 s854×480Sin pista de sonido

El tiempo en cola varía: el trabajo de 2 segundos sin audio tardó 4 min 36 s, más que cualquiera de los dos clips de 5 segundos en 720P. Para redactar prompts, la guía de prompts de Wan 3.0 tiene la estructura y ejemplos.

¿Cómo obtienes el archivo de vídeo y cuánto duran los enlaces?

Consulta GET /v1/media/tasks/{id} hasta que el estado diga succeeded, failed o canceled; mientras el trabajo corre dice queued o processing. Una tarea terminada devuelve una URL de recurso firmada que dura cerca de una hora (documentación de OmniaKey, comprobada el 31 de octubre de 2026). Descárgala en el acto y consulta la tarea otra vez para obtener una URL nueva cuando la anterior caduque, porque el registro vive 24 horas.

El archivo es un MP4 con vídeo H.264 a 30 fps, y la URL de vídeo de Alibaba dura 24 horas. Cancelar un trabajo de Wan 3.0 no detiene el render, y un trabajo que termina bien después de una cancelación se factura igual, así que revisa duration y resolution antes de enviar.

¿Qué errores vas a encontrar?

La mayoría vuelve antes de que exista una tarea, y cada uno se arregla en la petición o en la clave.

  • 400 model_price_error — duration fuera del rango de 2 a 30 segundos. Nuestra prueba con "duration": 1 falló en 0.9 s con "media duration must be between 2 and 30 seconds"; no se creó ninguna tarea y no se cobró nada.
  • 400 missing_idempotency_key — falta la cabecera Idempotency-Key. Añade una, de hasta 255 caracteres.
  • 409 idempotency_key_reused — misma clave, cuerpo distinto. Acuña una clave nueva para cada prompt.
  • 403 model_not_allowed — la clave no puede llamar a ese modelo. Revisa el valor de model y luego los ajustes de la clave.
  • 403 con un mensaje de saldo o de límite de gasto — saldo bajo o un tope por clave. Recarga o sube el tope.
  • 404 task_not_found — ID equivocado, o una tarea de más de 24 horas. Consulta el ID que devolvió la llamada de creación.
  • 409 task_state_conflict — el trabajo ya terminó, como cuando una cancelación llega después del éxito. Lee el estado primero.
  • 429 — demasiadas peticiones. OmniaKey no publica límites de tasa fijos, así que retrocede con espera exponencial y jitter.
  • 503 no_available_channel — no hay canal para esa operación, como video to video. Usa text to video o image to video.
  • TimeoutError — sigue corriendo después de 15 minutos. Consulta el mismo ID más tarde; un reenvío crea y factura un segundo trabajo.

¿Cuánto cuesta un clip de Wan 3.0?

Alibaba cobra por segundo de vídeo, y una petición fallida no se cobra (página de precios actualizada el 29 de octubre de 2026). La tabla tiene los precios de lista de Alibaba en Singapur por segundo, comprobados el 31 de octubre de 2026 en la página de precios de Model Studio.

Model480P720P1080P
Wan 3.0$0.05$0.1$0.2
Wan 3.0 Prime$0.068$0.14$0.28

Un clip de 5 segundos en 720P cuesta $0.50 en Wan 3.0 (5 × $0.1) y $0.70 en Prime (5 × $0.14). Los tres precios de Wan 3.0 llevan la marca "Limited-time 30% off", y la página no dice si las cifras la incluyen. Con sonido o sin él cuesta lo mismo.

La cuota gratuita es de 30 segundos de vídeo, entrada más salida, en wan3.0-video en Singapur; Prime no tiene ninguna. Alibaba lista tarifas en dólares más bajas en China (Pekín) para el modelo estándar: $0.041256, $0.082513 y $0.165025 por segundo en 480P, 720P y 1080P.

OmniaKey también cobra por segundo, con las tarifas actuales en las páginas de Wan 3.0 y Wan 3.0 Prime.

Preguntas frecuentes

¿Cuánto tarda una llamada?

Alibaba dice que un trabajo suele tardar de 1 a 5 minutos y recomienda consultar cada 15 segundos (referencia, comprobada el 31 de octubre de 2026). Nuestros tres trabajos tardaron 2 min 42 s, 3 min 20 s y 4 min 36 s.

¿Cómo desactivo el sonido?

Pon "audio": false dentro de parameters y el MP4 llega solo con pista de vídeo, como pasó con el trabajo del farol. El precio no cambia.

¿Uso wan3.0-video o wan3.0-video-prime?

Elige wan3.0-video por la tarifa de lista más baja de Alibaba y su cuota gratuita de 30 segundos en Singapur, y Prime cuando el tiempo importe más. OmniaKey describe Prime como las mismas capacidades en aproximadamente la mitad del tiempo.

¿Cuánto dura el enlace del vídeo?

Cerca de una hora en OmniaKey, y consultar la tarea otra vez devuelve un enlace nuevo mientras el registro dura 24 horas. La URL de vídeo de Alibaba dura 24 horas.

Fuentes consultadas

Modelos de este artículo

Wan 3.0video APIPythontext-to-videoimage-to-video

Artículos relacionados

Artículos recientes