Tutoriel
API FLUX 3 Max : génération de vidéo à partir de texte, d'image et d'images clés sur hiapi
Trois identifiants de modèle, un seul flux /v1/tasks : curl, script Python d'assistance, règles de chronologie des images clés et erreurs de validation réelles.
Résumé
- FLUX 3 Max sur hiapi correspond à trois identifiants de modèle distincts sur le même point de terminaison
POST /v1/tasks:flux-3-max/text-to-video,flux-3-max/image-to-videoetflux-3-max/keyframes-to-video. Pour changer de mode, il suffit de modifiermodelet un champ d'entrée. - Les trois génèrent des clips de 5 à 20 secondes en 720p ou 1080p, facturés à la seconde de sortie et selon la résolution. Consultez les tarifs en temps réel sur /en/pricing.
- Les règles de numérotation des images clés ne sont pas vérifiées à la soumission. Si la chronologie est erronée, l'API renvoie tout de même un HTTP 200 et un
taskId, mais la tâche échoue au bout d'environ 2 secondes. Validez donc localement au préalable.
Ce guide concerne le niveau Max. Pour le modèle flux-3 de base avec mode brouillon et prolongation vidéo, voir le guide de l'API vidéo FLUX.3 ; pour l'édition de contenus existants, voir édition vidéo flux-3.
Prérequis
Créez une clé dans la console hiapi et exportez-la :
export HIAPI_KEY=sk-your-key
Le flux de requête est identique pour tous les modes : POST /v1/tasks renvoie un taskId, puis interrogez GET /v1/tasks/<taskId> (ou utilisez un callback) jusqu'à ce que status vaille success, puis téléchargez data.output[0].url.
Quel identifiant de modèle pour quelle entrée
| Entrée dont vous disposez | Identifiant de modèle | Entrée à modifier |
|---|---|---|
| Uniquement un prompt textuel | flux-3-max/text-to-video |
prompt |
| Une image fixe (éventuellement plus une image de fin) | flux-3-max/image-to-video |
image_url, éventuellement end_image_url |
| 1 à 10 images devant apparaître à des instants précis | flux-3-max/keyframes-to-video |
keyframes: [{image_url, frame_index}] |
Champs optionnels communs aux trois : duration (secondes entières, 5–20, par défaut 5), resolution (720p ou 1080p), aspect_ratio (auto, 21:9, 2:1, 16:9, 4:3, 1:1, 3:4, 9:16), generate_audio (booléen, activé par défaut) et reasoning_level (low ou high, par défaut high). Pages des modèles : texte vers vidéo, image vers vidéo, images clés vers vidéo.
Exemple minimal : texte vers vidéo avec curl
curl -X POST "https://api.hiapi.ai/v1/tasks" \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-3-max/text-to-video",
"input": {
"prompt": "a slow aerial shot of ocean waves at sunrise, photorealistic",
"duration": 5,
"resolution": "720p",
"generate_audio": false,
"reasoning_level": "low"
}
}'
Lorsque la requête est valide, elle renvoie {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}. Ensuite :
curl https://api.hiapi.ai/v1/tasks/tk-hiapi-... -H "Authorization: Bearer $HIAPI_KEY"
La configuration generate_audio désactivé avec 5 secondes et un raisonnement low est un moyen économique de tester un prompt ; la page du modèle indique que l'audio ne modifie pas le prix.
Un script Python d'assistance couvrant les trois modes
# pip install requests
import os, time, requests
KEY = os.environ["HIAPI_KEY"]
H = {"Authorization": f"Bearer {KEY}"}
BASE = "https://api.hiapi.ai/v1/tasks"
def submit(mode: str, **inp) -> str:
"""mode: text-to-video | image-to-video | keyframes-to-video"""
body = {"model": f"flux-3-max/{mode}", "input": inp}
res = requests.post(BASE, json=body, headers=H, timeout=30).json()
if res.get("code") != 200:
# sync 400s look like {"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: ..."}
raise RuntimeError(res)
return res["data"]["taskId"]
def wait(task_id: str, timeout_s: int = 900, every: int = 10) -> str:
deadline = time.time() + timeout_s
while time.time() < deadline:
d = requests.get(f"{BASE}/{task_id}", headers=H, timeout=30).json()["data"]
if d["status"] == "success":
return d["output"][0]["url"]
if d["status"] == "fail":
raise RuntimeError(d.get("error"))
time.sleep(every)
raise TimeoutError(task_id)
# 1) text-to-video
t2v = submit("text-to-video",
prompt="A single white sneaker rotates slowly on a wet black plinth, studio softbox lighting, macro product shot",
duration=5, resolution="720p", aspect_ratio="16:9", generate_audio=False)
# 2) image-to-video: first frame, optional last frame
i2v = submit("image-to-video",
prompt="Morning mist drifts over the harbor; the boats rock gently and the camera slowly pushes forward.",
image_url="https://example.com/harbor.jpg",
# end_image_url="https://example.com/harbor-end.jpg", # optional fixed ending
duration=5, resolution="720p", generate_audio=False)
# 3) keyframes-to-video
FPS = 24
def keyframes_ok(duration: int, frames: list[dict]) -> None:
idx = [f["frame_index"] for f in frames]
assert 1 <= len(frames) <= 10, "1-10 keyframes"
assert len(set(idx)) == len(idx), "frame_index must be unique"
assert all(0 <= i <= duration * FPS for i in idx), f"frame_index must be 0..{duration * FPS}"
frames = [
{"image_url": "https://example.com/harbor.jpg", "frame_index": 0},
{"image_url": "https://example.com/latte.jpg", "frame_index": 120},
]
keyframes_ok(5, frames)
kf = submit("keyframes-to-video",
prompt="A continuous cinematic morph from the misty harbor into a close-up of an iced matcha latte.",
keyframes=frames, duration=5, resolution="720p", generate_audio=False)
url = wait(kf)
open("clip.mp4", "wb").write(requests.get(url).content)
Les URL de sortie expirent : téléchargez ou copiez donc le fichier immédiatement après le succès de la tâche, plutôt que de conserver le lien.
Images clés : fonctionnement de la chronologie
frame_index est une position sur une horloge à 24 fps commençant à 0, et non un pourcentage. La valeur maximale autorisée est duration × 24 : 120 pour 5 secondes, 240 pour 10 secondes, 480 pour 20 secondes. Les index doivent être uniques ; vous pouvez fournir de 1 à 10 images clés. Pour une transition propre de A à B, placez le premier point d'ancrage à 0 et le dernier à duration × 24 ; avancer le dernier ancrage fige la fin, le reculer compresse la transformation. Conservez le même rapport d'aspect pour toutes les images clés ; pour une boucle sans raccord, faites en sorte que les images de début et de fin évoquent le même instant.
Considérations pour la production
- Interrogation ou callback. L'API de tâches accepte
callback.urletwhen: "final", ce qui évite d'interroger en boucle ; une interrogation toutes les 10 secondes comme ci-dessus convient aussi pour les scripts et les tâches par lots. - Définissez toujours un délai d'expiration pour la boucle d'interrogation, et persistez le
taskIdavant l'interrogation, afin qu'un plantage ne fasse pas perdre une tâche déjà facturée. - Téléchargez immédiatement. Considérez
output[0].urlcomme valide à court terme. - Maîtrise des coûts. La facturation se fait à la seconde de sortie et selon la résolution : un clip de 20 secondes en 1080p coûte donc plusieurs fois le prix d'un test de 5 secondes en 720p. Prototypez d'abord en 5 secondes et 720p, puis augmentez les deux une fois le prompt validé. Les tarifs actuels figurent sur la page des tarifs.
Ce que j'ai testé et ce que je n'ai pas testé
Ces vérifications ont été effectuées le 23 octobre 2026 sur l'API en production avec une clé de test en lecture seule. Cet article ne rend pas de clips complets ; je ne fais donc aucune affirmation sur la qualité des sorties ; les prompts d'exemple proviennent des exemples fournis sur les pages des modèles.
Validation synchrone (HTTP 400, non mise en file). Les valeurs hors limites sont rejetées dès la soumission, avec error_code: INVALID_REQUEST et un message lisible :
| Requête | message de réponse |
|---|---|
duration: 3 |
invalid input: duration: minimum: got 3, want 5 |
resolution: "4k" |
value must be one of '720p', '1080p' |
aspect_ratio: "5:4" |
value must be one of 'auto', '21:9', '2:1', '16:9', '4:3', '1:1', '3:4', '9:16' |
reasoning_level: "medium" |
value must be one of 'low', 'high' |
Image vers vidéo avec image_urls au lieu de image_url |
image_url: missing required field "image_url"; ... additional properties 'image_urls' not allowed |
La dernière ligne est une erreur courante : d'autres modèles à entrée image sur hiapi utilisent un champ au pluriel, mais l'image vers vidéo de FLUX 3 Max n'accepte qu'un seul image_url. Les champs inconnus sont rejetés, et non ignorés.
Les erreurs de chronologie des images clés sont asynchrones. J'ai soumis deux requêtes de 5 secondes avec images clés, toutes deux problématiques sur le plan de la chronologie : l'une utilisait frame_index: 121 (au-delà de la limite de 120), l'autre avait deux images clés à frame_index: 0. Les deux ont été acceptées, renvoyant un HTTP 200 et un taskId. Environ 1 à 2 secondes après la création, l'interrogation renvoie l'état final :
{"code":200,"data":{"status":"fail","model":"flux-3-max/keyframes-to-video",
"error":{"code":"INVALID_REQUEST","message":"Invalid request parameters for this model. Please check the request and try again."},
"taskId":"tk-hiapi-..."},"message":"success"}
Deux conclusions s'imposent. Premièrement, un HTTP 200 à la soumission ne signifie pas que la chronologie est valide : vérifiez donc status et error.code lors de l'interrogation. Deuxièmement, le message d'échec est générique et n'indique pas quelle image pose problème ; c'est pourquoi la vérification keyframes_ok ci-dessus mérite d'être exécutée avant la soumission. La page du modèle indique que les tâches en échec ne sont pas facturées ; je n'ai pas vérifié les relevés de facturation de ces deux tâches.
Questions fréquentes
Quel identifiant de modèle utiliser pour une première et une dernière image ? Utilisez flux-3-max/image-to-video et passez image_url et end_image_url. N'utilisez les images clés que si vous devez placer des ancrages entre le début et la fin.
Ajouter des images clés coûte-t-il plus cher ? Selon la page du modèle, non : la facturation se fait à la seconde de sortie et selon la résolution, et le nombre d'ancrages n'influence pas le prix.
Quelle différence avec flux-3 ? flux-3-max/* regroupe des identifiants de modèle distincts, séparés par mode (texte, image, images clés) ; le flux-3 de base est un seul identifiant qui change de mode selon l'entrée et prend aussi en charge le mode brouillon et la prolongation. Voir le guide de l'API vidéo FLUX.3. Je n'ai pas comparé la qualité des sorties des deux, choisissez donc selon les fonctionnalités et les tarifs de la page des tarifs.
Puis-je utiliser un autre modèle image vers vidéo ? Oui. Pour d'autres solutions image vers vidéo, voir Comment utiliser l'API image vers vidéo Ray 3.2.
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