HiAPI
Blog

Tutoriale

Tutorial su kandinsky-6.0-pro/image-to-video tramite HiAPI: curl + Python

Avvia una richiesta funzionante di image-to-video su HiAPI: dal caricamento del primo fotogramma al polling asincrono fino al download finale

Nov 3, 2026
深色底上青绿与石板灰的扁平液态色块相互交叠,构成 kandinsky-6.0-pro 视频教程的封面图。

Panoramica del flusso image-to-video su HiAPI

Ogni chiamata image-to-video su HiAPI segue lo stesso ciclo di vita in tre fasi. Conoscerlo in anticipo farà sembrare il resto del tutorial una procedura passo-passo anziché un mistero.

Fase 1: invio del task

Invii una richiesta POST all'endpoint kandinsky-6.0-pro/image-to-video, allegando l'immagine del primo fotogramma e un breve prompt che descrive il movimento desiderato. La risposta non restituisce un flusso di byte video, ma accetta il task e restituisce un identificatore di task: tutte le operazioni successive si basano su questo handle.

Fase 2: polling dello stato

La generazione video richiede tempo, quindi l'endpoint è asincrono. Con l'identificatore di task chiami la rotta di stato, che riporta lo stato corrente del task: in coda, in elaborazione, completato o fallito. Ripeti il controllo a brevi intervalli finché lo stato non raggiunge uno stato terminale.

Fase 3: recupero dell'output

Una volta che il task risulta completato, il payload di stato contiene la posizione del video finale. Lo scarichi e lo scrivi su disco. Questo è l'intero contratto.

Perché questa forma è importante

La separazione tra invio e polling non è casuale. Significa che il tuo client HTTP non deve mantenere aperto il socket per tutta la durata del rendering, e che puoi persistere l'identificatore di task, allontanarti e riprendere dopo. In caso di errore, il campo di stato ti dice dove è fallito, il che è molto più utile di un timeout opaco.

Ricorda le tre fasi: invio, polling, download. Gli esempi curl e Python che seguono sono solo due modi di scrivere la stessa sequenza.

Preparare il primo fotogramma e le credenziali API

Prima della prima chiamata di solito si verificano problemi solo in due punti: la chiave e l'immagine. Sistema entrambi subito e il resto del tutorial scorrerà senza intoppi.

Impostare la chiave API come variabile d'ambiente

Non incollare la chiave nei file di codice. Esportala nella shell, così curl e Python possono leggerla senza codificare nulla a mano:

export HIAPI_API_KEY="your_api_key_here"

In Windows PowerShell l'equivalente è $env:HIAPI_API_KEY="your_api_key_here". Prima di procedere, verifica che la shell la legga:

echo "$HIAPI_API_KEY" | head -c 4; echo

Dovresti vedere i primi caratteri della chiave. Se non vedi nulla, la variabile non è stata resa persistente nella sessione shell corrente: è una causa comune delle successive risposte 401.

Scegliere un'immagine del primo fotogramma valida

Il primo fotogramma determina soggetto, composizione e proporzioni dell'intero video. Alcuni vincoli pratici evitano la maggior parte dei rifiuti:

  • Formato: usa formati immagine Web standard come JPEG o PNG. Evita codec poco diffusi, casi limite progressivi o profili colore CMYK.
  • Accessibilità: l'API deve leggere davvero quei byte. Se passi un URL, assicurati che sia pubblicamente accessibile o correttamente autenticato; se passi dati inline, assicurati che la codifica sia completa.
  • Dimensioni: le immagini di dimensioni ragionevoli si validano più rapidamente. I file enormi rallentano la richiesta e sono spesso all'origine di errori di caricamento.
  • Contenuto: scegli un fotogramma plausibile come punto di partenza del movimento: soggetto nitido, sfondo semplice. Il prompt descrive come allontanarsi da questo fotogramma, quindi un fotogramma confuso produce un video confuso.

Decidere come fare riferimento all'immagine

Il corpo della richiesta consente di puntare al primo fotogramma tramite URL o dati codificati inline. Scegli in base a dove si trova l'immagine:

  • Se il file è ospitato ed è leggibile pubblicamente, l'URL è l'opzione più concisa.
  • Se l'immagine è locale o privata, la codifica inline rende l'intera richiesta autosufficiente, al costo di un payload più grande.

In entrambi i casi, mantieni la stessa forma di variabile per il riferimento all'immagine in curl e Python, così i due esempi restano direttamente confrontabili.

Inviare la richiesta con curl

Questa è una richiesta di invio completa. Sostituisci il riferimento all'immagine e il prompt con i tuoi ed eseguila.

curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "https://your-host.example/first-frame.jpg",
    "prompt": "slow dolly-in on the subject, gentle ambient motion, stable camera",
    "duration": 5,
    "aspect_ratio": "16:9"
  }'

Il ruolo di ciascuna parte

  • URL punta specificamente al modello kandinsky-6.0-pro/image-to-video. La scelta del modello è nel percorso, non nel corpo della richiesta, quindi un errore di battitura qui produce un 404 anziché un messaggio di validazione cortese.
  • Authorization trasporta il token bearer dalla variabile d'ambiente esportata. Nient'altro autentica la chiamata.
  • Content-Type: application/json è importante per qualsiasi POST con corpo JSON; se lo ometti, alcuni proxy possono alterare il payload prima che raggiunga l'API.
  • image è il riferimento al primo fotogramma: qui in forma di URL, oppure come stringa codificata inline se l'immagine è privata.
  • prompt descrive il movimento. Mantienilo focalizzato sul movimento e sul comportamento della camera, invece di ripetere ciò che l'immagine già contiene.
  • duration e aspect_ratio modellano l'output. Le proporzioni devono corrispondere al primo fotogramma; una mancata corrispondenza comporta ritaglio o bande nere. La fatturazione è misurata sull'output generato, quindi queste impostazioni determinano anche il costo.

Leggere la risposta

Un invio riuscito restituisce il payload del task, non il video. Estrai l'identificatore di task: lo passerai all'endpoint di stato più avanti:

curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @body.json | jq -r '.id'

Usare un file body.json al posto del -d inline mantiene leggibili prompt lunghi e immagini codificate. jq è opzionale, ma trasforma la risposta in una riga pronta da incollare nella chiamata successiva.

Chiamare lo stesso endpoint con Python

La versione Python è la stessa richiesta, lo stesso corpo, solo racchiusa in una funzione per il riutilizzo. Mantieni il corpo identico a quello della versione curl: è proprio questo il senso di mostrare entrambe.

import os
import json
import requests

API_BASE = "https://api.hiapi.ai/v1"
ENDPOINT = f"{API_BASE}/kandinsky-6.0-pro/image-to-video"

def submit_video_job(image_ref: str, prompt: str, duration: int = 5, aspect_ratio: str = "16:9") -> str:
    """Submit a first-frame image-to-video job and return the job id."""
    api_key = os.environ.get("HIAPI_API_KEY")
    if not api_key:
        raise RuntimeError("HIAPI_API_KEY is not set in this environment")

    body = {
        "image": image_ref,
        "prompt": prompt,
        "duration": duration,
        "aspect_ratio": aspect_ratio,
    }

    response = requests.post(
        ENDPOINT,
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json=body,
        timeout=60,
    )

    if response.status_code >= 400:
        raise RuntimeError(f"submit failed: {response.status_code} {response.text}")

    payload = response.json()
    return payload["id"]

if __name__ == "__main__":
    job_id = submit_video_job(
        image_ref="https://your-host.example/first-frame.jpg",
        prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
    )
    print(json.dumps({"job_id": job_id}, indent=2))

Note sulla versione Python

  • Fallimento rapido se manca la chiave. Il controllo esplicito dell'ambiente trasforma l'errore più comune in un chiaro errore locale, anziché in un 401 remoto.
  • json=body rispetto a data=json.dumps(body). Passare json= fa impostare il content type a requests, mantenendo gli header minimali. Se usi data=, imposta esplicitamente Content-Type.
  • Timeout generoso. L'invio video comporta talvolta il trasferimento di payload di immagini grandi. Timeout troppo brevi producono falsi fallimenti.
  • Leggere il corpo della risposta in caso di errore. Sollevare insieme codice di stato e corpo della risposta significa che il messaggio di errore ti dice effettivamente cosa contesta l'API.

Se il primo fotogramma è un file locale, leggilo, codificalo in base64 e sostituisci image_ref all'interno di submit_video_job con quella stringa. La firma della funzione non cambia: è proprio questo il motivo per cui i due stili di chiamata condividono la stessa definizione del corpo della richiesta.

Polling del task e download del video

Un task inviato non è il video finale. Esegui il polling finché il task non raggiunge uno stato terminale, poi scarica.

Ciclo di polling

import time
import requests

def wait_for_video(job_id: str, interval: float = 10.0, max_wait: float = 600.0) -> str:
    """Poll the job until it finishes; return the output URL."""
    import os
    api_key = os.environ["HIAPI_API_KEY"]
    url = f"https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video/{job_id}"
    headers = {"Authorization": f"Bearer {api_key}"}

    deadline = time.time() + max_wait
    while time.time() < deadline:
        response = requests.get(url, headers=headers, timeout=30)
        response.raise_for_status()
        payload = response.json()
        status = payload.get("status")

        if status == "succeeded":
            return payload["output"]
        if status == "failed":
            raise RuntimeError(f"job failed: {payload.get('error', 'unknown error')}")

        time.sleep(interval)

    raise TimeoutError(f"job {job_id} did not finish within {max_wait}s")

Tre dettagli fanno funzionare bene questo ciclo:

  • Attesa a intervalli, non affidamento alla fortuna. Un'attesa fissa di circa dieci secondi è un buon punto di partenza; non martellare l'endpoint in un ciclo serrato.
  • Gestire ogni stato terminale. succeeded ti dà l'output, failed ti dà il messaggio di errore. Entrambi vanno trattati come uscita. Un ciclo che controlla solo il successo continuerebbe a girare fino alla scadenza su un task morto.
  • Limitare il tempo di attesa. max_wait garantisce che lo script termini, anziché girare all'infinito dietro un task bloccato.

Scaricare il video finale

Ottenuto l'URL di output, scrivilo su disco in streaming anziché caricare l'intero file in memoria:

def download_video(output_url: str, path: str = "result.mp4") -> str:
    with requests.get(output_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        with open(path, "wb") as handle:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    handle.write(chunk)
    return path

Combinando le parti:

job_id = submit_video_job(
    image_ref="https://your-host.example/first-frame.jpg",
    prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
)
output_url = wait_for_video(job_id)
saved = download_video(output_url, "kandinsky_result.mp4")
print(f"saved to {saved}")

In produzione, persisti job_id nel momento stesso in cui l'invio riesce. Se il processo si riavvia, puoi rientrare nel ciclo di polling con l'identificatore salvato, senza pagare per un nuovo invio.

Risolvere gli errori comuni di richiesta e task

La maggior parte dei fallimenti rientra in tre categorie: chiave, immagine o stato del task. Isola la categoria prima di modificare qualsiasi altra cosa.

Chiave rifiutata

Sintomo: errore di autenticazione o autorizzazione prima della creazione di qualsiasi task.

  • Verifica che la variabile sia effettivamente esportata nella shell corrente: echo "$HIAPI_API_KEY".
  • Controlla se hai incollato spazi o newline insieme alla chiave; rimuovili.
  • Verifica che l'header sia scritto Authorization e che il valore inizi con Bearer seguito da uno spazio.
  • Se curl funziona ma Python no, stampa os.environ.get("HIAPI_API_KEY") dallo stesso interprete: la variabile può esistere nella tua shell ma non nell'ambiente ereditato dallo script.

Immagine rifiutata

Sintomo: errore di validazione all'invio, oppure task fallito immediatamente.

  • Formato errato o poco diffuso. Riesporta in JPEG o PNG standard e riprova. I profili CMYK e i codec esotici sono i colpevoli più comuni.
  • URL irraggiungibile. Apri l'URL dell'immagine in una finestra di navigazione in incognito; se non ottieni i byte, nemmeno l'API li otterrà.
  • Codifica inline corrotta. Se hai codificato in base64 localmente, decodifica una volta la stringa e verifica che sia un'immagine valida prima di inviarla.
  • Proporzioni non corrispondenti. Se il video torna ritagliato o con bande nere, allinea aspect_ratio al primo fotogramma, anziché combattere con l'output a posteriori.

Il task non termina o fallisce

Sintomo: lo stato resta su queued/processing, oppure riporta failed.

  • Leggi il campo error. I task falliti trasportano un messaggio. Di solito indica il campo o la condizione che ha causato il problema. Non indovinare: registra l'intero payload di stato.
  • Rispetta il design asincrono. Attendere qualche secondo prima di controllare è normale. Un ciclo di retry serrato che si arrende dopo due secondi non è un meccanismo di stato.
  • Limita il tempo di attesa. Se il task supera un limite ragionevole, trattalo come fallito, esponi l'id del task e inviane uno nuovo, anziché eseguire il polling per sempre.
  • Confronta con una chiamata funzionante nota. Se la tua immagine personalizzata fallisce, esegui il curl esatto dell'inizio di questo tutorial con una piccola immagine pubblica e un prompt breve. Se funziona, il problema è nel tuo input; se fallisce anche, il problema è nelle credenziali o nella forma della richiesta.

Errore di download dopo il successo

Se il task riporta succeeded ma il download fallisce, l'URL di output potrebbe essere scaduto o soggetto a controllo degli accessi. Esegui di nuovo il polling del task per ottenere una nuova posizione di output, anziché riprovare con quella scaduta.

Affronta le categorie in ordine: chiave, poi immagine, poi stato del task. Ogni errore restringe rapidamente la causa a un solo motivo. Questo è l'intero ciclo: invia il primo fotogramma, esegui il polling fino al completamento, scarica il risultato.

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