Tutoriel
Comment utiliser l'API image-to-video hailuo 2.3 : curl, Python et un exemple de requête exécutable
Résumé
- De quoi s'agit-il : une recette exécutable pour utiliser l'API hailuo-2.3/image-to-video sur hiapi — transformer une image statique en une courte vidéo : créer une tâche, interroger la tâche, télécharger le
.mp4. - Point de terminaison :
POST https://api.hiapi.ai/v1/tasks, avec"model": "hailuo-2.3/image-to-video"dans le corps de la requête, puis interrogez avecGET /v1/tasks/<taskId>jusqu'à ce que la tâche atteigne un état final. - Deux champs d'entrée obligatoires :
promptetimage_url— une seule URL publique pointant vers votre première image (pas un tableau). durationest une chaîne de caractères, pas un nombre :"6"ou"10". Passer l'entier6sera rejeté avec un 400.- Le schéma est strict. Il n'existe pas de paramètres
motion_strength,camera_movementouresolution— les envoyer sera rejeté avec un 400. Le mouvement est entièrement contrôlé via le prompt.
Ce que vous allez construire, et ce qu'il vous faut préparer
Vous disposez d'une image statique — photo produit, rendu de personnage, photographie — et vous voulez que hailuo-2.3 la mette en mouvement, en générant un clip qui commence exactement sur cette image. hailuo-2.3 est réputé pour son mouvement physiquement crédible (tissus, cheveux, mécanique corporelle), ce qui en fait un excellent choix pour animer des images statiques.
Il vous faut deux choses :
- Une clé d'API hiapi. Créez-en une dans le dashboard. La clé ressemble à
sk-...et se place dans l'en-têteAuthorization: Bearer. - Une URL d'image de première image accessible publiquement. L'API récupère l'image depuis
image_url, elle doit donc être accessible sans authentification — un lien S3/R2/CDN convient ; un cheminlocalhostou une URL signée expirée ne convient pas.
Comme chaque modèle de génération sur hiapi, ce modèle passe par l'interface de tâches asynchrone : vous POSTez une tâche, obtenez immédiatement un taskId, puis récupérez le résultat par interrogation ou par callback. Il n'existe pas de point de terminaison synchrone pour la vidéo — le rendu d'un clip prend du temps et dépasse les délais d'expiration HTTP classiques.
Schéma de la requête
Le schéma d'entrée complet de hailuo-2.3/image-to-video — vérifié contre l'API en production :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
prompt |
string | ✅ | Décrivez le mouvement, pas la scène — la scène provient de votre image. |
image_url |
string | ✅ | Une URL publique, la première image. Au singulier — pas image_urls. |
duration |
string | Facultatif | "6" ou "10" (secondes). Doit être une chaîne de caractères. |
prompt_optimizer |
boolean | Facultatif | Laisse la plateforme enrichir votre prompt avant la génération. |
Le schéma est strict : tout ce qui ne figure pas dans ce tableau sera rejeté. Envoyez motion_strength, camera_movement ou resolution, et vous recevrez ceci tel quel :
{
"code": 400,
"error_code": "INVALID_REQUEST",
"message": "invalid input: <root>: additional properties 'resolution', 'camera_movement', 'motion_strength' not allowed"
}
Deux conséquences à retenir :
- Pas de bouton de réglage du mouvement. La physique du mouvement de hailuo-2.3 est uniquement guidée par le prompt — voir la section sur la rédaction du prompt ci-dessous.
- Aucun contrôle de résolution ni de ratio d'aspect sur ce point de terminaison. Ne construisez pas d'UI pour des paramètres que l'API rejetterait avec un 400.
Exemple minimal exécutable : curl
Créer une tâche :
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "hailuo-2.3/image-to-video",
"input": {
"prompt": "The woman turns toward the camera and smiles; wind gently moves her hair; slow cinematic push-in",
"image_url": "https://your-cdn.example.com/first-frame.jpg",
"duration": "6",
"prompt_optimizer": true
}
}'
La réponse (extrait) contient l'id de tâche sous data.taskId :
{ "data": { "taskId": "..." } }
Interrogez-la :
curl -s https://api.hiapi.ai/v1/tasks/<taskId> \
-H "Authorization: Bearer sk-<your-key>"
Pendant le rendu du clip, data.status signale un état non final. Quand il passe à "success", l'URL de la vidéo se trouve dans data.output[0].url ; s'il passe à "fail", data.error.code et data.error.message en indiquent la raison.
Téléchargez le fichier immédiatement après le succès de la tâche. L'URL de sortie est signée et comporte une expiration (expireAt) — stockez les octets dans votre propre stockage, ne faites jamais de hotlink vers l'URL de la tâche.
Exemple minimal exécutable : Python
Le script complet du même flux — création, interrogation, téléchargement :
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
def create_task() -> str:
payload = {
"model": "hailuo-2.3/image-to-video",
"input": {
"prompt": (
"The cat stretches, hops off the windowsill, and walks toward "
"the camera; soft afternoon light, subtle handheld camera sway"
),
"image_url": "https://your-cdn.example.com/first-frame.jpg",
"duration": "6", # string, not int: "6" or "10"
"prompt_optimizer": True,
},
}
r = requests.post(API_BASE, json=payload, headers=HEADERS, timeout=30)
task_id = (r.json().get("data") or {}).get("taskId")
if not task_id:
raise RuntimeError(f"create failed ({r.status_code}): {r.text[:300]}")
return task_id
def wait_task(task_id: str, timeout_s: int = 900, poll_s: int = 10) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
task = r.json().get("data") or {}
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')}: {err.get('message')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} not finished after {timeout_s}s")
def main() -> None:
task_id = create_task()
print("task created:", task_id)
task = wait_task(task_id)
url = task["output"][0]["url"]
# The URL is signed and expires -- download immediately, store the bytes yourself.
video = requests.get(url, timeout=120).content
with open("hailuo-output.mp4", "wb") as f:
f.write(video)
print("saved hailuo-output.mp4")
if __name__ == "__main__":
main()
Les tâches vidéo s'exécutent nettement plus longtemps que les tâches image, c'est pourquoi le script interroge toutes les 10 secondes et fixe une limite confortable de 15 minutes. N'interrogez pas plus agressivement que toutes les ~5 secondes — cela n'accélérera pas le rendu.
Rédiger des prompts qui contrôlent le mouvement
Comme il n'existe aucun paramètre de mouvement, le prompt est votre seul volant — et pour hailuo-2.3, cela suffit. Trois règles empiriques :
- Décrivez le mouvement, pas l'apparence. Le modèle a déjà vu votre image.
"a beautiful woman in a red dress"gâche le prompt ;"she turns her head slowly to the left as the camera pushes in"l'exploite bien. - Exprimez le mouvement de caméra en langage courant.
"slow push-in","orbit right","handheld sway","static camera"— cela s'écrit dans le texte du prompt, pas dans un champcamera_movement(qui n'existe pas). - En cas de doute, laissez
prompt_optimizervous aider. Avec"prompt_optimizer": true, la plateforme enrichit les prompts courts avant la génération — une bonne valeur par défaut pour les entrées brèves. Désactivez-le lorsque vous voulez respecter strictement une formulation soigneusement rédigée.
Considérations pour la production
Privilégiez les callbacks à l'interrogation. Ajoutez un callback lors de la création de la tâche et hiapi POSTera le résultat final à votre point de terminaison, vous évitant ainsi de maintenir une boucle ouverte :
{
"model": "hailuo-2.3/image-to-video",
"input": { "...": "..." },
"callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
"when": "final" ne se déclenche qu'une fois à l'état final. L'interrogation convient aux scripts et notebooks ; le callback est la forme correcte pour un serveur — le rendu vidéo est suffisamment long pour qu'un worker bloqué en interrogation représente un coût réel.
Gérez explicitement ces erreurs :
401avec"code": "permission_denied"— la clé est incorrecte, ou n'a pas accès à ce modèle. Le message contient unrequest_idque vous pouvez transmettre au support.400 INVALID_REQUEST— violation du schéma. Le message est précis, par exempleduration: got number, want stringouimage_url: missing required field "image_url". Enregistrez-le tel quel.402lors de la création de la tâche — solde insuffisant. Notez que la vidéo coûte plus cher par tâche que l'image, une clé qui exécute encore normalement des tâches image peut donc commencer à échouer sur la création de vidéos. Rechargez, ou vérifiez votre consommation dans le dashboard.- La tâche passe à
"fail"— échec côté génération ; vérifiezdata.error. Une cause fréquente en image-to-video : l'image_urlest inaccessible (bucket privé, URL signée expirée).
Rendez les tentatives idempotentes. Si votre processus meurt entre la création et le téléchargement, un redémarrage naïf créera (et facturera) un second rendu. Persistez le taskId immédiatement après le retour de create_task, et au redémarrage, continuez l'interrogation au lieu de recréer.
Lectures associées
- Page du modèle hailuo-2.3/image-to-video — playground, facturation à la seconde et schéma en temps réel.
- hailuo-2.3-fast/image-to-video — version à faible latence, même workflow de tâches.
- hailuo-2.3/text-to-video — sans image source, génération à partir du prompt uniquement.
- Documentation hiapi — description complète de l'interface de tâches, y compris les callbacks.
- Tarifs — tarifs vidéo actuels à la seconde pour tous les modèles.
Questions fréquentes
Quelles durées l'image-to-video de hailuo-2.3 prend-il en charge ?
Deux : "6" et "10" secondes, passées sous forme de chaînes. Toute autre valeur — ou la même valeur écrite en nombre — renvoie 400 INVALID_REQUEST.
Pourquoi "duration": 6 échoue-t-il alors que "duration": "6" fonctionne ?
Le schéma définit duration comme une énumération de chaînes. L'API vous le dit clairement : duration: got number, want string. C'est le 400 le plus fréquent sur ce point de terminaison.
Puis-je définir la résolution ou le ratio d'aspect de la sortie ?
Non. Le point de terminaison n'expose pas de champ resolution ou aspect_ratio, en envoyer un provoque un 400 — le schéma rejette les propriétés inconnues au lieu de les ignorer.
Comment contrôler le mouvement de caméra ou l'intensité du mouvement ?
Via le prompt. Il n'existe pas de paramètres camera_movement ou motion_strength — écrivez les instructions de caméra et de mouvement en langage courant ("slow push-in", "she walks toward the camera").
Puis-je fournir plusieurs images de référence ?
Non — image_url est une seule chaîne, la première image. Cela diffère d'autres modèles sur hiapi qui acceptent un tableau image_urls ; le schéma est défini par modèle, consultez donc toujours la page du modèle.
Quels formats d'image sont pris en charge pour la première image ? Les formats Web standards (JPEG/PNG), fournis via une URL accessible publiquement. Si la plateforme ne peut pas récupérer l'URL, la tâche échouera après création — vérifiez donc que le lien est accessible publiquement avant de soumettre.
En quoi cela diffère-t-il de hailuo-2.3/text-to-video ?
Le text-to-video invente la scène à partir de votre prompt seul ; l'image-to-video ancre la première image sur votre image et part de là pour animer. Le cycle de vie de la tâche est identique — seul le schéma d'entrée diffère (ici image_url est obligatoire, alors que le text-to-video n'a aucun champ image).
Combien cela coûte-t-il ? La vidéo est facturée à la seconde de sortie, et les tarifs évoluent — consultez la page du modèle hailuo-2.3/image-to-video et la page des tarifs pour les chiffres actuels.
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