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
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
POSTne 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_idou un nom similaire. - Un champ d'état initial, généralement quelque chose comme
queuedouprocessing. - 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 avecallow_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.mp4est 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
.partpuis 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 →-
Tutoriel
Comment appeler hailuo-2.3-fast/image-to-video via l'API HiAPI : curl et Python en pratique
La première requête exploitable du palier image-vers-vidéo rapide et économique — de l'ID du modèle au téléchargement du MP4
-
Tutoriel
Comment appeler hailuo-2.3/text-to-video via l'API HiAPI : curl, Python et exemples de requêtes exécutables
-
Tutoriel
Comment utiliser kling-4.0/text-to-video via l'API HiAPI : curl, Python et un exemple de requête fonctionnel
Guide pratique pour les développeurs : prompts cinématographiques, audio synchronisé, interrogation asynchrone et téléchargement des sorties