HiAPI
Blog

Tutoriel

Comment appeler hailuo-2.3/text-to-video via l'API HiAPI : curl, Python et exemples de requêtes exécutables

Nov 3, 2026
极简封面图:浅藕紫色与墨黑色两块纯色平面以一道清晰的硬边相接,边缘有一条细紫缝,构图庄重平静。

Ce que fait l'endpoint hailuo-2.3/text-to-video

Si vous disposez d'un prompt textuel et souhaitez générer à partir de celui-ci un court clip vidéo, hailuo-2.3/text-to-video est l'endpoint qu'il vous faut. Il reçoit un prompt en langage naturel décrivant la scène, le sujet et le mouvement que vous souhaitez voir, puis renvoie le clip vidéo généré. Le modèle est optimisé pour des sorties courtes, il donne donc le meilleur de lui-même lorsque vous demandez un instant compact et autonome plutôt qu'un long récit.

Sur HiAPI, l'appel suit le même schéma que les autres endpoints de génération asynchrone : vous envoyez une requête, le service accepte la tâche, puis vous interrogez le statut jusqu'à ce que le résultat soit prêt. Cela rend cet endpoint parfaitement adapté aux pipelines backend — outils de contenu, générateurs de prototypes, tâches par lots, ou tout scénario nécessitant quelques secondes de vidéo à la demande sans qu'une personne doive rester devant un éditeur vidéo.

La requête porte un prompt et quelques paramètres de contrôle de génération ; la réponse contient un identifiant de tâche, puis l'URL de la vidéo terminée. Vous n'avez pas à gérer de GPU ni de poids de modèle — HiAPI se charge du calcul et renvoie le lien de sortie. Si vous avez déjà utilisé d'autres API de texte-vers-vidéo, la forme générale vous sera familière, mais le style de prompt de hailuo-2.3 récompense davantage une réflexion sur la physique du mouvement qu'une simple description visuelle (nous y reviendrons en détail plus loin).

Prérequis et identifiants API

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

  • Une clé API issue de votre compte HiAPI. Traitez-la comme un mot de passe : ne la versionnez pas, chargez-la depuis une variable d'environnement, et renouvelez-la en cas de fuite.
  • Un client HTTP. Les exemples shell ci-dessous ne nécessitent que curl. Les exemples Python nécessitent Python 3.8+ ainsi que la bibliothèque requests (pip install requests).
  • L'URL de base de l'API HiAPI. Toutes les requêtes sont envoyées à l'hôte de l'API HiAPI, avec le chemin d'endpoint hailuo-2.3/text-to-video. Vous vous authentifiez en envoyant un bearer token dans l'en-tête Authorization.

Définissez la clé dans une variable d'environnement afin qu'elle n'apparaisse pas dans votre code :

export HIAPI_API_KEY="your_api_key_here"

En Python, vous pouvez la lire avec os.environ["HIAPI_API_KEY"]. Avec curl, vous référencerez la même variable via $HIAPI_API_KEY.

Il reste un point à décider à l'avance : où les vidéos générées seront stockées. L'API renvoie l'URL de la sortie, et cette URL doit être récupérée et stockée rapidement dans votre propre bucket ou système de fichiers — ne construisez pas un pipeline qui suppose que cette URL est un actif permanent.

Requête exécutable avec curl

Voici un appel curl complet pour soumettre une tâche de texte-vers-vidéo. Remplacez le prompt par votre propre description de scène. Le corps de la requête est du JSON ; les champs clés sont le prompt ainsi que les paramètres de génération contrôlant la durée et la forme de la sortie.

curl -X POST "https://api.hiapi.ai/v1/hailuo-2.3/text-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "une bille de verre dévale une pente en bois, accélère puis tombe sur un sol en pierre, rebondit deux fois et s'immobilise",
    "duration": 6
  }'

Une soumission réussie renvoie un objet JSON contenant un identifiant de tâche. Cela ressemble à ceci :

{
  "id": "job_abc123",
  "status": "queued"
}

L'élément essentiel est id. La génération ne se termine pas de façon synchrone — l'endpoint met la tâche en file d'attente et renvoie immédiatement le contrôle. Conservez le id ; vous l'utiliserez pour interroger le statut et finalement récupérer l'URL de la vidéo.

Si vous rencontrez une erreur d'authentification, vérifiez que la clé a bien été exportée dans la même session shell. En cas d'erreur de validation, vérifiez que le corps JSON est correctement formé et que le prompt est présent. Une réponse 429 indique que vous envoyez des requêtes trop rapidement et que vous devez adopter un backoff — la section sur la production détaille cela.

Le même appel en Python

La version Python fait la même chose, mais encapsulée dans une fonction réutilisable, pratique à intégrer dans un pipeline. Elle soumet la tâche et renvoie l'identifiant de tâche.

import os
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def submit_text_to_video(prompt: str, duration: int = 6) -> str:
    """Soumet une tâche hailuo-2.3/text-to-video et renvoie son id de tâche."""
    api_key = os.environ["HIAPI_API_KEY"]
    response = requests.post(
        f"{HIAPI_BASE}/hailuo-2.3/text-to-video",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json={"prompt": prompt, "duration": duration},
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    return data["id"]


if __name__ == "__main__":
    job_id = submit_text_to_video(
        "une bille de verre dévale une pente en bois, accélère puis tombe sur un sol en pierre, rebondit deux fois et s'immobilise"
    )
    print("submitted job:", job_id)

Quelques détails méritent d'être conservés :

  • raise_for_status() transforme les réponses non 2xx en exceptions, ce qui est précisément le comportement souhaité dans un pipeline. Il vaut mieux échouer bruyamment à la soumission que d'interroger une tâche qui n'a jamais été créée.
  • Le timeout de la requête de soumission est volontairement court. La soumission doit être rapide ; les longues attentes se produisent pendant le polling, pas ici.
  • Le paramètre duration est un paramètre distinct, afin que l'appelant puisse demander un clip plus court ou plus long sans dupliquer la logique de construction de la requête.

Une fois cette fonction retournée, vous disposez de tout ce qu'il faut pour poursuivre le suivi du statut.

Rédiger des prompts axés sur la physique du mouvement pour des clips de 6 à 10 secondes

Les clips courts ne laissent aucune marge. En six à dix secondes, vous ne pouvez pas établir un personnage, construire un monde et boucler une intrigue — les prompts les plus efficaces décrivent donc une seule action continue avec une conséquence physique claire. Considérez le prompt comme la description d'un plan d'un instant, et non comme une histoire.

Commencez par le sujet et l'action

Commencez par ce qui bouge et par ce qu'il fait. « une bille de verre dévale une pente en bois » donne immédiatement au modèle le sujet, la matière et la direction du déplacement. Une ouverture vague comme « une belle scène » ne lui donne rien à animer.

Décrivez les forces, pas seulement l'apparence

Un prompt axé sur la physique du mouvement signifie nommer les forces en jeu : gravité, friction, élan, poids, élasticité. Des mots comme rouler, accélérer, rebondir, s'immobiliser, osciller, basculer, éclabousser, se déchirer suggèrent un modèle physique. Pour un objet qui rebondit, précisez combien de fois il rebondit et où il finit par s'arrêter. Pour un objet qui tombe, précisez sur quoi il tombe et s'il se brise, s'enfonce ou rebondit.

Gardez un plan explicite et simple

Un plan fixe ou un seul mouvement de caméra lent suffit généralement pour un clip court. Si la caméra et le sujet font tous deux des choses complexes, le clip devient confus et le mouvement ressemble à du bruit. Ne précisez le type de plan que lorsqu'il importe pour l'action — gros plan, plan large, travelling.

Construisez une arche événementielle

Un modèle utile pour un clip de 6 à 10 secondes est : mise en place → action → conséquence. La bille est en haut de la pente ; elle dévale et accélère ; elle tombe, rebondit deux fois et s'immobilise. Cette arche donne au modèle un début, un milieu et une fin, tous adaptés à la longueur du clip. Évitez de demander plusieurs actions sans rapport ; un événement physique bien décrit se lit bien mieux que trois événements à moitié aboutis.

Enfin, restez précis dans le prompt. Les matériaux, l'éclairage et la texture des surfaces aident le modèle à ancrer le mouvement — une bille sur du bois ne se comporte pas comme une bille sur de la glace, et le préciser oriente le résultat.

Gérer les tâches asynchrones par polling

La génération prend du temps, c'est pourquoi l'endpoint est asynchrone. Après avoir soumis la tâche, vous recevez un id ; vous interrogez ensuite l'endpoint de statut jusqu'à ce que la tâche atteigne un état terminal. Une boucle de polling robuste gère trois choses : l'intervalle, le timeout et l'exposition des erreurs.

import time
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def wait_for_video(job_id: str, api_key: str, interval: float = 3.0, max_wait: float = 600.0) -> str:
    """Interroge jusqu'à ce que la tâche soit terminée et renvoie l'URL de la vidéo de sortie."""
    deadline = time.time() + max_wait
    url = f"{HIAPI_BASE}/hailuo-2.3/text-to-video/{job_id}"

    while time.time() < deadline:
        response = requests.get(
            url,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30,
        )
        response.raise_for_status()
        data = response.json()
        status = data.get("status")

        if status == "completed":
            return data["output"]["video_url"]
        if status in ("failed", "cancelled"):
            raise RuntimeError(f"La tâche {job_id} s'est terminée avec le statut {status} : {data.get('error')}")

        time.sleep(interval)

    raise TimeoutError(f"La tâche {job_id} ne s'est pas terminée en {max_wait} secondes")

Remarques sur cette boucle :

  • Interrogez à intervalle régulier, pas en boucle serrée. Quelques secondes entre les vérifications suffisent et évitent de marteler l'API.
  • Limitez toujours le temps d'attente total. Une tâche bloquée ne doit pas suspendre indéfiniment un worker. La valeur max_wait ici est conservatrice ; ajustez-la selon la longueur de vos clips et l'état de la file d'attente.
  • Traitez failed comme une vraie branche. Exposez la charge d'erreur au lieu de réessayer aveuglément — un problème de prompt ou de paramètre ne se corrige pas tout seul.
  • Renvoiez l'URL de la vidéo, pas la réponse brute. L'appelant de cette fonction ne devrait pas avoir besoin de connaître la structure de la réponse.

Pour des charges de travail plus lourdes, placez les étapes de soumission et de polling dans des workers distincts : un worker met les tâches en file d'attente et stocke les identifiants de tâche, un autre se charge du polling et du téléchargement. Cela découple la latence des requêtes du temps de génération.

Télécharger et stocker la sortie

Une fois que le polling renvoie l'URL de la vidéo, récupérez les octets et écrivez-les dans un emplacement persistant. Faites-le rapidement : l'URL renvoyée est un lien de livraison, pas un stockage d'actif permanent. Téléchargez en streaming plutôt que de charger tout le fichier en mémoire ; écrivez d'abord dans un chemin temporaire puis renommez, afin qu'un téléchargement partiel ne ressemble jamais à un fichier terminé.

import os
import tempfile
import requests


def download_video(video_url: str, dest_path: str) -> None:
    """Écrit atomiquement en streaming la vidéo terminée vers dest_path."""
    os.makedirs(os.path.dirname(dest_path) or ".", exist_ok=True)
    with requests.get(video_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(dest_path) or ".")
        try:
            with os.fdopen(fd, "wb") as f:
                for chunk in response.iter_content(chunk_size=1 << 16):
                    f.write(chunk)
            os.replace(tmp_path, dest_path)
        except Exception:
            if os.path.exists(tmp_path):
                os.unlink(tmp_path)
            raise


api_key = os.environ["HIAPI_API_KEY"]
video_url = wait_for_video("job_abc123", api_key)
download_video(video_url, f"out/{'job_abc123'}.mp4")

Quelques choix pratiques :

  • Nommez le fichier d'après l'identifiant de tâche. Cela vous donne une clé stable et résistante aux collisions, et facilite le rattachement du fichier à la requête qui l'a produit.
  • Stockez les métadonnées avec la vidéo. Conservez le prompt d'origine, la durée et l'horodatage dans un JSON annexe ou une base de données. Six mois plus tard, vous voudrez savoir ce qui a produit un clip.
  • En production, téléversez vers un stockage objet. Écrire sur le disque local convient à un prototype ; un vrai pipeline doit pousser les fichiers vers votre bucket et enregistrer la clé d'objet, afin que les vidéos survivent au redémarrage des workers.

Conseils de production et modes de défaillance courants

La plupart des premières intégrations échouent aux mêmes endroits. Voici ce qu'il faut surveiller.

Réessayez les bonnes choses

Réessayez les défaillances transitoires — erreurs réseau, timeouts, réponses 429 et 5xx — avec un backoff exponentiel et du jitter. Ne réessayez pas les erreurs de validation 4xx ; un prompt malformé ou un paramètre incorrect échouera de la même manière à chaque fois. Si la tâche de génération elle-même échoue, exposez l'erreur et décidez prudemment s'il faut resoumettre.

Séparez la soumission et le polling

En production, la soumission et le polling doivent être des étapes distinctes, souvent dans des processus différents. Stockez immédiatement l'identifiant de tâche dans une file d'attente ou une base de données après une soumission réussie. Si un worker plante, vous pouvez reprendre le polling au lieu de perdre la tâche.

Définissez des timeouts partout

Les requêtes de soumission, le polling de statut et le téléchargement de fichiers doivent chacun avoir un timeout. L'absence de timeout à l'étape de téléchargement est la cause classique d'un worker qui se bloque.

Gardez les prompts dans les limites du modèle

Dans la plage de six à dix secondes, demandez une action unique et physiquement plausible. Lorsqu'un prompt en demande trop, vous obtenez un clip confus au mouvement brouillon. Si la qualité de sortie est irrégulière, raccourcissez d'abord le prompt et simplifiez l'action avant d'envisager de changer les paramètres.

Gérez correctement les identifiants

Chargez la clé API depuis des variables d'environnement ou un gestionnaire de secrets, jamais depuis un fichier versionné. Utilisez une clé différente par environnement, afin qu'une clé de développement compromise ne puisse pas atteindre la production.

Méfiez-vous des hypothèses d'expiration des URL

L'erreur la plus courante en production consiste à traiter l'URL vidéo renvoyée comme un lien permanent et à la rendre directement dans l'interface utilisateur des mois plus tard. Téléchargez et réhébergez le fichier dans le cadre de la tâche, et stockez votre propre URL.

Avec ces habitudes, l'intégration reste simple : soumettre, interroger, télécharger, stocker.

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