HiAPI
Blog

Tutoriale

API Kling 3.0 Turbo image-to-video in Python: schema, script completo e gestione degli errori

Riferimento specifico per questa versione: schema Turbo a immagine singola, limite da 3 a 15 secondi, livelli 720p/1080p e modalità di errore.

Jul 11, 2026
API Kling 3.0 Turbo image-to-video in Python: schema, script completo e gestione degli errori

Lo schema di kling-3.0-turbo/image-to-video è compatto e rigoroso: un URL pubblico dell'immagine, un prompt di movimento obbligatorio, una durata intera da 3 a 15 secondi e un output a 720p o 1080p. Questa pagina è il riferimento specifico per questa versione, utile a validare il corpo della richiesta e a distinguere gli errori HTTP 400 dai risultati asincroni TASK_FAILED.

Per il flusso generico di creazione, polling, callback e download, consulta la guida al task runner Python di Kling e alla scelta tra Omni e Turbo.

Schema di input di Turbo

Campo Tipo Obbligatorio Valori accettati
prompt string Sì Descrive il movimento e il comportamento della camera
image_urls array di stringhe Sì Esattamente un URL immagine accessibile pubblicamente
duration integer No Da 3 a 15 secondi
resolution string No 720p o 1080p

Turbo non accetta sound, aspect_ratio, negative_prompt, seed, mode, né un secondo URL immagine. Lo schema rigoroso rifiuta le proprietà extra invece di ignorarle silenziosamente.

L'immagine di input determina la forma del fotogramma. Prima di creare il task, caricala su un bucket pubblico o una CDN; il renderer non riesce a recuperare localhost, dashboard private o URL firmati scaduti.

Richiesta minima funzionante

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-3.0-turbo/image-to-video",
    "input": {
      "prompt": "The runner accelerates as the camera tracks from the side",
      "image_urls": ["https://cdn.example.com/first-frame.jpg"],
      "duration": 6,
      "resolution": "1080p"
    }
  }'

Una risposta riuscita contiene data.taskId. HTTP 200 indica solo che la creazione è riuscita, non che il task è completato; il rendering del video avviene ancora in modo asincrono.

Pre-validazione in Python

Valida i vincoli prima della chiamata di rete, così gli errori evidenti non creano mai un task:

from urllib.parse import urlparse

import requests


def turbo_input(prompt: str, image_url: str, duration: int, resolution: str) -> dict:
    if not prompt.strip():
        raise ValueError("prompt is required")
    if type(duration) is not int or not 3 <= duration <= 15:
        raise ValueError("duration must be an integer from 3 to 15")
    if resolution not in {"720p", "1080p"}:
        raise ValueError("resolution must be 720p or 1080p")
    parsed = urlparse(image_url)
    if parsed.scheme not in {"http", "https"} or not parsed.netloc:
        raise ValueError("image_url must be a public HTTP(S) URL")

    return {
        "prompt": prompt,
        "image_urls": [image_url],
        "duration": duration,
        "resolution": resolution,
    }


payload = {
    "model": "kling-3.0-turbo/image-to-video",
    "input": turbo_input(
        prompt="The runner accelerates as the camera tracks from the side",
        image_url="https://cdn.example.com/first-frame.jpg",
        duration=6,
        resolution="1080p",
    ),
}

response = requests.post(
    "https://api.hiapi.ai/v1/tasks",
    headers={"Authorization": "Bearer sk-your-key"},
    json=payload,
    timeout=30,
)
response.raise_for_status()
task_id = response.json()["data"]["taskId"]
print(task_id)

Questo controllo locale individua i problemi nella forma dei valori, ma non può dimostrare che l'immagine remota sia scaricabile pubblicamente. Il renderer esegue quel recupero dopo la creazione del task.

Script Python completo: invio, polling, download

Lo snippet precedente si ferma all'ID del task. Questa versione esegue il job completo e salva l'MP4. Invia l'header Idempotency-Key, quindi ritentare lo stesso invio dopo un timeout restituisce il task originale invece di crearne e addebitarne un secondo:

import os
import time
import uuid

import requests

API = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}


def run_turbo(prompt: str, image_url: str, duration: int = 5,
              resolution: str = "720p", out_path: str = "turbo.mp4") -> str:
    body = {
        "model": "kling-3.0-turbo/image-to-video",
        "input": turbo_input(prompt, image_url, duration, resolution),
    }
    key = str(uuid.uuid4())  # reuse this key if you retry the same submission
    r = requests.post(API, json=body, headers={**HEADERS, "Idempotency-Key": key}, timeout=30)
    if r.status_code == 400:
        raise ValueError(f"schema error, no task created: {r.text}")
    r.raise_for_status()
    task_id = r.json()["data"]["taskId"]

    deadline = time.time() + 900
    while time.time() < deadline:
        data = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
        if data["status"] == "success":
            video = requests.get(data["output"][0]["url"], timeout=120)
            video.raise_for_status()
            with open(out_path, "wb") as f:
                f.write(video.content)  # the output URL is temporary, so save it now
            return out_path
        if data["status"] == "fail":
            raise RuntimeError(f"TASK_FAILED {task_id}: {data.get('error')}")
        time.sleep(10)
    raise TimeoutError(task_id)


print(run_turbo(
    "The runner accelerates as the camera tracks from the side",
    "https://cdn.example.com/first-frame.jpg",
))

Un clip di 5 secondi a 720p costa $0.65. In produzione, sostituisci il ciclo di polling con un callback di livello superiore "callback": {"url": "https://your-app.example.com/hiapi/callback"} e deduplica le notifiche per ID del task.

HTTP 400: il task non è mai stato creato

Una risposta HTTP 400 è il risultato della validazione sincrona dello schema. Le cause tipiche includono:

Input non valido Perché fallisce Come correggere
"duration": "5" È stata inviata una stringa invece di un intero Invia 5
"duration": 20 Il massimo è 15 Scegli un valore tra 3 e 15
Due image_urls Turbo ne accetta solo una Mantieni solo il fotogramma iniziale
"resolution": "4K" Turbo supporta 720p e 1080p Usa 720p o 1080p, oppure scegli Omni
"sound": true sound non è nello schema di Turbo Rimuovi il campo o scegli Omni
prompt mancante Turbo richiede un prompt Aggiungi un prompt di movimento non vuoto

Poiché la validazione fallisce prima della creazione, non c'è alcun ID di task da interrogare. Registra il corpo della risposta e l'ID della richiesta, correggi il corpo e invia una nuova richiesta.

TASK_FAILED: creazione riuscita, ma rendering fallito

Se POST /v1/tasks restituisce HTTP 200 con un ID di task, i fallimenti successivi appartengono al ciclo di vita asincrono del task e vanno trattati diversamente dai 400.

Le cause comuni includono:

  • l'URL dell'immagine richiede Cookie o header di autorizzazione;
  • l'URL firmato dell'immagine è scaduto prima che il renderer lo recuperasse;
  • l'host blocca il recupero lato server o reindirizza a una pagina HTML;
  • il file è corrotto o il suo tipo MIME non corrisponde al contenuto;
  • il provider non riesce a completare quel rendering.

Registra l'ID del task, il codice e il messaggio di errore finali, l'URL di input originale e l'ora della richiesta. Prima di riprovare, verifica che un server non autenticato possa recuperare l'immagine con una risposta 2xx e un content type di immagine. Riprovare ciecamente lo stesso URL inaccessibile crea solo un altro task fallito.

La guida Python generica contiene il ciclo condiviso di polling dello stato finale e il codice di download dell'output; tenerlo lì evita di duplicare la logica del ciclo di vita in questa pagina di riferimento specifica della versione.

Prezzi di Turbo e scelta del modello

Le tariffe di produzione attuali sono:

Livello Turbo Prezzo al secondo Task da 5 secondi
720p $0.130 $0.65
1080p $0.160 $0.80

Prima di un uso su larga scala, consulta la pagina dei prezzi aggiornata. Il nome Turbo descrive una variante del modello e non garantisce che sia più economico a ogni risoluzione, né che i task rispettino un SLA fisso sui tempi di rendering.

Quando ti servono fotogramma finale, audio o 4K, scegli Kling 3.0 standard (kling-3.0/image-to-video): accetta una o due immagini (fotogramma iniziale e finale), ha un interruttore sound e costa $0.10/s a 720p senza audio e $0.129/s a 1080p senza audio. Quando ti servono immagini o video di riferimento, scegli Omni. Per un singolo fotogramma di input a 720p o 1080p, confronta queste varianti con i tuoi prompt di movimento e valuta qualità dell'output, tempi di coda e costo totale.

Domande frequenti

Quante immagini accetta Kling 3.0 Turbo image-to-video?

Esattamente un URL immagine pubblico. Una seconda immagine genera un errore di schema (image_urls: maxItems: got 2, want 1); per il controllo del primo e dell'ultimo fotogramma, usa Kling 3.0 image-to-video standard.

Quali valori di durata sono validi?

Invia un intero da 3 a 15. I numeri tra virgolette come "5" sono stringhe e falliscono la validazione.

Turbo supporta 4K o l'audio?

Niente 4K: questo endpoint accetta 720p o 1080p. Non esiste un campo sound, ma i clip Turbo includono l'audio e non è possibile disattivarlo. Quando ti serve 4K o un output senza audio, usa Kling 3.0 standard o Omni.

Qual è la differenza tra HTTP 400 e TASK_FAILED?

HTTP 400 significa che la richiesta viola lo schema, quindi non è stato creato alcun task. TASK_FAILED si verifica dopo una risposta di creazione valida, durante il recupero dell'input o la generazione.

Perché un URL immagine apparentemente pubblico causa TASK_FAILED?

L'URL potrebbe dipendere da Cookie, avere una firma scaduta, bloccare il recupero lato server o restituire HTML invece dei byte dell'immagine. Prima di riprovare, testalo senza l'autenticazione del browser.

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