Tutoriel
Comment utiliser l'API de génération vidéo à partir d'image hailuo 2.3 Fast : curl, Python et requêtes exécutables
Vous avez une image statique et vous voulez la transformer en une courte vidéo. Ce guide vous montre comment intégrer hailuo-2.3-fast/image-to-video via l'API de tâches hiapi : le schéma d'entrée exact (vérifié contre le validateur en ligne), une requête curl directement copiable, un script Python complet qui interroge jusqu'à la fin de la tâche, ainsi que les détails de production — callbacks, nouvelles tentatives idempotentes, et les réponses d'erreur que vous rencontrerez réellement.
Ce dont vous avez besoin
- Une clé API hiapi — obtenez-la depuis votre console. La clé ressemble à
sk-...et se place dans l'en-têteAuthorization: Bearer. - Une image source hébergée sur une URL HTTPS accessible publiquement. L'API reçoit une URL, pas un fichier téléversé.
- N'importe quel client HTTP. Les exemples ci-dessous utilisent curl et
requestsen Python.
Le tarif à la seconde de ce modèle est indiqué sur la page de tarification.
Schéma d'entrée (vérifié)
hailuo-2.3-fast/image-to-video utilise le point de terminaison unifié de tâches asynchrones : POST /v1/tasks crée une tâche, GET /v1/tasks/<taskId> interroge la tâche. Le schéma d'entrée est strict — les champs inconnus sont rejetés avec une erreur 400, au lieu d'être ignorés silencieusement.
| Champ | Type | Requis | Description |
|---|---|---|---|
prompt |
string | ✅ | Décrit le mouvement souhaité |
image_url |
string | ✅ | Forme singulière — une chaîne URL, pas un tableau image_urls |
duration |
string | Facultatif | "6" ou "10" — c'est une chaîne, pas un nombre |
prompt_optimizer |
boolean | Facultatif | Laisse le backend reformuler votre prompt pour le mouvement |
Le validateur intercepte trois pièges :
durationdoit être une chaîne. Envoyer"duration": 6renvoie400avecduration: got number, want string. Envoyez"duration": "6".- Le champ est
image_urlau singulier. Beaucoup d'autres modèles vidéo de la plateforme (Grok Imagine, Kling) reçoivent un tableauimage_urls. Ce modèle reçoit une seule chaîne. - Pas de
resolution,aspect_ratio,seed,watermarkniend_image_url. Tous renvoientadditional properties ... not allowed. Le format de sortie suit votre image source ; le contrôle du mouvement passe uniquement par le prompt.
Requête minimale exécutable : curl
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": "La caméra avance lentement, de la vapeur s'élève de la tasse de café, douce lumière du matin",
"image_url": "https://your-cdn.example.com/coffee.jpg",
"duration": "6"
}
}'
Réponse de succès :
{
"code": 200,
"data": { "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V" },
"message": "success"
}
Ensuite, interrogez :
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V \
-H "Authorization: Bearer sk-YOUR_KEY"
Pendant le rendu de la vidéo, data.status vaut "handling" :
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V",
"model": "hailuo-2.3-fast/image-to-video",
"status": "handling",
"storage": "temp",
"completed": 0,
"created": 1783648872
},
"message": "success"
}
Les états finaux sont "success" (l'URL de la vidéo se trouve dans data.output[0].url) et "fail" (détails dans data.error).
Script Python complet
import os
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"] # sk-...
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def create_task(prompt: str, image_url: str, duration: str = "6") -> str:
resp = requests.post(
API_BASE,
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": prompt,
"image_url": image_url,
"duration": duration, # chaîne : "6" ou "10"
},
},
timeout=60,
)
body = resp.json()
if resp.status_code != 200 or not body.get("data", {}).get("taskId"):
raise RuntimeError(f"création échouée : {resp.status_code} {body}")
return body["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"tâche échouée : {err.get('code')} {err.get('message')}")
time.sleep(poll_s)
raise TimeoutError(f"la tâche {task_id} tourne toujours après {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
prompt="Le chat cligne des yeux, tourne la tête vers la fenêtre, une brise caresse sa fourrure",
image_url="https://your-cdn.example.com/cat.jpg",
duration="6",
)
print("tâche :", task_id)
task = wait_task(task_id)
video_url = task["output"][0]["url"]
print("vidéo :", video_url)
# L'URL se trouve sur un stockage temporaire à durée limitée — téléchargez-la immédiatement, ne la liez pas directement.
mp4 = requests.get(video_url, timeout=120).content
with open("output.mp4", "wb") as f:
f.write(mp4)
print(f"output.mp4 enregistré ({len(mp4)} octets)")
Ce script fait correctement deux choses que les solutions bricolées à la hâte négligent souvent :
- Il télécharge la vidéo immédiatement.
storage: "temp"signifie que l'URL de sortie a une durée de validité (expireAt). Persistez les octets dans votre propre stockage ; ne stockez jamais l'URL renvoyée dans votre base de données. - Il traite
failcomme un état final. Interroger à nouveau une tâche échouée ne la ressuscite pas — créez une nouvelle tâche.
Considérations de production
Utilisez des callbacks au lieu de l'interrogation
Pour les cas d'usage hors script, enregistrez un webhook à la création de la tâche et sautez complètement la boucle d'interrogation :
{
"model": "hailuo-2.3-fast/image-to-video",
"input": { "prompt": "...", "image_url": "https://...", "duration": "6" },
"callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
Avec "when": "final", votre point de terminaison est appelé une fois lorsque la tâche atteint success ou fail. Règle empirique : l'interrogation convient aux CLI, aux tâches par lots et à tout scénario ad hoc ; dès que vous avez un serveur déjà à l'écoute, les callbacks sont préférables — les tâches vidéo prennent plusieurs minutes, et une boucle d'interrogation pendant ces minutes, c'est un slot de connexion occupé et un worker gaspillé.
Idempotence
L'appel de création n'est pas idempotent en lui-même — chaque POST /v1/tasks validé crée une nouvelle tâche (facturée). Si votre exécuteur de tâches réessaie en cas de timeout, stockez le taskId obtenu en le cléant sur votre propre identifiant de requête avant de traiter le résultat. Lors d'une nouvelle tentative, si ce clé possède déjà un taskId, interrogez-le au lieu de créer une tâche en double.
Les erreurs que vous rencontrerez réellement
| Symptôme | Signification | Correction |
|---|---|---|
401 — {"error":{"code":"permission_denied","type":"hiapi_error"}} |
Clé invalide, ou cette clé n'a pas accès à ce modèle | Vérifiez la clé dans la console ; la réponse contient un request_id utile au support |
400 INVALID_REQUEST — duration: got number, want string |
Un nombre JSON a été utilisé au lieu d'une chaîne | "duration": "6" |
400 INVALID_REQUEST — additional properties '...' not allowed |
Vous avez envoyé un champ hors du schéma | Supprimez-le — le message indique chaque champ en infraction |
400 INVALID_REQUEST — missing required field "prompt" / "image_url" |
Entrée vide ou nom de champ incorrect | Les deux champs sont obligatoires |
La tâche atteint fail après création |
Échec d'exécution — cause fréquente : une URL d'image que le backend ne peut pas récupérer | Le validateur ne récupère pas votre image à la création ; assurez-vous que l'URL est accessible publiquement |
La dernière ligne mérite d'être soulignée : la validation à la création ne porte que sur le schéma. Une image_url mal orthographiée ou privée vous donnera un taskId d'apparence normale et une tâche qui meurt quelques minutes plus tard — alertez donc sur fail, pas seulement sur les erreurs HTTP.
Lectures associées
- Page du modèle hailuo-2.3-fast/image-to-video — aire de jeux et tarification à la seconde
- Workflow de l'API de génération vidéo à partir d'image : guide de production — architecture de traitement par lots, stockage et nouvelles tentatives autour du point de terminaison i2v
- API texte-vers-vidéo vs image-vers-vidéo — quand ancrer la génération sur une image source
- Guide de l'API de génération vidéo à partir d'image Kling — même API de tâches, schéma d'entrée différent, comparaison utile
Questions fréquentes
Puis-je définir la résolution ou le rapport d'aspect ?
Non. Le schéma de hailuo-2.3-fast/image-to-video rejette resolution et aspect_ratio comme champs inconnus. Le format suit votre image source ; si vous avez besoin d'un rapport d'aspect spécifique, recadrez d'abord l'image d'entrée.
Quelles durées sont prises en charge ?
Exactement deux : "6" et "10" secondes, transmises sous forme de chaînes. Toute autre valeur renvoie 400 avec value must be one of '6', '10'.
Puis-je transmettre plusieurs images de référence ?
Non — le champ est une seule chaîne image_url. Les modèles qui acceptent des tableaux d'images (par exemple image_urls de Grok Imagine) utilisent un schéma différent ; ne copiez pas un corps de requête d'un modèle à l'autre sans vérifier.
Comment contrôler le mouvement ?
Uniquement via le prompt — il n'y a pas de paramètre d'intensité de mouvement ni de caméra. Décrivez le mouvement explicitement (« la caméra avance lentement », « les cheveux flottent au vent »). Vous pouvez éventuellement définir "prompt_optimizer": true pour laisser le backend enrichir votre prompt.
Existe-t-il une variante plus lente et de meilleure qualité ?
Oui — hailuo-2.3/image-to-video (sans -fast) est également disponible sur la plateforme, et hailuo-2.3/text-to-video couvre les scénarios sans image source. Vérifiez le schéma de chaque variante avant de basculer ; les champs d'entrée ne sont pas garantis identiques.
Combien cela coûte ? La facturation est calculée sur le nombre de secondes de vidéo générée et varie selon le modèle ; consultez les tarifs actuels sur la page de tarification.
Faut-il une clé API pour essayer ?
Oui — tous les appels à l'API de tâches nécessitent une clé Bearer sk-.... Vous pouvez en créer une dans la console et d'abord tester dans l'aire de jeux de la page du modèle.
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
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