Tutoriale
Come usare veo-3.1-lite/image-to-video tramite l'API hiapi
- Modello
- veo-3.1-lite
Veo 3.1 Lite trasforma una singola immagine di riferimento più un prompt testuale in un breve video, e su hiapi è esposto tramite la stessa API asincrona a task condivisa da tutti i modelli della piattaforma. Questa guida percorre un flusso di richiesta realmente funzionante: ottenere la chiave, chiamare POST /v1/tasks, recuperare il risultato e i dettagli da considerare quando si passa da uno script usa-e-getta alla produzione (callback, idempotenza, gestione degli errori).
Cosa costruirai e cosa preparare prima
Invierai un URL di immagine e un prompt al modello veo-3.1-lite/image-to-video, ottenendo in risposta un URL .mp4 ospitato esternamente. Tutto passa attraverso l'endpoint unificato a task di hiapi, quindi la stessa struttura di richiesta vale per ogni modello video e immagine della piattaforma — cambiano solo l'id model e i campi input.
Prima di iniziare:
- Crea un account hiapi e ottieni una chiave API dalla dashboard. La chiave ha la forma
sk-.... - Prepara un URL di immagine accessibile pubblicamente — l'API la recupera lato server, quindi percorsi
localhosto bucket privati non funzionano. - Prima di eseguire richieste reali (non di test), controlla il prezzo attuale di
veo-3.1-lite/image-to-videonella pagina dei prezzi, perché il costo dipende da durata e risoluzione.
Non esiste un piano gratuito né una modalità senza chiave — ogni chiamata richiede Authorization: Bearer sk-<your-key>.
Esempio minimo funzionante
L'API a task di hiapi consiste in due chiamate: creare il task, poi o interrogarlo periodicamente oppure lasciare che una callback ti avvisi quando è completato. Di seguito la versione con polling in Python, che usa solo requests e time:
import time
import requests
API_KEY = "sk-your-key-here"
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
payload = {
"model": "veo-3.1-lite/image-to-video",
"input": {
"prompt": "the camera slowly pushes in as steam rises from the cup",
"image_url": "https://example.com/your-reference-image.jpg",
"duration": 6,
"aspect_ratio": "16:9",
},
}
# 1. Create the task
resp = requests.post(BASE, headers=HEADERS, json=payload, timeout=60)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
print("task created:", task_id)
# 2. Poll until it's done
while True:
task = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
status = task["status"]
if status == "success":
video_url = task["output"][0]["url"]
print("done:", video_url)
break
if status == "fail":
raise RuntimeError(task.get("error"))
time.sleep(5)
Se vuoi solo vedere il formato di trasferimento sulla rete, ecco la stessa cosa in curl grezzo:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-your-key-here" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-lite/image-to-video",
"input": {
"prompt": "the camera slowly pushes in as steam rises from the cup",
"image_url": "https://example.com/your-reference-image.jpg",
"duration": 6,
"aspect_ratio": "16:9"
}
}'
# then poll:
curl -s https://api.hiapi.ai/v1/tasks/<taskId> \
-H "Authorization: Bearer sk-your-key-here"
Ci sono alcuni aspetti dello schema di input che vale la pena conoscere, perché è più rigoroso di un endpoint generico che accetta qualunque cosa — i campi in eccesso vengono rifiutati direttamente, non ignorati silenziosamente:
prompteimage_urlsono gli unici due campi obbligatori.image_urlè singolare — questo modello accetta esattamente una immagine di riferimento, non un array.durationaccetta solo4,6o8(secondi) — nessun altro intero.aspect_ratioaccettaauto,16:9o9:16.resolutionaccetta720po1080p.- Extra opzionali:
seed(intero, per la riproducibilità),generate_audio(booleano),negative_prompt(stringa).
Nota che l'id del modello è un id nudo, cioè veo-3.1-lite/image-to-video — non aggiungergli prefissi o namespace.
Quando status diventa "success", il video di output si trova in data.output[0].url. Quell'URL è temporaneo (con expireAt), quindi scaricalo o ri-ospitalo subito, invece di salvare il hotlink.
Considerazioni per la produzione: callback, idempotenza ed errori
Interrogare ogni 5 secondi va bene per uno script, ma è uno spreco in un server che gestisce molti task contemporaneamente. Per il traffico di produzione è preferibile usare le callback: passa un oggetto callback nella stessa richiesta di creazione del task e hiapi farà un POST del risultato finale al tuo endpoint, invece di essere tu a interrogarlo.
payload = {
"model": "veo-3.1-lite/image-to-video",
"input": {
"prompt": "the camera slowly pushes in as steam rises from the cup",
"image_url": "https://example.com/your-reference-image.jpg",
},
"callback": {
"url": "https://yourapp.example.com/hooks/hiapi",
"when": "final",
},
}
L'impostazione chiave qui è when: "final" — significa che riceverai una notifica una sola volta, quando il task raggiunge uno stato terminale (success o fail), e non a ogni cambio di stato intermedio. Il tuo handler webhook dovrebbe verificare l'id del task e poi recuperare il record locale del task creato quando hai chiamato POST /v1/tasks la prima volta.
Idempotenza. Se il tuo servizio può ritentare la chiamata di creazione del task (timeout, consegna at-least-once, ecc.), aggiungi un header Idempotency-Key, lungo al massimo 255 byte:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-your-key-here" \
-H "Idempotency-Key: order-42-veo-submit" \
-H "Content-Type: application/json" \
-d '{...}'
Ritentare con la stessa chiave nello stesso account restituisce il taskId originale, invece di crearne un secondo (fatturabile) — puoi quindi lanciarlo in sicurezza da un ciclo di retry senza addebitare due volte il cliente.
Polling vs. callback, in breve: per script, notebook o strumenti interni a basso volume, usa il polling se stai comunque aspettando il risultato in modo bloccante. Per qualsiasi scenario server-side e concorrente, usa le callback — evitano di tenere aperte le connessioni e scalano su molti task in corso senza dover eseguire un ciclo di polling per ciascuno.
Gestione degli errori. Una chiave errata o revocata restituisce HTTP 401 con error.code: "permission_denied" — controlla specificamente questo caso, invece di presumere che qualsiasi risposta non-2xx significhi che la generazione del video è fallita. Un input malformato (prompt mancante, duration fuori dall'enum, campi non riconosciuti) restituisce HTTP 400 con error_code: "INVALID_REQUEST" e un messaggio che indica il campo problematico specifico — vale la pena mostrarlo direttamente nei tuoi log, invece di ignorarlo, perché il messaggio ti dice esattamente cosa correggere. Una volta accettato il task, i fallimenti lato generazione si manifestano nel payload di polling/callback con status: "fail" e un oggetto error — trattalo come riprovabile solo se il messaggio indica un problema transitorio a monte, non un problema di schema.
Risorse correlate
- Documentazione del modello veo-3.1-lite/image-to-video — riferimento completo dei parametri per questo modello specifico
- Crea task e Ottieni dettagli task — i due endpoint su cui si basa questa guida
- Documentazione sull'autenticazione — formato delle chiavi e requisiti degli header
- Veo 3.1 Image-to-Video: guida ai video brevi — la spiegazione dei casi d'uso se desideri output a più alta fedeltà dal modello non-lite
- Prezzi — le tariffe attuali al secondo in base a durata e risoluzione
Domande frequenti
Devo passare image_url come data URI o base64?
No — image_url deve essere un URL HTTP(S) pubblico che i server hiapi possono recuperare. Questo modello non accetta immagini codificate in base64.
Posso generare un video senza immagine di riferimento?
Con veo-3.1-lite/image-to-video no — è un modello image-to-video, image_url è obbligatorio. Se vuoi la generazione da solo testo, usa un modello text-to-video; la pagina del modello Veo 3.1 non-lite elenca le modalità disponibili.
Perché ricevo ancora 400 anche se ho passato tutti i campi obbligatori?
Controlla se ci sono campi extra — lo schema di input di questo modello rifiuta tutto ciò che non è nella lista consentita (prompt, image_url, duration, aspect_ratio, resolution, seed, generate_audio, negative_prompt). Il messaggio di errore indica il campo esatto che non riconosce.
Quanto tempo richiede effettivamente la generazione? Varia in base alla durata e alla profondità corrente della coda: è proprio per questo che è corretto fare polling a intervalli brevi o usare le callback, invece di presumere un tempo di attesa fisso.
L'output può includere audio?
Sì, tramite il booleano generate_audio — consulta la documentazione del modello per i valori predefiniti attuali e come influisce sul costo.
Cosa succede se il mio endpoint di callback è inattivo quando il task si completa?
Non affidarti solo all'arrivo della callback — conserva il taskId restituito dalla chiamata di creazione e, se non ricevi la callback entro una finestra di tempo ragionevole, passa al polling con GET /v1/tasks/<id>.
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