Tutorial
Cómo usar la API de imagen a vídeo de hailuo 2.3 Fast: curl, Python y una solicitud ejecutable
Tienes una imagen estática y quieres convertirla en un vídeo corto. Esta guía te muestra cómo integrarte con hailuo-2.3-fast/image-to-video a través de la API de tareas de hiapi: el esquema de entrada exacto (verificado contra el validador en línea), una solicitud curl lista para copiar, un script completo de Python que sondea hasta que la tarea finaliza, y detalles de producción — callbacks, reintentos idempotentes y las respuestas de error que realmente encontrarás.
Lo que necesitas
- Una clave de API de hiapi — obtenla desde tu consola. La clave tiene la forma
sk-...y se envía en el encabezadoAuthorization: Bearer. - Una imagen de origen alojada en una URL HTTPS accesible públicamente. La API recibe una URL, no un archivo subido.
- Cualquier cliente HTTP. Los ejemplos siguientes usan curl y
requestsde Python.
El precio por segundo de este modelo está publicado en la página de precios.
Esquema de entrada (verificado)
hailuo-2.3-fast/image-to-video usa el endpoint unificado de tareas asíncronas: POST /v1/tasks crea una tarea y GET /v1/tasks/<taskId> la sondea. El esquema de entrada es estricto — los campos desconocidos se rechazan con un 400 en lugar de ignorarse silenciosamente.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
prompt |
string | ✅ | Describe el movimiento que deseas |
image_url |
string | ✅ | Forma singular — una cadena URL, no un arreglo image_urls |
duration |
string | Opcional | "6" o "10" — es una cadena, no un número |
prompt_optimizer |
boolean | Opcional | Deja que el backend reescriba tu prompt para el movimiento |
El validador detecta tres trampas:
durationdebe ser una cadena. Enviar"duration": 6devuelve400con el mensajeduration: got number, want string. Envía"duration": "6".- El campo es
image_urlen singular. Muchos otros modelos de vídeo de la plataforma (Grok Imagine, Kling) reciben un arregloimage_urls. Este modelo recibe una sola cadena. - No hay
resolution,aspect_ratio,seed,watermarkniend_image_url. Todos ellos devuelvenadditional properties ... not allowed. La relación de aspecto de salida sigue a tu imagen de origen; el control del movimiento solo se realiza mediante el prompt.
Solicitud mínima ejecutable: curl
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": "La cámara se acerca lentamente, el vapor se eleva sobre la taza de café, luz suave de la mañana",
"image_url": "https://your-cdn.example.com/coffee.jpg",
"duration": "6"
}
}'
Respuesta exitosa:
{
"code": 200,
"data": { "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V" },
"message": "success"
}
Luego sondea:
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V \
-H "Authorization: Bearer sk-YOUR_KEY"
Mientras el vídeo se renderiza, data.status es "handling":
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V",
"model": "hailuo-2.3-fast/image-to-video",
"status": "handling",
"storage": "temp",
"completed": 0,
"created": 1783648872
},
"message": "success"
}
Los estados terminales son "success" (la URL del vídeo está en data.output[0].url) y "fail" (los detalles están en data.error).
Script completo de Python
import os
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"] # sk-...
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def create_task(prompt: str, image_url: str, duration: str = "6") -> str:
resp = requests.post(
API_BASE,
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": prompt,
"image_url": image_url,
"duration": duration, # cadena: "6" o "10"
},
},
timeout=60,
)
body = resp.json()
if resp.status_code != 200 or not body.get("data", {}).get("taskId"):
raise RuntimeError(f"create failed: {resp.status_code} {body}")
return body["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
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} still running after {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
prompt="El gato parpadea, gira la cabeza hacia la ventana, una brisa le roza el pelaje",
image_url="https://your-cdn.example.com/cat.jpg",
duration="6",
)
print("task:", task_id)
task = wait_task(task_id)
video_url = task["output"][0]["url"]
print("video:", video_url)
# La URL está en almacenamiento temporal con caducidad; descárgala de inmediato, no la enlaces directamente.
mp4 = requests.get(video_url, timeout=120).content
with open("output.mp4", "wb") as f:
f.write(mp4)
print(f"saved output.mp4 ({len(mp4)} bytes)")
Este script hace dos cosas correctamente que las soluciones improvisadas suelen pasar por alto:
- Descarga el vídeo de inmediato.
storage: "temp"significa que la URL de salida tiene caducidad (expireAt). Persiste los bytes en tu propio almacenamiento; nunca guardes en tu base de datos la URL devuelta. - Trata
failcomo terminal. Volver a sondear una tarea fallida no la reanima — crea una tarea nueva.
Consideraciones para producción
Usa callbacks en lugar de sondeo
Para casos de uso fuera de scripts, registra un webhook al crear la tarea y omite por completo el bucle de sondeo:
{
"model": "hailuo-2.3-fast/image-to-video",
"input": { "prompt": "...", "image_url": "https://...", "duration": "6" },
"callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
Con "when": "final", tu endpoint se invoca una vez cuando la tarea alcanza success o fail. Regla general: el sondeo va bien para CLI, tareas por lotes y cualquier escenario transitorio; una vez que tienes un servidor ya escuchando, los callbacks son superiores — las tareas de vídeo tardan minutos, y un bucle de sondeo durante esos minutos es una conexión ocupada y un worker desperdiciado.
Idempotencia
La llamada de creación no es idempotente — cada POST /v1/tasks que pasa la validación crea una nueva tarea (facturada). Si tu ejecutor de tareas reintenta tras un timeout, almacena el taskId obtenido con tu propio id de solicitud como clave antes de procesar el resultado. Al reintentar, si esa clave ya tiene un taskId, sondea ese en lugar de crear una tarea duplicada.
Errores que realmente encontrarás
| Síntoma | Significado | Solución |
|---|---|---|
401 — {"error":{"code":"permission_denied","type":"hiapi_error"}} |
Clave inválida o la clave no puede usar este modelo | Revisa la clave en la consola; la respuesta incluye un request_id para soporte |
400 INVALID_REQUEST — duration: got number, want string |
Se usó un número JSON en lugar de una cadena | "duration": "6" |
400 INVALID_REQUEST — additional properties '...' not allowed |
Enviaste un campo fuera del esquema | Quítalo — el mensaje indica cada campo infractor |
400 INVALID_REQUEST — missing required field "prompt" / "image_url" |
Entrada vacía o nombre de campo incorrecto | Ambos campos son obligatorios |
La tarea llega a fail después de crearse |
Fallo en tiempo de ejecución — causa común: una URL de imagen que el backend no puede obtener | El validador no obtiene tu imagen al crear; asegúrate de que la URL sea accesible públicamente |
Vale la pena enfatizar la última fila: la validación al crear solo comprueba el esquema. Un image_url mal escrito o privado te da un taskId que parece normal y una tarea que muere unos minutos después — así que alerta sobre fail, no solo sobre errores HTTP.
Lecturas relacionadas
- Página del modelo hailuo-2.3-fast/image-to-video — playground y precios por segundo
- Flujo de trabajo de la API de imagen a vídeo: guía de producción — arquitectura de lotes, almacenamiento y reintentos en torno al endpoint i2v
- API de texto a vídeo vs. imagen a vídeo — cuándo conviene anclar la generación a una imagen de origen
- Guía de la API de imagen a vídeo de Kling — la misma API de tareas, distinto esquema de entrada, comparación útil
Preguntas frecuentes
¿Puedo establecer la resolución o la relación de aspecto?
No. El esquema de hailuo-2.3-fast/image-to-video rechaza resolution y aspect_ratio como campos desconocidos. La relación de aspecto sigue a tu imagen de origen; si necesitas una relación específica, recorta primero la imagen de entrada.
¿Qué duraciones se admiten?
Exactamente dos: "6" y "10" segundos, pasadas como cadenas. Cualquier otro valor devuelve 400 con el mensaje value must be one of '6', '10'.
¿Puedo pasar varias imágenes de referencia?
No — el campo es una sola cadena image_url. Los modelos que aceptan arreglos de imágenes (por ejemplo, image_urls de Grok Imagine) usan un esquema distinto; no copies el cuerpo de la solicitud entre modelos sin revisarlo.
¿Cómo controlo el movimiento?
Solo mediante el prompt — no hay parámetros de intensidad de movimiento ni de cámara. Describe el movimiento de forma explícita ("la cámara se acerca lentamente", "el cabello se mece con el viento"). Opcionalmente, establece "prompt_optimizer": true para que el backend amplíe tu prompt.
¿Hay una variante más lenta y de mayor calidad?
Sí — hailuo-2.3/image-to-video (sin -fast) también está disponible en la plataforma, y hailuo-2.3/text-to-video cubre escenarios sin imagen de origen. Revisa el esquema de cada variante antes de cambiar; los campos de entrada no están garantizados como idénticos.
¿Cuánto cuesta? La facturación se calcula por los segundos del vídeo generado y varía según el modelo; consulta las tarifas actuales en la página de precios.
¿Necesito una clave de API para probarlo?
Sí — todas las llamadas a la API de tareas requieren una clave Bearer sk-.... Puedes crear una en la consola y probarla primero en el playground de la página del modelo.
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