GPT-6 Sol e Claude Opus 5.5 disponibiliGPT-6 Sol a metà prezzo rispetto a 5.6 Sol

Wan 3.0 API: come creare video da testo e da immagine in Python

Un solo script ha prodotto entrambe le clip: il codice, i tempi reali e il prezzo al secondo di Alibaba.

Kiki, OmniaKey COO8 min di lettura
In questa pagina

Wan 3.0 gira su Alibaba Cloud Model Studio come wan3.0-video e come wan3.0-video-prime, più veloce. Ogni chiamata è asincrona: crei un task, interroghi l'ID, scarichi l'MP4. Il nostro script Python ha prodotto una clip 720P di 5 secondi da un testo in 2 min 42 s e una da una foto ferma in 3 min 20 s, entrambe con l'audio.

  1. Metti la chiave in OMNIAKEY_API_KEY.
  2. Fai una POST a https://api.omniakey.com/v1/media/tasks con modello, operazione, prompt, parametri e una nuova Idempotency-Key.
  3. Interroga GET /v1/media/tasks/{id} finché lo stato non è succeeded, poi scarica subito assets[0].url.

Esiste un'API ufficiale di Wan 3.0, e quale modello uso?

Sì. L'API ufficiale è Alibaba Cloud Model Studio, con wan3.0-video e wan3.0-video-prime (riferimento aggiornato il 15 ottobre 2026). La chiamata di creazione richiede l'header X-DashScope-Async: enable, e la via Python di Alibaba è DashScope SDK 2.0.1 o successivo.

Alibaba Model StudioOmniaKey
I due ID modelloSìSì
Header asyncServeNon serve
Link al video24 oreCirca 1 ora, rinnovabile
AddebitoAl secondoAl secondo
PythonDashScope SDKLibreria standard

I due ID accettano lo stesso body, e il modello sceglie la modalità dal media che invii. Lo script sotto esegue wan3.0-video, e la riga MODEL lo cambia. Non abbiamo eseguito Wan 3.0 Prime, che la documentazione di OmniaKey descrive con le stesse capacità e tempi circa dimezzati (verificato il 31 ottobre 2026).

Cosa serve prima della prima chiamata?

Tre cose, e la prima è la chiave:

  1. Una chiave API OmniaKey, esportata nella shell:

    bash
    export OMNIAKEY_API_KEY="your-key"
    
  2. Python 3. Lo script importa solo la libreria standard, quindi python3 lo esegue così com'è.

  3. Per image to video serve un primo fotogramma: un JPEG largo circa 1024 px, oppure un URL HTTPS pubblico. Lo script rifiuta un file oltre 700.000 byte, perché Base64 aggiunge un terzo e il limite del body è 1 MiB (documentazione, verificata il 31 ottobre 2026).

Quali parametri contano?

Sette campi fanno quasi tutto il lavoro, e ognuno è un valore dentro parameters.

ParametroA cosa serveDefault
DurataLunghezza della clip, secondi5
RisoluzioneFascia di dimensione dell'immagine1080P
ProporzioniForma del fotogrammaadaptive
AudioTraccia sonoraattivo
SeedIndizio di ripetibilità-1
Prompt extendRiscrive il tuo promptattivo
WatermarkAggiunge un segno nell'angolospento

Lo script imposta durata, risoluzione e proporzioni. Chiede 720P mentre il default di Alibaba è 1080P, che ai prezzi di listino costa il doppio al secondo.

Come è fatto il codice Python?

Lo script sotto ha girato senza modifiche il 31 ottobre 2026: solo libreria standard, due modalità, una riga MODEL da cambiare.

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",
    ))

Cosa fa ogni parte:

  • run_task genera una nuova Idempotency-Key per ogni job. Rimandare la stessa chiave con lo stesso body restituisce il task originale e non addebita due volte (documentazione, verificata il 31 ottobre 2026).
  • Interroga ogni 5 secondi per un massimo di 15 minuti, poi solleva TimeoutError.
  • Un timeout significa interrogare di nuovo lo stesso ID più tardi; un nuovo invio genera una chiave nuova, crea un secondo job e lo fattura.
  • Scarica subito il primo URL dell'asset, perché il link firmato dura poco.
  • image_to_video rifiuta un fotogramma oltre 700.000 byte: Base64 aggiunge un terzo e il limite del body è 1 MiB.
  • La chiamata con immagine imposta le proporzioni su adaptive, così la clip segue la forma della foto ferma.

Cosa stampa:

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

Cosa hanno prodotto le due chiamate?

Entrambi i file sono tornati come MP4 da 5.04 secondi, 150 fotogrammi a 30 fps, H.264, con traccia stereo AAC a 44.1 kHz.

Testo in video: la forgia

Quattro fotogrammi dalla clip della forgia di Wan 3.0
Testo in video, 5 s a 720P: fotogrammi a 0.3, 2.2, 3.5 e 4.7 secondi.

La clip segue il prompt: un fabbro in camicia scura e grembiule di cuoio martella un ferro di cavallo arancione incandescente, a 2.2 secondi partono le scintille e la camera si avvicina un po'. Il difetto è un marchio del fabbro con lettere illeggibili sull'incudine, anche se il prompt chiedeva nessun testo. Dall'avvio al file sono passati 2 min 42 s; l'MP4 è 1280×720 a 6.6 MB.

Immagine in video: la barca di carta

La foto ferma del primo fotogramma e tre fotogrammi dalla clip della barca di carta di Wan 3.0
Immagine in video: la foto ferma che abbiamo inviato (in alto a sinistra), poi la clip a 1.6, 3.5 e 4.7 secondi.

Il primo fotogramma era una foto ferma fatta con Nano Banana 2.1, una barca di carta rossa su una pozzanghera, ridimensionata a un JPEG 1024×571 da 158 KB e inviata inline come data URL. La clip mantiene quella luce di crepuscolo e i sampietrini bagnati, sposta la barca da sinistra a destra come richiesto, crea increspature a 1.6 secondi e tiene la camera bassa e ferma. È tornata 1284×716 perché adaptive ha seguito la forma della foto, in 3 min 20 s a 7.4 MB.

L'audio è attivo, e "no music" funziona?

L'audio è attivo per default. Gemini 3.8 Flash ha descritto la traccia della forgia come tintinnio metallico senza parlato e senza musica, e quella della barca di carta come una melodia di pianoforte malinconica e calma, anche se quel prompt finiva con "no music". La guida ai prompt di Alibaba (aggiornata il 16 ottobre 2026) consiglia di scrivere "No BGM" o "No background music", e il nostro prompt non usava nessuno dei due.

Con "audio": false il file porta solo la traccia video: il nostro job della lanterna, 2 secondi a 480P, non aveva traccia audio, e Alibaba fattura lo stesso in entrambi i casi.

ClipTempoDimensioneAudio
Forgia (testo)2 min 42 s1280×720Tintinnio, niente musica
Barca di carta (immagine)3 min 20 s1284×716Pianoforte nonostante "no music"
Lanterna, audio off4 min 36 s854×480Nessuna traccia audio

Il tempo in coda varia: il job da 2 secondi con audio off ha impiegato 4 min 36 s, più di entrambe le clip 720P da 5 secondi. Per come scrivere il prompt, la guida ai prompt di Wan 3.0 ha la struttura e prompt di esempio.

Interroga GET /v1/media/tasks/{id} finché lo stato non è succeeded, failed o canceled; mentre il job gira lo stato è queued o processing. Un task finito restituisce un URL firmato dell'asset che dura circa un'ora (documentazione OmniaKey, verificata il 31 ottobre 2026). Scaricalo subito, poi interroga di nuovo il task per un URL fresco quando il vecchio scade, perché il record vive 24 ore.

L'MP4 ha video H.264 a 30 fps, e l'URL video di Alibaba dura 24 ore. Annullare un job Wan 3.0 non ferma il render, e un job che riesce dopo l'annullamento viene fatturato lo stesso, quindi controlla durata e risoluzione prima di inviare.

Quali errori incontrerai?

La maggior parte arriva prima che esista un task, e ognuno ha una correzione nella richiesta o nella chiave.

  • 400 model_price_error — durata fuori dai 2-30 secondi. Il nostro test con "duration": 1 è fallito in 0.9 s con "media duration must be between 2 and 30 seconds"; nessun task creato e niente fatturato.
  • 400 missing_idempotency_key — manca l'header Idempotency-Key. Aggiungine uno, fino a 255 caratteri.
  • 409 idempotency_key_reused — stessa chiave, body diverso. Genera una chiave nuova per ogni prompt.
  • 403 model_not_allowed — la chiave non può chiamare quel modello. Controlla il valore model, poi le impostazioni della chiave.
  • 403 con un messaggio su saldo o limite di spesa — saldo basso o limite per chiave. Ricarica o alza il limite.
  • 404 task_not_found — ID sbagliato, o task più vecchio di 24 ore. Interroga l'ID restituito dalla chiamata di creazione.
  • 409 task_state_conflict — il job è già finito, per esempio un annullamento arrivato dopo il successo. Leggi prima lo stato.
  • 429 — troppe richieste. OmniaKey non pubblica limiti di frequenza fissi, quindi fai backoff con attesa esponenziale e jitter.
  • 503 no_available_channel — nessun canale per quell'operazione, come video to video. Usa text to video o image to video.
  • TimeoutError — ancora in esecuzione dopo 15 minuti. Interroga lo stesso ID più tardi; un nuovo invio crea e fattura un secondo job.

Quanto costa una clip di Wan 3.0?

Alibaba fattura al secondo di video, e una richiesta fallita non viene fatturata (pagina dei prezzi aggiornata il 29 ottobre 2026). La tabella riporta i prezzi di listino di Alibaba a Singapore al secondo, verificati il 31 ottobre 2026, dalla pagina dei prezzi di Model Studio di Alibaba.

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

Secondo Alibaba una clip 720P da 5 secondi costa $0.50 su Wan 3.0 (5 × $0.1) e $0.70 su Prime (5 × $0.14). I tre prezzi di Wan 3.0 hanno la scritta "Limited-time 30% off", e la pagina non dice se le cifre la includono. Con audio on o off il prezzo è lo stesso.

La quota gratuita di Alibaba è 30 secondi di video, input più output, su wan3.0-video a Singapore; Prime non ne ha. La regione Cina (Pechino) di Alibaba elenca tariffe in dollari più basse per il modello standard: $0.041256, $0.082513 e $0.165025 al secondo a 480P, 720P e 1080P.

Anche OmniaKey fattura al secondo, con le tariffe attuali nelle pagine dei modelli Wan 3.0 e Wan 3.0 Prime.

Domande frequenti

Quanto dura una chiamata?

Alibaba dice che un job richiede di solito da 1 a 5 minuti e consiglia di interrogare ogni 15 secondi (riferimento, verificato il 31 ottobre 2026). I nostri tre job hanno impiegato 2 min 42 s, 3 min 20 s e 4 min 36 s.

Come disattivo l'audio?

"audio": false dentro parameters fa arrivare l'MP4 con la sola traccia video, come nel nostro job della lanterna. Il prezzo resta uguale.

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

Scegli wan3.0-video per la tariffa di listino più bassa di Alibaba e per la quota gratuita di 30 secondi a Singapore, e Prime quando conta di più il tempo di elaborazione. OmniaKey descrive Prime con le stesse capacità e circa metà del tempo.

Circa un'ora su OmniaKey, e interrogare di nuovo il task restituisce un link fresco finché il record dura 24 ore. L'URL video di Alibaba dura 24 ore.

Fonti verificate

Modelli citati in questo articolo

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

Articoli correlati

Articoli recenti