Tutorial
FLUX 3 Max API: texto a video, imagen a video y fotogramas clave en hiapi
Tres ID de modelo, un solo flujo /v1/tasks: curl, un script auxiliar en Python, las reglas de la línea de tiempo de fotogramas clave y errores de validación reales.
Resumen
- FLUX 3 Max en hiapi son tres ID de modelo independientes en el mismo endpoint
POST /v1/tasks:flux-3-max/text-to-video,flux-3-max/image-to-videoyflux-3-max/keyframes-to-video. Cambiar de modo solo requiere cambiarmodely un campo de entrada. - Los tres generan clips de 5 a 20 segundos en 720p o 1080p, con facturación por segundos de salida y resolución. Consulta los precios en tiempo real en /en/pricing.
- Las reglas de numeración de fotogramas clave no se comprueban en el momento del envío. Si la línea de tiempo es incorrecta, la API sigue devolviendo HTTP 200 y un
taskId, pero la tarea falla unos 2 segundos después. Valídala primero en local.
Esta guía está orientada al nivel Max. Para el modelo base flux-3, con modo borrador y continuación de video, consulta la guía de la API de video FLUX.3; para editar material existente, consulta edición de video flux-3.
Requisitos previos
Crea una clave en la consola de hiapi y expórtala:
export HIAPI_KEY=sk-your-key
El flujo de solicitud es el mismo en todos los modos: POST /v1/tasks devuelve un taskId, luego se consulta GET /v1/tasks/<taskId> (o se usa un callback) hasta que status sea success, y después se descarga data.output[0].url.
Qué ID de modelo corresponde a cada entrada
| Entrada de la que dispones | ID de modelo | Entrada que hay que cambiar |
|---|---|---|
| Solo un prompt de texto | flux-3-max/text-to-video |
prompt |
| Una imagen fija (opcionalmente con una imagen final) | flux-3-max/image-to-video |
image_url, opcionalmente end_image_url |
| De 1 a 10 imágenes que deben aparecer en momentos concretos | flux-3-max/keyframes-to-video |
keyframes: [{image_url, frame_index}] |
Campos opcionales compartidos por los tres: duration (segundos enteros, 5–20, por defecto 5), resolution (720p o 1080p), aspect_ratio (auto, 21:9, 2:1, 16:9, 4:3, 1:1, 3:4, 9:16), generate_audio (booleano, activado por defecto) y reasoning_level (low o high, por defecto high). Páginas de los modelos: texto a video, imagen a video, fotogramas clave a video.
Ejemplo mínimo: texto a video con 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"
}
}'
Si la solicitud es válida, devuelve {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}. Después:
curl https://api.hiapi.ai/v1/tasks/tk-hiapi-... -H "Authorization: Bearer $HIAPI_KEY"
La configuración con generate_audio desactivado y 5 segundos con razonamiento low es una forma económica de comparar el efecto de los prompts; la página del modelo indica que el audio no cambia el precio.
Un script auxiliar en Python que cubre los tres modos
# 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)
Las URL de salida caducan, así que en cuanto la tarea tenga éxito descarga o copia el archivo de inmediato, en lugar de guardar el enlace.
Fotogramas clave: cómo funciona la línea de tiempo
frame_index es una posición en un reloj de 24 fps que empieza en 0, no un porcentaje. El valor máximo permitido es duration × 24: 120 para 5 segundos, 240 para 10 segundos y 480 para 20 segundos. Los índices deben ser únicos y se pueden enviar de 1 a 10 fotogramas clave. Para lograr una transición limpia de A a B, coloca el primer ancla en 0 y la última en duration × 24; adelantar la última ancla mantiene el final, y retrasarla comprime el cambio. Mantén la misma relación de aspecto en todos los fotogramas clave; si quieres un bucle sin cortes, haz que las imágenes inicial y final parezcan el mismo instante.
Consideraciones para producción
- Sondeo y callbacks. La API de tareas acepta
callback.urlywhen: "final", así evitas el sondeo; consultar cada 10 segundos como en el ejemplo anterior también funciona bien para scripts y tareas por lotes. - Establece siempre un tiempo de espera en el bucle de sondeo y persiste el
taskIdantes de sondear, para que un fallo del programa no haga perder una tarea ya pagada. - Descarga de inmediato. Trata
output[0].urlcomo de validez temporal. - Control de costos. La facturación se calcula por segundos de salida y resolución, así que un clip de 20 segundos en 1080p cuesta varias veces más que una prueba de 5 segundos en 720p. Prototipa primero con 5 segundos y 720p, y aumenta ambos valores cuando el prompt funcione. Consulta las tarifas actuales en la página de precios.
Qué probé y qué no probé
Estas comprobaciones se hicieron el 23 de octubre de 2026 contra la API en producción con una clave de prueba de solo lectura. En este artículo no se renderizó ningún clip completo, por lo que no hago ninguna afirmación sobre la calidad de la salida; los prompts de ejemplo provienen de los ejemplos incluidos en las páginas de los modelos.
Validación síncrona (HTTP 400, no se encola). Los valores fuera de rango se rechazan en el envío, devolviendo error_code: INVALID_REQUEST y un message legible:
| Solicitud | Respuesta message |
|---|---|
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' |
Imagen a video usando image_urls en lugar de image_url |
image_url: missing required field "image_url"; ... additional properties 'image_urls' not allowed |
La última fila es un error habitual: otros modelos de entrada de imagen de hiapi usan el campo en plural, pero FLUX 3 Max imagen a video solo acepta un único image_url. Los campos desconocidos se rechazan en lugar de ignorarse.
Los errores de la línea de tiempo de fotogramas clave son asíncronos. Envié dos solicitudes de fotogramas clave de 5 segundos, ambas con problemas en la línea de tiempo: una con frame_index: 121 (por encima del límite de 120) y otra con dos fotogramas clave en frame_index: 0. Ambas fueron aceptadas, devolviendo HTTP 200 y un taskId. Al consultar entre 1 y 2 segundos después de crearlas, se obtuvo el estado 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"}
De esto se derivan dos conclusiones. Primera, que el envío devuelva 200 no significa que la línea de tiempo sea válida, así que al sondear hay que comprobar status y error.code. Segunda, el mensaje de error es genérico y no indica qué fotograma tiene el problema; por eso conviene ejecutar la comprobación keyframes_ok anterior antes de enviar. La página del modelo indica que las tareas fallidas no se cobran; no comprobé los registros de facturación de estas dos tareas.
Preguntas frecuentes
¿Qué ID de modelo debo usar para un primer fotograma más un fotograma final? Usa flux-3-max/image-to-video y pasa image_url y end_image_url. Recurre a los fotogramas clave solo cuando necesites fijar anclas entre el inicio y el final.
¿Es más caro añadir fotogramas clave? Según la página del modelo, no: la facturación se calcula por segundos de salida y resolución, y el número de anclas no afecta al precio.
¿En qué se diferencia de flux-3? Los flux-3-max/* son ID de modelo independientes, divididos por modo (texto, imagen, fotogramas clave); en cambio, el flux-3 base es un único ID que cambia de modo según la entrada y además admite modo borrador y continuación. Consulta la guía de la API de video FLUX.3. No comparé la calidad de salida de ambos, así que elige según las funciones y las tarifas de la página de precios.
¿Puedo usar otro modelo de imagen a video? Sí. Consulta otras opciones de imagen a video en Cómo usar la API de imagen a video de Ray 3.2.
Artículos relacionados
Ver todos los artículos →-
Tutorial
Cómo llamar a hailuo-2.3-fast/image-to-video a través de la API de HiAPI: práctica con curl y Python
La primera solicitud ejecutable del nivel rápido y de bajo coste de imagen a vídeo: del ID del modelo a la descarga del MP4
-
Tutorial
Cómo llamar a hailuo-2.3/text-to-video mediante la API de HiAPI: curl, Python y ejemplos de solicitud ejecutables
-
Tutorial
Uso de Kandinsky 6.0 Pro texto a video en HiAPI: tutorial con curl y Python
Demostración práctica centrada en la solicitud: construir la llamada de prompt a clip de video, enviar la solicitud, sondear el estado de finalización y descargar el resultado