HiAPI
Blog

Tutoriel

Utiliser Kandinsky 6.0 Pro texte-vers-vidéo sur HiAPI : tutoriel curl et Python

Démonstration pratique axée sur la requête : construire l'appel du prompt au clip vidéo, soumettre la requête, interroger l'état d'achèvement et télécharger le résultat

Nov 3, 2026
米色纸层与石墨色顶边、一块陶土色纸片层叠成阶梯状的封面图,呈现平静的地层节奏。

Ce que fait la requête kandinsky-6.0-pro/text-to-video

kandinsky-6.0-pro/text-to-video convertit un prompt textuel en un court clip vidéo. Vous envoyez un prompt et quelques paramètres de génération, et le modèle produit un fichier vidéo que vous pouvez enregistrer et lire. C'est tout le produit : un prompt en entrée, un clip en sortie.

Le détail architectural essentiel est le suivant : il ne s'agit pas d'un appel synchrone. Vous n'obtenez pas la vidéo directement dans le corps de la réponse à la première requête. À la place, vous créez une tâche, l'API renvoie l'identifiant de cette tâche, puis le modèle travaille en arrière-plan. Votre code doit vérifier l'état de la tâche jusqu'à ce qu'elle signale son achèvement, moment où le résultat devient téléchargeable.

Ce mode de fonctionnement a plusieurs conséquences autour desquelles vous devez concevoir dès le départ :

  • Le client doit interroger l'état. Un seul POST ne peut pas renvoyer la vidéo terminée, donc toute intégration nécessite une boucle d'interrogation d'état ou une revérification de type webhook.
  • La requête doit être idempotente de votre côté. Si le script plante après la soumission, vous ne voulez pas créer silencieusement une seconde tâche. Capturez l'identifiant de la tâche et persistez-le.
  • La latence est variable. La génération vidéo est plus lente que les appels d'image ou de texte, donc l'attente est normale, pas un défaut.

Le reste de ce tutoriel suit ce cycle de vie : préparation, soumission avec curl, interrogation, téléchargement, puis reconstruction du même flux en Python. Considérez le code comme un squelette fonctionnel — le chemin de l'endpoint et les noms de champs doivent toujours être confirmés par rapport à la référence API du modèle, car ces détails évoluent avec la plateforme.

Avant d'envoyer la première requête

Quatre choses doivent être prêtes avant le premier appel.

1. Un compte HiAPI et une clé API

L'authentification se fait avec une clé API émise depuis votre compte HiAPI. Gardez la clé hors du contrôle de version et de l'historique du shell dans la mesure du possible. La pratique courante consiste à l'exporter comme variable d'environnement et à laisser le code la lire depuis là :

export HIAPI_API_KEY="your-key-here"

Chaque requête ci-dessous suppose que la clé est envoyée comme bearer token dans l'en-tête Authorization. Si vous n'avez pas encore créé de clé, faites-le d'abord dans le tableau de bord de votre compte.

2. Un client HTTP

curl suffit pour vérifier qu'une requête fonctionne. Pour tout ce qui doit être répété, utilisez Python 3 et la bibliothèque requests — une seule dépendance, un code lisible, et facile à intégrer plus tard dans un planificateur ou un service :

python3 -m pip install requests

3. Un emplacement pour les sorties

Les fichiers vidéo sont bien plus volumineux que les réponses JSON. Décidez à l'avance si vous écrivez dans un répertoire local ou si vous diffusez vers un stockage objet. Dans ce tutoriel, un répertoire local ./output suffit :

mkdir -p output

4. Connaître votre prompt

Rédigez le prompt avant le code. Un prompt précis et descriptif — sujet, action, comportement de la caméra, style visuel — vous donne une base de comparaison en cas de problème. Quand le prompt est une constante nommée dans le script, plutôt qu'une chaîne tapée dans l'invite du shell, il est bien plus facile de ne changer qu'une variable à la fois.

Voilà la liste complète des prérequis. Aucun SDK à installer, aucune étape de build ; la plateforme est accessible via HTTPS standard.

La requête curl qui fonctionne

Le premier objectif est d'obtenir une commande qui renvoie une tâche (pas une vidéo). Faites-la fonctionner avant d'ajouter du code.

La requête comporte trois parties : l'endpoint du modèle, l'en-tête Authorization, et un corps JSON contenant le prompt et les paramètres de génération.

curl -X POST "https://api.hiapi.ai/v1/models/kandinsky-6.0-pro/text-to-video/jobs" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A slow drone shot over a misty pine forest at sunrise, soft golden light, cinematic",
    "duration_seconds": 5,
    "aspect_ratio": "16:9"
  }'

Lisez attentivement la réponse. Vous devez y chercher :

  • Un identifiant de tâche — le handle que vous utiliserez pour interroger. Il peut s'appeler id, job_id ou un nom similaire.
  • Un champ d'état initial, généralement quelque chose comme queued ou processing.
  • Tous les paramètres renvoyés, qui servent à confirmer que le corps de la requête a été interprété comme prévu.

Une réponse renvoyant un identifiant de tâche et un état non-erreur signifie que la requête a été acceptée. Si cette réponse contenait directement un fichier vidéo, cela signifierait qu'il se passe autre chose que ce qui est décrit dans cet article.

Confirmer le contrat avant de construire dessus

Les noms de champs ci-dessus — le chemin de l'endpoint, duration_seconds, aspect_ratio, la clé de l'identifiant — sont les détails les plus susceptibles de varier selon le modèle et le temps. La source de vérité fiable est la page de référence API du modèle. Vérifiez une fois, copiez les noms exacts comme constantes dans le script, et structurez le code pour qu'un changement de nom soit une modification d'une ligne plutôt qu'une recherche dans toute la base de code.

Si vous recevez un 4xx, le corps de la réponse d'erreur fournit plus d'informations que le code de statut. 401 signifie une clé erronée ou manquante ; une erreur de validation de type 422 indique généralement le champ en cause.

Soumettre et interroger la tâche jusqu'à l'achèvement

Une fois l'appel de soumission fonctionnel, le cycle de vie est : soumettre, capturer l'identifiant, interroger, s'arrêter à l'état terminal.

Soumettre

Le POST de la section précédente crée la tâche. Quoi que fasse le code ensuite, il doit stocker l'identifiant renvoyé dans un endroit durable — une variable du script, une ligne dans une table de tâches, un message dans une file d'attente. Si le processus meurt après avoir reçu la réponse de soumission mais avant de persister l'identifiant, vous perdez la capacité d'interroger cette tâche.

Interroger

L'interrogation est une requête GET sur la ressource de la tâche, avec l'identifiant que vous avez capturé :

curl "https://api.hiapi.ai/v1/models/kandinsky-6.0-pro/text-to-video/jobs/$JOB_ID" \
  -H "Authorization: Bearer $HIAPI_API_KEY"

La réponse indique l'état actuel de la tâche. En pratique, vous verrez peu d'états : en file d'attente ou en attente, en cours de traitement, terminée, et une forme d'échec ou d'annulation. Concevez votre boucle autour de ces catégories plutôt qu'autour des chaînes exactes — mappez tout ce que renvoie l'API vers running, done, failed dans votre code, pour qu'un renommage ne casse pas votre logique de nouvelle tentative.

Décider combien de temps attendre

Deux nombres comptent : l'intervalle d'interrogation et le délai global.

  • L'intervalle. Interrogez toutes les quelques secondes, pas en boucle serrée. Une boucle serrée n'apporte rien et peut déclencher des limites de débit. Pour des tâches vidéo, un intervalle de plusieurs secondes entre les requêtes est raisonnable.
  • Le délai. Fixez une limite supérieure. La génération vidéo prend du temps, mais « attendre indéfiniment » n'est pas une réponse acceptable pour un script de production. Choisissez un budget de temps maximal réaliste et traitez son dépassement comme un échec à journaliser et à retenter consciemment.

Un modèle qui résiste à l'usage réel

En production, l'étape d'interrogation est généralement découplée de l'étape de soumission, plutôt que placée dans un processus qui dort. Un worker soumet, enregistre la tâche et se termine ; une revérification périodique reprend les tâches inachevées et les interroge. C'est plus robuste face aux redémarrages et plus facile à observer. Pour ce tutoriel, une simple boucle dans un seul processus suffit — organisez-la simplement en fonctions plutôt qu'en code en ligne, et la déplacer plus tard vers un worker planifié périodiquement sera simple.

Télécharger le clip généré

Une tâche terminée n'est pas encore un fichier sur votre disque. La réponse d'état d'une tâche terminée pointe vers la sortie — généralement une URL, parfois un objet imbriqué contenant l'URL. Lisez ce champ et utilisez-le comme entrée de l'étape de téléchargement.

curl -L "$OUTPUT_URL" -o output/clip.mp4

Vérifiez les points suivants pour confirmer que le téléchargement a réellement réussi :

  • Suivez les redirections. Les URL de sortie sont souvent servies via redirection ; curl les gère avec -L, Python avec allow_redirects=True.
  • Vérifiez le type de contenu. Une tâche terminée doit produire une charge vidéo. Si un fichier enregistré sous clip.mp4 est en réalité du JSON ou une page d'erreur HTML, c'est le téléchargement qui a échoué, pas la génération.
  • Vérifiez la taille. Un fichier de zéro octet ou anormalement petit est un échec de téléchargement. Si des en-têtes de réponse existent, comparez le nombre d'octets à la taille déclarée.
  • Tenez compte de l'expiration. Les URL de sortie sont souvent limitées dans le temps. Téléchargez immédiatement après l'achèvement et, si vous avez besoin de persistance, copiez le fichier dans votre propre stockage plutôt que de conserver l'URL comme référence permanente.

Pour tout usage au-delà de ce tutoriel, diffusez le téléchargement vers la destination plutôt que de charger le fichier entier en mémoire, et écrivez d'abord sous un nom temporaire avant de renommer — ainsi un téléchargement incomplet n'apparaîtra jamais comme un fichier complet au code en aval.

Implémenter la même requête en Python

Voici la reconstruction du flux curl sous forme d'une fonction appelable : soumettre, interroger, télécharger. Les noms à ajuster sont regroupés en haut comme constantes.

import os
import time
import requests

API_BASE = "https://api.hiapi.ai/v1"
MODEL_PATH = "/models/kandinsky-6.0-pro/text-to-video"
API_KEY = os.environ["HIAPI_API_KEY"]

HEADERS = {"Authorization": f"Bearer {API_KEY}"}

RUNNING_STATES = {"queued", "pending", "processing", "running"}
DONE_STATES = {"completed", "succeeded", "done"}
FAILED_STATES = {"failed", "cancelled", "error"}


def generate_clip(prompt, out_path, timeout_s=600, interval_s=5):
    # 1. submit
    resp = requests.post(
        API_BASE + MODEL_PATH + "/jobs",
        headers={**HEADERS, "Content-Type": "application/json"},
        json={"prompt": prompt, "duration_seconds": 5, "aspect_ratio": "16:9"},
        timeout=30,
    )
    resp.raise_for_status()
    job = resp.json()
    job_id = job["id"]
    print(f"submitted job {job_id}")

    # 2. poll
    deadline = time.monotonic() + timeout_s
    while time.monotonic() < deadline:
        status_resp = requests.get(
            f"{API_BASE}{MODEL_PATH}/jobs/{job_id}",
            headers=HEADERS,
            timeout=30,
        )
        status_resp.raise_for_status()
        data = status_resp.json()
        state = str(data.get("status", "")).lower()

        if state in DONE_STATES:
            break
        if state in FAILED_STATES:
            raise RuntimeError(f"job {job_id} ended in state {state}: {data}")
        time.sleep(interval_s)
    else:
        raise TimeoutError(f"job {job_id} did not finish within {timeout_s}s")

    # 3. download
    url = data["output"]["url"] if isinstance(data.get("output"), dict) else data["output"]
    with requests.get(url, stream=True, allow_redirects=True, timeout=60) as r:
        r.raise_for_status()
        tmp = out_path + ".part"
        with open(tmp, "wb") as f:
            for chunk in r.iter_content(chunk_size=1 << 16):
                f.write(chunk)
        os.replace(tmp, out_path)
    print(f"saved {out_path}")
    return job_id


if __name__ == "__main__":
    generate_clip(
        "A slow drone shot over a misty pine forest at sunrise, soft golden light, cinematic",
        "output/clip.mp4",
    )

Pourquoi c'est écrit ainsi

  • Des ensembles d'états plutôt qu'une correspondance exacte. Mapper les états renvoyés vers running/done/failed signifie qu'un nouvel état intermédiaire ne cassera pas la boucle.
  • Une échéance monotone. time.monotonic() n'est pas affecté par les ajustements d'horloge, donc le délai est précis.
  • Une écriture atomique. Écrire dans .part puis renommer garantit qu'un téléchargement interrompu ne laisse jamais un fichier tronqué qui semble valide.
  • Renvoyer l'ID de tâche. L'appelant peut journaliser, stocker et interroger à nouveau si nécessaire — c'est le premier pas pour sortir l'interrogation de ce processus.

Ajustez le chemin de l'endpoint, les noms de champs de requête et les clés de réponse pour correspondre à la référence API du modèle. Tout le reste — la boucle, le délai, le téléchargement — est générique.

États d'erreur et checklist de débogage

Quand une exécution échoue, isolez d'abord l'étape avant de changer quoi que ce soit. Chaque étape a une signature de défaillance différente.

Échec d'authentification

Un 401 ou 403 à la soumission signifie que la clé est absente, erronée ou non envoyée. Vérifiez que la variable d'environnement est bien définie dans le shell ou le processus qui exécute le code — une clé exportée dans un terminal est invisible pour une tâche cron. Affichez les premiers caractères de la clé pour confirmer qu'elle est résolue, jamais la clé entière.

Requête mal formée

Une erreur de type 400 ou 422 à la soumission signifie que le corps de la requête a échoué à la validation. Le corps de la réponse indique généralement le champ. Causes fréquentes : paramètre mal orthographié, durée hors des plages prises en charge, ou prompt vide. Comparez votre JSON champ par champ avec la référence API ; une seule clé renommée est la cause la plus fréquente.

Tâche bloquée en état d'exécution

Si l'interrogation n'atteint jamais un état terminal, vérifiez trois choses : l'identifiant que vous interrogez est bien celui que vous avez soumis ; l'intervalle d'interrogation n'est pas si fréquent qu'il déclenche une limite de débit ; le délai est suffisamment long pour le modèle. Journalisez la réponse d'état brute à chaque interrogation pour voir si l'état progresse ou reste figé.

Tâche terminée mais téléchargement en échec

Une tâche terminée dont le téléchargement échoue est un problème de traitement de fichier, pas de génération. Vérifiez si les redirections sont suivies, si l'URL n'a pas expiré, et si le type de contenu est bien une vidéo et non du JSON. Essayez l'URL séparément avec curl -L pour l'isoler du script.

Le même prompt échoue de façon répétée

Si un prompt échoue systématiquement alors que d'autres réussissent, soupçonnez d'abord la politique de contenu ou la longueur du prompt, pas l'infrastructure. Changez une variable — raccourcissez le prompt, simplifiez la description de la scène — puis réessayez.

Une règle générale

Journalisez quatre choses pour chaque tâche : l'identifiant de tâche, l'état final, le temps écoulé réel, et le statut HTTP du téléchargement. Ces quatre valeurs transforment la plupart des rapports « ça ne marche pas » en une étape concrète et réparable en moins d'une minute.

Articles similaires

Voir tous les articles →

Commencez avec des artefacts IA persistants

Obtenez votre clé API et appelez des modèles d'image, de vidéo et d'audio via une API unique basée sur les tasks.

Lire la documentation de l'API