HiAPI
Blog

Tutoriel

Comment appeler veo-3.1-lite/text-to-video via l'API HiAPI : curl et Python

Exemples de requêtes directement copiables, flux de génération de vidéo à partir d'un prompt, et modèle d'interrogation asynchrone

Nov 3, 2026
深炭底色上,一道琥珀色光带横向掠过,构图克制,是这篇教程文章的封面图。

Ce que veo-3.1-lite/text-to-video peut vous apporter

veo-3.1-lite/text-to-video est un point de terminaison de génération de vidéo à partir de texte sur HiAPI : vous envoyez un prompt textuel et le modèle renvoie un clip vidéo généré. Le mot « lite » dans le nom est le signal le plus important lorsqu'il s'agit de choisir un modèle. Le palier léger est conçu pour le débit et l'itération rapide, et non pour une fidélité maximale ; il constitue donc un excellent choix par défaut lorsque vous avez besoin de nombreux clips courts, que vous prototypez une fonctionnalité avant de décider d'adopter un modèle plus lourd, ou que le clip n'est qu'un maillon d'un pipeline d'automatisation plus vaste où la latence par clip et l'échelle des lots comptent davantage que la qualité cinématographique.

Lorsque le clip est lui-même le produit — par exemple un plan principal, un élément marketing, ou tout contenu qui sera examiné image par image par des humains — il faut plutôt passer à un modèle de génération de vidéo à partir de texte plus lourd. En revanche, lorsque le clip n'est qu'un composant — aperçu de brouillon, boucle d'arrière-plan, ébauche de storyboard, ou premier rendu destiné à être affiné ensuite — choisissez veo-3.1-lite/text-to-video.

Deux caractéristiques de ce point de terminaison déterminent tout ce qui suit :

  • Il est asynchrone. Une requête de génération ne vous renvoie pas directement un fichier lisible dans la même réponse. Vous soumettez une tâche, recevez une référence vers cette tâche, puis interrogez jusqu'à ce que la tâche soit terminée et que l'URL de sortie soit disponible.
  • Il est piloté par le prompt. Il n'y a ni image d'entrée ni vidéo source dans ce flux — le texte que vous envoyez constitue le brief créatif complet, de sorte que la qualité du prompt est votre principal levier.

Le reste de ce guide est un exercice pratique : construire la requête, soumettre avec curl, porter en Python, interroger correctement, et gérer les cas d'échec que vous rencontrerez réellement.

Prérequis et authentification

Avant le premier appel, assurez-vous de disposer des éléments suivants :

  • Une clé API issue de votre compte HiAPI. Traitez-la comme un secret, avec le même soin qu'un mot de passe de base de données.
  • Un moyen d'envoyer des requêtes HTTP : curl pour les vérifications rapides, Python 3 avec la bibliothèque requests pour toute tâche scriptée.
  • Un emplacement pour stocker le clip final, car la sortie arrive sous forme d'URL qu'il vous faudra télécharger.

La clé est transmise dans chaque requête via un en-tête HTTP. Copiez exactement le nom d'en-tête et le préfixe Bearer indiqués ; un en-tête absent ou mal formaté est la cause la plus fréquente d'échec au premier appel.

Garder la clé hors du contrôle de source

Ne collez jamais une clé réelle dans un fichier que vous allez committer. Utilisez plutôt une variable d'environnement :

export HIAPI_API_KEY="your-key-here"

Puis lisez-la à l'exécution. Si vous travaillez en équipe ou dans un pipeline CI, stockez la clé dans un gestionnaire de secrets et injectez-la en tant que variable d'environnement au déploiement. Si une clé a été exposée — commit accidentel, collage dans un ticket, impression dans les logs — faites-la tourner immédiatement au lieu de compter sur le fait que personne ne le remarquera.

Avant de commencer à déboguer quoi que ce soit d'autre, vérifiez rapidement que la variable d'environnement est définie :

test -n "$HIAPI_API_KEY" && echo "key is set" || echo "key is missing"

Une requête curl fonctionnelle

Voici la forme d'une requête de soumission de génération de vidéo à partir de texte. Remplacez l'URL de base de l'espace réservé du point de terminaison par celle documentée dans votre référence HiAPI, et conservez strictement l'identifiant de modèle inchangé : veo-3.1-lite/text-to-video.

curl -X POST "$HIAPI_BASE_URL/v1/videos/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "veo-3.1-lite/text-to-video",
    "prompt": "A slow dolly-in on a rain-soaked neon sign at night, shallow depth of field, gentle camera drift, cinematic color"
  }'

Une soumission réussie ne renvoie pas les octets de la vidéo. Elle renvoie un objet tâche : contenant l'identifiant de cette tâche, un champ status dont l'état initial est quelque chose comme queued ou processing, ainsi que des métadonnées sur l'heure de création. Cet identifiant est le handle de toutes vos opérations suivantes — vous devrez l'interroger jusqu'à ce que le statut atteigne un état terminal, et c'est seulement alors que la réponse portera l'URL du clip généré.

Si vous testez manuellement, capturez la réponse complète plutôt que de vous contenter de la regarder :

curl -s -X POST "$HIAPI_BASE_URL/v1/videos/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"veo-3.1-lite/text-to-video","prompt":"A paper boat drifting down a sunlit gutter, macro lens"}' \
  | tee submission.json

Deux habitudes méritent d'être prises dès maintenant. Premièrement, envoyez toujours Content-Type: application/json ; un corps de requête qui ressemble à du JSON mais n'est pas déclaré comme tel sera rejeté. Deuxièmement, si l'appel échoue, lisez le corps de la réponse d'erreur avant de modifier quoi que ce soit — HiAPI renvoie des messages structurés qui, généralement, pinpointent le problème plus précisément qu'un simple code de statut (clé incorrecte, modèle inconnu, champ manquant).

Si un code de statut non 2xx est renvoyé ici, cela signifie que la tâche n'a jamais été acceptée. N'interrogez pas une soumission échouée ; corrigez d'abord la requête.

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

L'appel curl se porte directement. Le script ci-dessous soumet le prompt, vérifie que la soumission a réussi, et conserve la référence de tâche pour l'étape d'interrogation.

import os
import requests

BASE_URL = os.environ["HIAPI_BASE_URL"]
API_KEY = os.environ["HIAPI_API_KEY"]

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "veo-3.1-lite/text-to-video",
    "prompt": (
        "A single lantern floating on still black water, "
        "soft ripples, warm light against cool darkness, slow push-in"
    ),
}

response = requests.post(
    f"{BASE_URL}/v1/videos/generations",
    headers=headers,
    json=payload,
    timeout=30,
)

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

job = response.json()
job_id = job["id"]
print(f"submitted job {job_id} with status {job.get('status')}")

Plusieurs choix délibérés figurent dans cet extrait :

  • Utiliser json=payload plutôt que de concaténer des chaînes manuellement. Laissez la bibliothèque gérer la sérialisation et définir le type de contenu ; cela évite toute une catégorie de bugs liés aux guillemets.
  • Définir explicitement un timeout. Sans cela, une connexion bloquée ferait pendre le script indéfiniment. L'appel de soumission est rapide — même un timeout généreux ici reste court.
  • Échouer durement sur un statut non 2xx. Lever une exception immédiatement rapproche l'erreur de sa cause, au lieu de laisser un job ID corrompu se propager dans la boucle d'interrogation.
  • La clé provient de os.environ. Aucun secret n'est écrit dans le fichier lui-même.

Enveloppez cela dans une fonction qui renvoie un job_id, et vous disposez de la partie soumission de n'importe quel pipeline.

Interroger la tâche asynchrone et télécharger le clip

La génération vidéo prend du temps. L'appel de soumission renvoie en une ou deux secondes ; le rendu réel, non. Si vous écrivez du code qui suppose que la première réponse contient l'URL de la vidéo, il échouera — non pas parce que l'API est cassée, mais parce que vous lisez une tâche qui n'est pas encore terminée.

Le bon modèle est l'interrogation bornée : dormir entre les vérifications, reculer à mesure que le temps d'attente augmente, et abandonner après un nombre maximal de tentatives plutôt que de boucler indéfiniment.

import time
import requests

def wait_for_video(job_id, headers, base_url, max_attempts=60, initial_delay=5):
    delay = initial_delay
    for attempt in range(1, max_attempts + 1):
        r = requests.get(
            f"{base_url}/v1/videos/generations/{job_id}",
            headers=headers,
            timeout=30,
        )
        if r.status_code >= 400:
            raise RuntimeError(f"Poll failed: {r.status_code} {r.text}")

        data = r.json()
        status = data.get("status")
        print(f"attempt {attempt}: {status}")

        if status == "completed":
            return data
        if status in {"failed", "cancelled"}:
            raise RuntimeError(f"Job {job_id} ended as {status}: {data}")

        time.sleep(delay)
        delay = min(delay * 1.5, 30)

    raise TimeoutError(f"Job {job_id} did not finish within polling budget")

Lorsque la tâche atteint completed, la réponse porte l'emplacement de sortie — l'URL du clip terminé. Si le clip est volumineux, téléchargez-le plutôt que de le lire en flux dans la mémoire :

result = wait_for_video(job_id, headers, BASE_URL)
video_url = result["output"]["url"]

with requests.get(video_url, stream=True, timeout=120) as r:
    r.raise_for_status()
    with open(f"{job_id}.mp4", "wb") as f:
        for chunk in r.iter_content(chunk_size=1 << 16):
            f.write(chunk)

print("saved", f"{job_id}.mp4")

Deux détails important en production. Premièrement, l'URL de sortie peut être soumise à une limite de temps, alors téléchargez-la rapidement plutôt que de conserver le lien quelques jours avant de récupérer — persistez le fichier ou copiez-le dans votre propre stockage. Deuxièmement, consignez l'ID de tâche à côté de chaque artefact. En cas de problème en aval, l'ID de tâche vous permet de recouper vos propres enregistrements avec ce que l'API a réellement renvoyé.

Erreurs courantes et comment les corriger

La plupart des échecs au premier lancement se répartissent en quelques catégories. Voici comment chacune se manifeste et ce qu'il faut modifier.

Échec d'authentification

Un 401 ou 403 à la soumission signifie que la clé n'est pas acceptée. Vérifiez dans l'ordre : la variable d'environnement a-t-elle réellement une valeur dans ce shell ou ce processus ; le nom d'en-tête est-il Authorization ; le préfixe Bearer est-il présent avec un espace après ; la clé a-t-elle été tournée ou révoquée. Une clé qui fonctionne dans votre terminal mais échoue en CI signifie presque toujours que le secret n'a pas été injecté dans cet environnement.

Identifiant de modèle invalide

Un 400 ou 404 mentionnant le nom du modèle indique une chaîne qui ne correspond pas. L'identifiant est veo-3.1-lite/text-to-video — la barre oblique et le numéro de version en font partie. Copiez-collez, ne retapez pas ; un espace superflu ou un numéro de version modifié suffit à faire échouer.

Prompt mal formaté ou vide

Un prompt vide, un champ prompt manquant, ou un corps de requête envoyé sans Content-Type: application/json seront tous rejetés avant que la génération ne commence. Si vous construisez vos prompts dynamiquement, journalisez la chaîne exacte que vous avez envoyée en cas d'échec — les bugs de template produisant des prompts vides ou tronqués sont courants et invisibles tant qu'ils ne sont pas affichés.

Expiration de l'interrogation

Si wait_for_video épuise son budget, ne resoumettez pas immédiatement. La tâche est peut-être simplement encore en cours. Vérifiez à nouveau le statut une fois, confirmez que votre intervalle d'interrogation n'est pas si long qu'il consume le budget en sommeil, et confirmez que le budget est réaliste pour la durée de clip demandée. Resoumettre à chaque expiration est précisément la raison pour laquelle vous finissez par payer plusieurs fois le même clip.

Limitation de débit

Un 429 signifie qu'un recul est nécessaire. Le délai exponentiel dans la boucle d'interrogation aide déjà ; appliquez la même retenue à la soumission, et mettez le travail en file d'attente plutôt que de l'envoyer en rafale. En cas de doute, respectez d'abord les indications de réessai présentes dans les en-têtes de réponse, puis votre propre plan de recul.

Coûts et conseils d'itération avant la production

La génération vidéo est facturée à la sortie — c'est-à-dire à la longueur du contenu produit — de sorte que l'erreur coûteuse consiste à tester de petites idées avec de longs clips. Le flux de travail le plus économique est celui qui ne génère jamais un clip dont vous n'avez pas besoin.

Testez la structure du prompt, pas la sortie finale. Rédigez et affinez vos prompts sur la durée la plus courte prise en charge par ce point de terminaison. Une fois que la composition, le mouvement et le langage cinématographique se lisent correctement dans un clip court, augmentez la durée pour le rendu final. La plupart des itérations de prompt portent sur la formulation, pas sur la longueur, et un rendu court répond tout aussi bien aux questions de formulation.

Tenez un journal des prompts. Consignez pour chaque test le prompt, la durée et votre propre jugement. Dix itérations documentées vous en apprendront davantage sur ce à quoi ce modèle réagit que cinquante itérations non documentées, et vous ne retesterez plus des prompts déjà rejetés.

Traitez par lots de manière réfléchie. Si vous avez besoin de nombreux clips, mettez-les en file et exécutez-les en parallèle dans les limites de débit — mais faites d'abord un essai du lot entier avec un petit nombre de prompts. Découvrir un bug systématique de prompt après avoir soumis deux cents tâches est le coût le plus évitable.

Interrogez avec retenue. Une interrogation fréquente n'accélère pas le rendu et peut vous pousser dans la limitation de débit. Un intervalle initial modéré associé à un recul doux constitue la bonne valeur par défaut.

Échouez tôt et fort. Chaque garde-fou dans le code ci-dessus — lever une exception sur un statut non 2xx à la soumission, détecter un échec terminal lors de l'interrogation, borner le nombre de tentatives — vise à vous éviter de payer deux fois le même travail. Conservez-les en production.

Commencez par un prompt court et une requête curl pour confirmer le cycle de vie de la tâche de bout en bout, puis transposez le même flux dans votre pipeline Python. La référence complète du point de terminaison se trouve sur la page de documentation du modèle veo-3.1-lite/text-to-video de HiAPI.

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