Tutoriale
Come chiamare happyhorse-1.1/image-to-video sull'API hiapi: guida con curl e Python
Cosa fa questo endpoint e quando usarlo
happyhorse-1.1/image-to-video trasforma una singola immagine statica in un breve video. Invii a questo endpoint un'immagine del primo fotogramma e il modello genera l'animazione a partire da quel fotogramma. Il punto chiave è la continuità: soggetto, composizione e aspetto presenti nell'immagine iniziale si estendono nel frammento generato. È quello che qui chiamiamo conservazione dell'identità: il modello non crea una scena nuova dal nulla basandosi solo su un prompt testuale, ma continua una scena che hai già creato con un'immagine.
Di conseguenza, questo endpoint è particolarmente adatto quando l'identità visiva conta più dell'improvvisazione:
- Hai già un fotogramma di riferimento — un ritratto, una foto di prodotto, un character sheet — e vuoi un movimento fedele a quel fotogramma.
- Produci un breve video all'interno di una pipeline in cui tutti gli altri materiali sono stati progettati prima come immagini.
- Ti serve un'animazione di prova o un'anteprima di movimento per i fotogrammi di uno storyboard.
È invece poco adatto quando vuoi che il modello reinterpreti liberamente la scena da zero, oppure quando non hai un fotogramma statico che ancori l'output. In questi casi, un flusso di lavoro image-first di solito significa generare prima un'immagine di ancoraggio e poi passare il risultato a questo endpoint.
La chiamata stessa è asincrona: invii un job e poi esegui il polling finché il video non è pronto. Il resto di questa guida ripercorre l'intero ciclo di vita, dall'inizio alla fine.
Prima di inviare la richiesta
Prima della prima chiamata servono due cose.
API key
Tutte le chiamate passano attraverso la piattaforma hiapi, con l'API key allegata come credenziale bearer. Conserva la chiave in una variabile d'ambiente, non nel controllo di versione, così lo stesso codice funziona sia in locale sia in CI:
export HIAPI_API_KEY="your_key_here"
In Python, leggila a runtime con os.environ["HIAPI_API_KEY"]. Non registrare mai il valore grezzo dell'header.
Un'immagine del primo fotogramma a cui fare riferimento
Questo endpoint richiede un'immagine iniziale. Decidi in anticipo come passarla — come URL raggiungibile dalla piattaforma oppure come materiale caricato/codificato in base64, a seconda di ciò che supportano il tuo account e la documentazione dell'endpoint. L'importante è che il riferimento sia stabile e accessibile al momento dell'invio. Se il job può andare in coda, un URL firmato che scade dopo cinque minuti è una pessima scelta.
È utile anche conoscere in anticipo il rapporto d'aspetto e la durata previsti dell'output, perché il primo fotogramma di solito li vincola. Prendere questa decisione in anticipo evita di dover reinviare il job più tardi.
Una volta esportata la chiave e definito il riferimento dell'immagine, sei pronto per inviare.
Preparare l'input del primo fotogramma
Il primo fotogramma è l'ancora di tutto ciò che il modello genera a seguire. In pratica, va trattato come un contratto d'identità: tutto ciò che è chiaramente visibile in quell'immagine — volti, abbigliamento, loghi, palette colori, angolazione della camera — è ciò a cui il modello deve attenersi. Se un dettaglio nel fotogramma è sfocato o occluso, anche l'output sarà sfocato.
Indipendentemente dai parametri specifici del modello, valgono questi principi di preparazione:
- Scegli un fotogramma nitido e ben illuminato. Gli artefatti di compressione e il rumore intenso riducono ciò che il modello può conservare. Un'immagine nitida e con luce uniforme è un'ancora migliore di un'immagine scenografica ma sfocata.
- Posiziona il soggetto dove vuoi che inizi il movimento. Ritagliare e comporre nel fotogramma statico costa meno che sperare che il modello ricomponga l'inquadratura.
- Mantieni il rapporto d'aspetto previsto per l'output. Se il video finale è orizzontale, prepara un'immagine di ancoraggio orizzontale; il padding successivo non recupererà la composizione perduta.
- Evita indizi contraddittori. Un fotogramma che si legge in un modo ma implica azioni fuori campo dà al modello un punto di partenza instabile.
Non dare per scontati parametri specifici del modello che non siano nella documentazione dell'endpoint. L'approccio più sicuro è lasciare che sia l'immagine stessa a portare l'intenzione, e poi usare i campi della richiesta solo per ciò che coprono esplicitamente.
Inviare una richiesta funzionante con curl
Per inviare un job basta una singola POST. La struttura è: inviare una richiesta autenticata all'endpoint, con un corpo JSON che contiene l'identificatore del modello e l'input immagine.
curl -sS -X POST "https://api.hiapi.ai/v1/video/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.1/image-to-video",
"input": {
"image": "https://your-bucket.example.com/first-frame.jpg"
}
}'
Spiegazione passo per passo:
- Endpoint. La POST va alla rotta di generazione video sull'API hiapi. Se scrivi script per più ambienti, mettila in una variabile.
- Header di autenticazione.
Authorization: Bearer $HIAPI_API_KEY— la shell espande la variabile d'ambiente esportata prima. - Content type.
application/json, perché il corpo è JSON. - Corpo della richiesta.
modelselezionahappyhorse-1.1/image-to-video;input.imageè il riferimento al tuo primo fotogramma. Consulta la documentazione di riferimento dell'endpoint per conoscere il nome esatto del campo immagine e la struttura accettati dal tuo account.
Una risposta riuscita non è il video stesso, ma un handle del job. Aspettati un identificatore e un campo di stato, di solito qualcosa come queued o processing. Annota l'ID: ti servirà per il polling nei passaggi successivi. Esegui il comando una volta e stampa la risposta, così ne vedi la struttura prima di iniziare a scrivere lo script.
Inviare la stessa richiesta con Python
La versione Python è un porting diretto, non una nuova integrazione. Stessa rotta, stessi header, stesso corpo JSON.
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
URL = "https://api.hiapi.ai/v1/video/generations"
payload = {
"model": "happyhorse-1.1/image-to-video",
"input": {
"image": "https://your-bucket.example.com/first-frame.jpg"
},
}
resp = requests.post(
URL,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
resp.raise_for_status()
job = resp.json()
print(job)
Note di corrispondenza:
requestsconjson=payloadserializza il dizionario come fa la stringa-ddi curl — se usijson=, non impostareContent-Typea mano; ci pensa la libreria. L'header esplicito qui sopra è innocuo ma ridondante.raise_for_status()trasforma subito in eccezione i fallimenti a livello HTTP, prima che tu inizi a fare polling di un job inesistente.timeoutè solo una protezione lato client sulla chiamata di invio. La generazione avviene sul server e non è vincolata da esso.
Conserva il payload in una variabile e riusala. Quando in futuro cambierai modello o immagine, dovrai modificare un solo dizionario, non due implementazioni parallele.
Gestire i job asincroni e il polling
La generazione da immagine a video richiede più tempo di un ciclo richiesta/risposta. Per questo l'API restituisce subito un riferimento al job e si aspetta che tu lo ricontrolli più tardi. Il ciclo di vita è: invio, ricezione dell'ID, polling dello stato, recupero del risultato.
Estrai l'ID del job dalla risposta di invio — il nome del campo dipende dallo schema di risposta documentato per questo endpoint, quindi leggilo una volta e codifica la ricerca della chiave, non il valore:
job_id = job["id"] # check the endpoint docs for the exact field
Poi esegui il polling a intervalli:
import time
poll_url = f"https://api.hiapi.ai/v1/video/generations/{job_id}"
while True:
status = requests.get(
poll_url,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
).json()
if status["status"] == "succeeded":
break
if status["status"] == "failed":
raise RuntimeError(status)
time.sleep(5)
Regole per un polling ragionevole:
- Interroga a intervalli fissi, non in un ciclo serrato. Per job di questa entità, qualche secondo tra un controllo e l'altro è sufficiente; martellare l'endpoint aumenta il carico senza far arrivare prima il risultato.
- Limita il tempo di attesa totale. Un
while Truesenza limite è un blocco che prima o poi accadrà. Monitora il tempo trascorso e fallisci in modo esplicito dopo un budget ragionevole. - Gestisci entrambi gli stati terminali. Successo e fallimento sono entrambe risposte. Tratta le stringhe di stato sconosciute come non terminali, ma registrale, così noterai cambiamenti di schema.
- Non fare polling dello stesso job da più worker in parallelo. Un poller per job, oppure coordina tramite una coda.
Una volta che lo stato è terminale, passa a scaricare il risultato.
Scaricare e archiviare l'output
Il video completato viene esposto nella risposta del job completato come materiale — di solito un URL, a volte con scadenza. Il primo passo dopo un polling riuscito è recuperare quel riferimento e copiare i byte in uno storage sotto il tuo controllo.
video_url = status["output"]["video_url"] # inspect the real response shape
with requests.get(video_url, stream=True, timeout=120) as r:
r.raise_for_status()
with open(f"out/{job_id}.mp4", "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 20):
f.write(chunk)
Linee guida sullo storage valide per qualsiasi pipeline:
- Copia gli artefatti persistenti, non linkarli. Gli URL firmati o a scadenza sono un mezzo di trasporto, non uno storage. Salva il file, poi memorizza nel database la tua chiave dell'oggetto insieme all'ID del job.
- Gestisci i file grandi in streaming.
iter_contentmantiene la memoria stabile; caricare l'intero video in una variabile lega il limite di memoria alla dimensione del materiale. - Registra la provenienza. Conserva insieme al materiale il
job_id, il riferimento all'immagine di input e l'identificatore del modello. Quando dovrai riprodurre il frammento, quel record è la ricetta. - Controlla lo stato HTTP prima di scrivere. Una scrittura parziale dovuta a una risposta di errore è peggio di un fallimento pulito, perché sembra un file valido.
Una volta che il file è su disco o nello storage a oggetti, la pipeline si chiude e puoi passare al fotogramma successivo.
Errori e insidie da tenere d'occhio
La maggior parte dei fallimenti di questo endpoint è prevedibile. Ecco una lista breve:
- Input del primo fotogramma malformato o non raggiungibile. La causa più comune di rifiuto dell'invio. Verifica che l'URL dell'immagine si risolva pubblicamente, che il formato sia accettato dall'endpoint e che il campo immagine sia annidato correttamente nel payload. Riproduci con una chiamata curl per distinguere problemi di autenticazione da problemi di payload.
- Polling prima che il job esista. Leggere l'ID dal campo sbagliato o interrogare una rotta che non corrisponde alla risposta di invio genera 404 che sembrano fallimenti del job. Stampa una volta la risposta di invio e fissa la ricerca delle chiavi su quella.
- Attesa illimitata. Senza timeout, un job bloccato appende il worker all'infinito. Imposta un budget, fai fallire e genera un avviso.
- Link al materiale perso. La generazione riesce, ma l'URL viene consumato una volta e non copiato. Salva i byte al momento del recupero e conserva le tue chiavi; non affidarti al link restituito come storage a lungo termine.
- Fuga di credenziali. Incollare la chiave in un notebook e committarla per errore è un problema ricorrente. Caricala dall'ambiente e, in caso di dubbio, ruotala.
- Dare per scontati parametri non documentati dell'endpoint. Se ti serve un parametro non elencato, allora non esiste. Esprimi l'intenzione solo tramite l'immagine del primo fotogramma e i campi documentati.
Gestite queste cose, il flusso asincrono diventa banale — che è esattamente ciò che vuoi in una pipeline di produzione. Per i nomi dei campi specifici dell'endpoint e i valori accettati, tieni aperta la documentazione di riferimento dell'endpoint mentre costruisci.
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