HiAPI
Blog

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.

Oct 23, 2026
API FLUX 3 Max : génération de vidéo à partir de texte, d'image et d'images clés sur hiapi

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-video et flux-3-max/keyframes-to-video. Pour changer de mode, il suffit de modifier model et 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.url et when: "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 taskId avant 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].url comme 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 →

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