HiAPI
Blog

Tutoriale

Come chiamare l'API text-to-video di Kling 2.5 Turbo: guida con curl e Python

Nov 3, 2026
深松绿背景上几块被直线分割成哑光平面的巨型棱镜,配鼠尾草绿与雾绿色面,构成本教程文章的抽象几何封面图。

Cosa offre l'endpoint kling-2.5-turbo/text-to-video

kling-2.5-turbo/text-to-video è il modello text-to-video offerto da HiAPI. Gli fornisci un prompt testuale e restituisce un video generato. Il "turbo" nel nome indica la direzione dell'ottimizzazione: un tempo di risposta più rapido rispetto al livello di qualità standard, al costo di perdere alcuni dettagli. Per rendering di bozze, anteprime di storyboard, montaggi per i social media e iterazioni creative, questo compromesso è di solito quello giusto.

Prima di scrivere la prima riga di codice, la cosa più importante da interiorizzare è questa: è un endpoint asincrono. La generazione video richiede da secondi a minuti, ben oltre qualsiasi timeout HTTP ragionevole. Per questo l'API è suddivisa in due operazioni:

  1. Invio — esegui una POST con prompt e parametri e ricevi immediatamente un identificatore del job.
  2. Polling — esegui ripetutamente una GET del job con quell'identificatore finché non raggiunge uno stato terminale, poi leggi il risultato video dal payload della risposta completata.

Se provi a modellarlo come una singola chiamata bloccante, incontrerai timeout, generazioni duplicate nei retry e reset di connessione sotto carico elevato. Il pattern invia-poi-polling non è un fastidio da aggirare; è il modello mentale corretto. Ogni esempio di codice qui sotto è costruito attorno ad esso, e una volta interiorizzato questo, il resto dell'integrazione è immediato.

C'è anche un'aspettativa da fissare: l'endpoint è stateful, ma lo stato risiede sul server, non dalla tua parte. I job esistono indipendentemente dalla tua connessione HTTP. Il tuo script può andare in crash a metà del polling, riavviarsi e riconnettersi allo stesso job tramite l'ID — a patto che tu abbia persistito quell'ID da qualche parte. Progetta tenendo conto di questo fin dall'inizio.

Struttura della richiesta: prompt, preset veloce e durata flessibile

Controlli solo pochi campi, ma ognuno ha un impatto sostanziale sul job. Ecco le parti che contano davvero.

Il prompt

Il prompt è l'input creativo principale. Trattalo come la descrizione di un'inquadratura, non come una query di ricerca. Un buon prompt per questo modello di solito include:

  • Soggetto — chi o cosa è sullo schermo.
  • Azione — cosa fa il soggetto nella clip.
  • Movimento di camera — composizione e movimento, ad esempio slow dolly in, static wide shot, handheld follow.
  • Ambiente e illuminazione — scena, momento della giornata, atmosfera.
  • Stile — se vuoi orientare l'aspetto, puoi scrivere cinematic, anime, product photography e simili.

Rimani specifico e metti il soggetto per primo. I prompt vaghi producono movimento vago, e il livello turbo amplifica questo perché lascia meno spazio all'interpretazione.

Il preset fast/turbo

La famiglia di modelli supporta un preset veloce che scambia parte della finezza con la latenza. Quando lo abiliti, stai dicendo al backend di dare priorità alla velocità — il movimento resta coerente, ma texture fini, volti piccoli e sfondi complessi si degradano prima rispetto al percorso di qualità. Usalo nel tuo ciclo iterativo mentre testi le varianti del prompt; quando renderizzi l'inquadratura finale, valuta se il percorso di qualità sia un ultimo passo migliore. Il preset è un campo della richiesta, quindi è una decisione per singolo job, non un'impostazione globale a livello di account.

Durata flessibile

La durata è flessibile entro l'intervallo supportato dal modello, non fissa a una singola lunghezza. Una durata più lunga significa generare più frame, quindi tempo di completamento più lungo e costo più alto — la fatturazione è per secondi di output. Scegli la durata più breve che soddisfa l'inquadratura. Un loop di cinque secondi per un post sui social non ha bisogno della stessa lunghezza di un beat narrativo.

Disciplina sui campi

Imposta solo i campi di cui hai bisogno. Chiavi sconosciute o scritte male sono una fonte comune di errori di configurazione silenziosi, quindi mantieni il corpo JSON piccolo, esplicito e sotto controllo di versione insieme al resto della configurazione della pipeline.

Inviare la richiesta con curl

Ogni chiamata a HiAPI usa lo stesso schema di autenticazione: un bearer token nell'header Authorization. Metti la chiave in una variabile d'ambiente, così non finisce nella cronologia della shell o in script committati.

export HIAPI_API_KEY="your_api_key_here"

Poi invia il job. I nomi esatti dei campi e il percorso dell'endpoint vanno presi dal riferimento del modello; la forma qui sotto è quella canonica:

curl -X POST "https://api.hiapi.ai/v1/video/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-2.5-turbo/text-to-video",
    "prompt": "A slow dolly-in on a ceramic coffee cup on a wooden table, morning light raking across the surface, steam rising, shallow depth of field, cinematic",
    "duration": 5,
    "fast": true
  }'

Quello che dovresti aspettarti di ricevere non è un video. È una conferma contenente l'identificatore del job e il suo stato iniziale — di solito lo stato queued o processing, più un campo id. Salva quell'ID; è l'handle per tutte le operazioni successive.

La risposta minima è più o meno così:

{
  "id": "job_abc123",
  "status": "queued",
  "model": "kling-2.5-turbo/text-to-video"
}

La chiamata di invio dovrebbe tornare rapidamente — ben sotto un secondo in condizioni normali. Se si blocca, il problema è nella connettività o nell'autenticazione, non nel modello. Se restituisce 401, controlla il formato dell'header (il prefisso Bearer è importante). Se restituisce 422, il tuo corpo JSON è malformato o manca di campi obbligatori.

Non aggiungere -L, retry o timeout lunghi a questa chiamata. Il passo di invio o riesce rapidamente o fallisce rapidamente. Tutta l'attesa avviene nel loop di polling, che è l'argomento successivo.

La stessa richiesta in Python

La versione Python è un sottile wrapper sullo stesso contratto HTTP. Usa requests con una Session condivisa, così il connection pooling vale tra l'invio e ogni polling. Avvolgilo in funzioni, così il resto del tuo codice non tocca mai HTTP grezzo.

import os
import time
import requests

BASE = "https://api.hiapi.ai/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
    "Content-Type": "application/json",
}

session = requests.Session()

def submit_video(prompt: str, duration: int = 5, fast: bool = True) -> str:
    body = {
        "model": "kling-2.5-turbo/text-to-video",
        "prompt": prompt,
        "duration": duration,
        "fast": fast,
    }
    resp = session.post(f"{BASE}/video/generations", json=body, headers=HEADERS, timeout=15)
    resp.raise_for_status()
    return resp.json()["id"]

def poll_video(job_id: str, timeout_s: int = 600, interval_s: float = 3.0) -> dict:
    deadline = time.monotonic() + timeout_s
    delay = interval_s
    while time.monotonic() < deadline:
        resp = session.get(f"{BASE}/video/generations/{job_id}", headers=HEADERS, timeout=15)
        resp.raise_for_status()
        data = resp.json()
        status = data.get("status")
        if status in ("succeeded", "failed", "cancelled"):
            return data
        time.sleep(delay)
        delay = min(delay * 1.5, 15.0)
    raise TimeoutError(f"job {job_id} did not finish in {timeout_s}s")

if __name__ == "__main__":
    job = submit_video("A slow dolly-in on a ceramic coffee cup, morning light, steam rising, cinematic")
    result = poll_video(job)
    print(result)

Alcuni dettagli meritano di essere mantenuti anziché eliminati: il timeout su ogni richiesta, così un socket bloccato non blocca il tuo worker; il backoff esponenziale con un limite ragionevole; e un TimeoutError separato, così il chiamante può distinguere "ancora in esecuzione" da "rotto".

Se preferisci httpx, la conversione è diretta — stessi metodi, URL e corpi JSON. Il livello di trasporto non è la parte interessante; il contratto lo è. Prima di iniziare il polling, salva job_id in un posto persistente, così un riavvio non orfana una generazione in corso.

Polling del job e lettura della risposta

Il loop di polling è dove si annida la maggior parte dei bug di integrazione. Tre regole lo mantengono affidabile.

Regola 1: solo gli stati terminali chiudono il loop

Vedrai stati transitori — queued, processing — e stati terminali come succeeded, failed e cancelled. Solo uno stato terminale fa uscire dal loop. Non trattare stringhe di stato sconosciute come successo, e non interrompere su processing. Registra lo stato a ogni iterazione; quando qualcosa va storto alle due di notte, quel log è la tua unica prova.

Regola 2: fai backoff, non girare a vuoto

Per un job che richiede un minuto, un polling fisso ogni secondo è uno spreco; e quando esegui job in batch, un polling aggressivo può raggiungere i limiti di rate. Inizia da circa due o tre secondi, moltiplica per circa 1,5 a ogni giro, con un tetto di dieci o quindici secondi. Le richieste totali per un job di un minuto scendono da sessanta a meno di quindici, mentre la latenza di rilevamento nel caso peggiore resta solo il valore del tetto.

Regola 3: separa asset e metadati

Il payload della risposta completata contiene entrambi. Il video stesso viene consegnato come URL (e di solito con una scadenza), mentre tutto il resto — ID del job, modello, durata, stato, tempo trascorso — sono metadati su come lo hai ottenuto. Leggi l'URL, scaricalo subito e archivialo tu stesso. Gli URL degli asset generati non sono CDN permanenti; trattali come una consegna, non come una casa. Persisti l'ID del job insieme alla tua copia, così puoi risalire da qualsiasi clip alla richiesta esatta che l'ha prodotta.

Una nota su failed

Lo stato failed è un risultato a livello di job, non un errore di trasporto. La chiamata HTTP ha avuto successo; la generazione no. Leggi il payload di errore — potrebbe indicare un rifiuto per politica sui contenuti, una combinazione di parametri non supportata o un guasto interno. Riprovare un rifiuto per politica così com'è fallirà solo di nuovo, quindi ramifica sul motivo prima di considerare un retry.

Gestire errori, timeout e retry

Distingui due mondi di errore e gestiscili separatamente.

Gli errori a livello di trasporto sono fallimenti HTTP: reset di connessione, risposte 5xx, rate limit 429 e timeout del client. Questi non dicono se il job è stato eseguito. Riprova con backoff esponenziale e jitter, limitando il numero di tentativi.

Gli errori a livello di job sono stati terminali all'interno di una risposta HTTP riuscita. Il job è stato eseguito e ha prodotto un risultato definito. Riprovare il polling non aiuta; se vuoi riprovare, è un nuovo invio, e solo se la causa del fallimento era temporanea.

Riprova la cosa giusta

Questa è la parte sottile. Se la tua chiamata di invio va in timeout, non sai se il server ha accettato il job. Un nuovo invio cieco può produrre due generazioni e due addebiti. Un pattern più sicuro è rendere idempotente l'invio con una chiave di richiesta generata dal client, che invii come header o campo del corpo, così invii duplicati restituiscono il job originale invece di avviarne uno nuovo. Se la superficie API che usi non lo offre, allora in caso di timeout dell'invio, registra l'hash del prompt e la durata, e controlla i tuoi job recenti prima di inviare di nuovo.

Timeout a ogni livello

Imposta tre timeout distinti, senza confonderli:

  • Timeout per richiesta — breve, ad esempio da dieci a quindici secondi. Limita la singola chiamata HTTP, non il job.
  • Scadenza complessiva del job — il budget in tempo reale per l'intera generazione. Se viene superato, segna il job come orfano, emetti un avviso e prosegui.
  • Timeout lato client — se un utente è in attesa, decidi se fare streaming dell'avanzamento o restituire al frontend l'handle del job.

Strategia di retry pratica

Riprova 429 e 5xx con backoff, con un tetto piccolo. Non riprovare mai 400, 401, 403 o 422 — quelli sono bug nella tua richiesta, e ripeterli brucia solo quota. Registra il corpo della risposta di ogni fallimento; i payload di errore di HiAPI di solito indicano il campo problematico.

Sicurezza nei batch

Quando distribuisci molti job, aggiungi un limite di concorrenza e ritardi di avvio con jitter. Cento invii simultanei sono un incidente da rate limit che ti sei procurato da solo. Un pool di cinque-dieci worker, ciascuno che fa polling in modo indipendente, è molto più stabile e più facile da osservare.

Checklist di produzione prima del rilascio

Prima che questo esca dal tuo portatile, fissa queste decisioni.

  • Timeout e scadenze. Ogni chiamata ha un timeout per richiesta, c'è una scadenza complessiva del job, e c'è una politica esplicita su cosa succede quando un job diventa orfano. Scrivila come costanti, non come numeri magici.
  • Persistenza degli ID. Salva job_id e hash del prompt prima che inizi il polling. Questa è la chiave che rende possibili riavvii e audit.
  • Archiviazione degli asset. Al successo, scarica il video completato nel tuo bucket di archiviazione. Non inviare mai al frontend o al database un URL che non controlli come riferimento permanente.
  • Logging. Registra ogni transizione di stato con ID del job, modello, durata, preset e tempo trascorso. Quando emergono problemi di costo o qualità, questo è il dataset per rispondere.
  • Consapevolezza dei costi. La fatturazione è per secondi di output, quindi la durata è la tua leva principale sui costi. Il preset turbo mantiene bassa la latenza (e quindi l'occupazione dei worker). Tieni traccia dei secondi generati per feature, così la discussione sui costi si basa su numeri reali e non su supposizioni.
  • Idempotenza. Usa una chiave di richiesta generata dal client all'invio e definisci regole su cosa costituisce un nuovo invio sicuro.
  • UX dei fallimenti. Decidi ora cosa vede l'utente in caso di fallimento a livello di job: pulsante di retry, prompt di fallback o semplice messaggio testuale. Girare a vuoto in silenzio è la scelta peggiore.
  • Controllo di versione dei prompt. Tieni i prompt in configurazione, non inline nei handler, così puoi confrontare gli output di varianti diverse senza rideployare.

L'endpoint in sé è piccolo — un invio, un polling. Quasi tutto lo sforzo ingegneristico sta nel ciclo di vita attorno ad esso, e è lì che si decide la qualità di produzione. Parti dal riferimento del modello di kling-2.5-turbo/text-to-video su HiAPI, poi costruisci attorno ad esso l'impalcatura descritta qui.

Inizia a creare con artefatti IA persistenti

Ottieni la tua chiave API e chiama modelli di immagini, video e audio tramite un'unica API basata sui task.

Leggi la documentazione API