HiAPI
Blog

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.

Oct 23, 2026
FLUX 3 Max API: texto a video, imagen a video y fotogramas clave en hiapi

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-video y flux-3-max/keyframes-to-video. Cambiar de modo solo requiere cambiar model y 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.url y when: "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 taskId antes de sondear, para que un fallo del programa no haga perder una tarea ya pagada.
  • Descarga de inmediato. Trata output[0].url como 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 →

Empieza a crear con artefactos de IA persistentes

Consigue tu API key y llama a modelos de imagen, vídeo y audio a través de una única API basada en tasks.

Leer la documentación de la API