Tutoriale
Come usare l'API image-to-video di hailuo 2.3 Fast:curl, Python e richieste eseguibili
Hai un'immagine statica e vuoi trasformarla in un breve video. Questa guida ti mostra come accedere a hailuo-2.3-fast/image-to-video tramite l'API a task di hiapi: lo schema di input esatto (verificato contro il validatore di produzione), una richiesta curl pronta da copiare, uno script Python completo che esegue il polling fino al completamento del task e i dettagli per la produzione — callback, retry idempotenti e le risposte di errore che incontrerai davvero.
Cosa ti serve
- Una chiave API hiapi — ottienila dalla tua console. La chiave ha la forma
sk-...e va inserita nell'headerAuthorization: Bearer. - Un'immagine sorgente ospitata su un URL HTTPS accessibile pubblicamente. L'API riceve un URL, non un file caricato.
- Qualsiasi client HTTP. Gli esempi seguenti usano curl e
requestsdi Python.
Il prezzo al secondo di questo modello è indicato nella pagina dei prezzi.
Schema di input (verificato)
hailuo-2.3-fast/image-to-video usa l'endpoint unificato per task asincroni: POST /v1/tasks crea il task, GET /v1/tasks/<taskId> ne interroga lo stato. Lo schema di input è rigoroso — i campi sconosciuti vengono rifiutati con 400, non ignorati silenziosamente.
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
prompt |
string | ✅ | Descrive il movimento desiderato |
image_url |
string | ✅ | Forma singolare — una stringa URL, non un array image_urls |
duration |
string | Opzionale | "6" o "10" — è una stringa, non un numero |
prompt_optimizer |
boolean | Opzionale | Fa riscrivere il prompt dal backend per il movimento |
Il validatore intercetta tre trappole comuni:
durationdeve essere una stringa. Inviare"duration": 6restituisce400con il messaggioduration: got number, want string. Invia"duration": "6".- Il campo è
image_urlal singolare. Molti altri modelli video della piattaforma (Grok Imagine, Kling) ricevono un arrayimage_urls. Questo modello riceve una singola stringa. - Non esistono
resolution,aspect_ratio,seed,watermarknéend_image_url. Tutti restituisconoadditional properties ... not allowed. Il formato di output segue l'immagine sorgente; il controllo del movimento avviene solo tramite il prompt.
Richiesta minima eseguibile: curl
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": "La camera avanza lentamente, vapore che sale dalla tazza di caffè, morbida luce mattutina",
"image_url": "https://your-cdn.example.com/coffee.jpg",
"duration": "6"
}
}'
Risposta di successo:
{
"code": 200,
"data": { "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V" },
"message": "success"
}
Poi esegui il polling:
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V \
-H "Authorization: Bearer sk-YOUR_KEY"
Mentre il video viene renderizzato, data.status è "handling":
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V",
"model": "hailuo-2.3-fast/image-to-video",
"status": "handling",
"storage": "temp",
"completed": 0,
"created": 1783648872
},
"message": "success"
}
Gli stati terminali sono "success" (l'URL del video è in data.output[0].url) e "fail" (i dettagli sono in data.error).
Script Python completo
import os
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"] # sk-...
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def create_task(prompt: str, image_url: str, duration: str = "6") -> str:
resp = requests.post(
API_BASE,
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": prompt,
"image_url": image_url,
"duration": duration, # stringa: "6" o "10"
},
},
timeout=60,
)
body = resp.json()
if resp.status_code != 200 or not body.get("data", {}).get("taskId"):
raise RuntimeError(f"create failed: {resp.status_code} {body}")
return body["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} still running after {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
prompt="Il gatto sbatte le palpebre, gira la testa verso la finestra, una brezza gli muove il pelo",
image_url="https://your-cdn.example.com/cat.jpg",
duration="6",
)
print("task:", task_id)
task = wait_task(task_id)
video_url = task["output"][0]["url"]
print("video:", video_url)
# L'URL si trova su storage temporaneo con scadenza — scarica subito, non collegarlo direttamente.
mp4 = requests.get(video_url, timeout=120).content
with open("output.mp4", "wb") as f:
f.write(mp4)
print(f"saved output.mp4 ({len(mp4)} bytes)")
Questo script fa correttamente due cose che le soluzioni improvvisate spesso trascurano:
- Scarica subito il video.
storage: "temp"significa che l'URL di output ha una scadenza (expireAt). Salva i byte nel tuo storage; non inserire mai l'URL restituito nel tuo database. - Considera
failuno stato terminale. Ripetere il polling di un task fallito non lo riporta in vita — crea un nuovo task.
Considerazioni per la produzione
Usa le callback invece del polling
Per casi d'uso al di fuori degli script, registra un webhook alla creazione del task e salta del tutto il ciclo di polling:
{
"model": "hailuo-2.3-fast/image-to-video",
"input": { "prompt": "...", "image_url": "https://...", "duration": "6" },
"callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
Con "when": "final", il tuo endpoint viene chiamato una volta quando il task raggiunge success o fail. Regola pratica: il polling va bene per CLI, job batch e qualsiasi scenario temporaneo; quando hai già un server in ascolto, le callback sono preferibili — i task video richiedono alcuni minuti, e un ciclo di polling in quei minuti occupa uno slot di connessione e spreca un worker.
Idempotenza
La chiamata di creazione non è idempotente — ogni POST /v1/tasks che supera la validazione crea un nuovo task (a pagamento). Se il tuo task runner esegue retry al timeout, memorizza il taskId ottenuto con chiave il tuo id di richiesta prima di elaborare il risultato. In caso di retry, se quella chiave ha già un taskId, esegui il polling su di esso invece di creare un task duplicato.
Gli errori che incontrerai davvero
| Sintomo | Significato | Correzione |
|---|---|---|
401 — {"error":{"code":"permission_denied","type":"hiapi_error"}} |
Chiave non valida, o la chiave non può usare questo modello | Controlla la chiave nella console; la risposta include un request_id da fornire al supporto |
400 INVALID_REQUEST — duration: got number, want string |
Hai usato un numero JSON invece di una stringa | "duration": "6" |
400 INVALID_REQUEST — additional properties '...' not allowed |
Hai inviato un campo al di fuori dello schema | Rimuovilo — il messaggio indica ogni campo non valido |
400 INVALID_REQUEST — missing required field "prompt" / "image_url" |
Input vuoto o nome del campo errato | Entrambi i campi sono obbligatori |
Il task arriva a fail dopo la creazione |
Errore in fase di esecuzione — causa comune un URL immagine che il backend non riesce a recuperare | Il validatore non recupera la tua immagine alla creazione; assicurati che l'URL sia accessibile pubblicamente |
L'ultima riga merita enfasi: la validazione alla creazione riguarda solo lo schema. Un image_url sbagliato o privato ti restituisce un taskId apparentemente valido e un task che muore dopo qualche minuto — quindi configura avvisi su fail, non solo sugli errori HTTP.
Letture correlate
- Pagina del modello hailuo-2.3-fast/image-to-video — playground e prezzo al secondo
- Workflow dell'API image-to-video: guida per la produzione — architettura di batch, storage e retry attorno all'endpoint i2v
- API text-to-video vs image-to-video — quando ancorare la generazione a un'immagine sorgente
- Guida all'API image-to-video di Kling — stessa API a task, schema di input diverso, utile confronto
Domande frequenti
Posso impostare risoluzione o rapporto d'aspetto?
No. Lo schema di hailuo-2.3-fast/image-to-video rifiuta resolution e aspect_ratio come campi sconosciuti. Il formato di output segue l'immagine sorgente; se ti serve un rapporto d'aspetto specifico, ritaglia prima l'immagine di input.
Quali durate sono supportate?
Esattamente due: "6" e "10" secondi, passati come stringhe. Qualsiasi altro valore restituisce 400 con il messaggio value must be one of '6', '10'.
Posso passare più immagini di riferimento?
No — il campo è un singolo image_url stringa. I modelli che accettano array di immagini (ad esempio image_urls di Grok Imagine) usano uno schema diverso; non copiare il body di richiesta tra modelli senza controllare.
Come controllo il movimento?
Solo tramite prompt — non esistono parametri per intensità di movimento o camera. Descrivi il movimento in modo esplicito ("la camera avanza lentamente", "i capelli ondeggiano al vento"). Facoltativamente, imposta "prompt_optimizer": true per far espandere il prompt dal backend.
Esiste una variante più lenta e di qualità superiore?
Sì — hailuo-2.3/image-to-video (senza -fast) è anch'esso disponibile sulla piattaforma, e hailuo-2.3/text-to-video copre gli scenari senza immagine sorgente. Controlla lo schema di ciascuna variante prima di passare da una all'altra; i campi di input non sono garantiti identici.
Quanto costa? La fatturazione si basa sui secondi di video generato e varia in base al modello; consulta le tariffe attuali nella pagina dei prezzi.
Serve una chiave API per provare?
Sì — tutte le chiamate all'API a task richiedono una chiave Bearer sk-.... Puoi crearne una nella console e testarla prima nel playground della pagina del modello.
Articoli correlati
Vedi tutti gli articoli →-
Tutoriale
Come chiamare hailuo-2.3-fast/image-to-video tramite l'API HiAPI: pratica con curl e Python
La prima richiesta funzionante per il livello image-to-video veloce ed economico — dall'ID del modello al download di un MP4
-
Tutoriale
Come chiamare hailuo-2.3/text-to-video tramite l'API HiAPI: curl, Python ed esempi di richiesta eseguibili
-
Tutoriale
Utilizzare Kandinsky 6.0 Pro su HiAPI per la generazione di video da testo: tutorial con curl e Python
Dimostrazione pratica guidata dalla richiesta: costruire la chiamata da prompt a clip video, inviare la richiesta, monitorare lo stato di completamento e scaricare il risultato