HiAPI
Blog

Tutorial

Cómo usar la API de imagen a vídeo de Kling 2.5 Turbo (curl + Python)

Un recorrido ejecutable por el primer fotograma a vídeo: crea la tarea, sondea la tarea, descarga el MP4, con el esquema de entrada estricto documentado por completo.

Oct 21, 2026
Cómo usar la API de imagen a vídeo de Kling 2.5 Turbo (curl + Python)

TL;DR

  • kling-2.5-turbo/image-to-video convierte una imagen de primer fotograma en un clip de 5 o 10 segundos; pasar una segunda URL de imagen fija el último fotograma. El modelo se ejecuta en la API de tareas asíncronas de HiAPI: primero POST /v1/tasks para crear la tarea y después sondea GET /v1/tasks/{taskId} para obtener el MP4 generado.
  • El coste de salida es de $0.06 por segundo: un clip de 5 segundos cuesta $0.30 y uno de 10 segundos $0.60. La facturación se calcula por segundo de salida completado; las tareas que fallan por entradas no válidas no generan salida y no se cobran.
  • El esquema de entrada es estricto y cerrado. Obligatorios: image_urls (array, 1–2 elementos — ojo al plural), prompt y duration (solo 5 o 10). Opcionales: aspect_ratio, negative_prompt y cfg_scale. La forma singular image_url se rechaza directamente.
  • El modelo ya está disponible en HiAPI: abre la página del modelo para probarlo en el navegador antes de integrar la API que se describe a continuación.

Qué vas a construir y qué necesitas

Al terminar este artículo tendrás una llamada funcional de primer fotograma → vídeo: enviar la imagen y el prompt de movimiento, sondear la tarea y descargar el MP4. Primero necesitas dos cosas:

  1. Una API Key del panel de HiAPI: cada petición debe enviarse como Authorization: Bearer sk-.... Si aún no has creado una, consulta la documentación de autenticación.
  2. La URL de una imagen de primer fotograma accesible públicamente. La llamada de creación solo comprueba la estructura de la entrada; la imagen se recupera realmente cuando se ejecuta la tarea, así que una URL de localhost o privada creará una tarea que después fallará (ver más abajo).

Esto es imagen a vídeo, así que el id del modelo es kling-2.5-turbo/image-to-video. Si solo quieres generar vídeo a partir de un prompt, hay un endpoint de texto a vídeo independiente.

Ejemplo mínimo ejecutable (curl)

Crea la tarea. El nombre del modelo va en el nivel superior; todo lo que lee el modelo va dentro de input:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-2.5-turbo/image-to-video",
    "input": {
      "prompt": "The perfume bottle rotates slowly on the marble stand, light glints across the glass, petals drift down, slow orbit",
      "image_urls": ["https://static.hiapi.ai/gallery/2026/10/4852c542c4447593.jpg"],
      "duration": 5,
      "aspect_ratio": "9:16"
    }
  }'

Una creación correcta devuelve un id de tarea, no el vídeo:

{ "code": 200, "data": { "taskId": "tk-hiapi-01M5CW..." }, "message": "success" }

Después sondea el endpoint de detalles hasta que status alcance un estado terminal:

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01M5CW... \
  -H "Authorization: Bearer sk-YOUR_KEY"

Mientras la tarea se ejecuta verás estados no terminales; al terminar, la URL del MP4 estará en data.output[0].url:

{
  "code": 200,
  "data": {
    "status": "success",
    "model": "kling-2.5-turbo/image-to-video",
    "storage": "temp",
    "output": [{ "url": "https://temp.hiapi.ai/kling-i2v/tk-hiapi-01M5CW.mp4?expireAt=1761350400" }]
  },
  "message": "success"
}

Esa output[0].url es un enlace temporal: descárgala de inmediato en lugar de enlazarla directamente desde tu aplicación (ver Notas para producción).

Ejemplo mínimo ejecutable (Python)

No hace falta SDK: la API de tareas de HiAPI es una interfaz HTTP pura, así que basta con la biblioteca estándar:

import time
import requests

API = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-YOUR_KEY", "Content-Type": "application/json"}


def create(image_url: str, prompt: str, duration: int = 5) -> str:
    payload = {
        "model": "kling-2.5-turbo/image-to-video",
        "input": {
            "prompt": prompt,
            "image_urls": [image_url],   # 1–2 items; 2nd = last frame
            "duration": duration,        # 5 or 10 only
        },
    }
    r = requests.post(API, json=payload, headers=HEADERS, timeout=60)
    body = r.json()
    task_id = (body.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"create failed: {body}")
    return task_id


def wait(task_id: str, timeout_s: int = 600, interval: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=30)
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(interval)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")


task_id = create(
    "https://static.hiapi.ai/gallery/2026/10/4852c542c4447593.jpg",
    "slow orbit around the product, light glints across the glass, petals drift down",
    duration=5,
)
mp4_url = wait(task_id)

# Download immediately — the URL is short-lived.
with requests.get(mp4_url, stream=True, timeout=120) as resp:
    resp.raise_for_status()
    with open("clip.mp4", "wb") as f:
        for chunk in resp.iter_content(1 << 16):
            f.write(chunk)
print("saved clip.mp4")

Notas para producción

Sondea o usa un callback. Sondear cada 5 segundos (como se muestra arriba) es la vía más sencilla y la que usa el ejemplo. Si prefieres que te envíen los resultados, la llamada de creación acepta un objeto callback en el nivel superior — {"url": "https://you/webhook", "when": "final"} — y HiAPI envía un POST a tu endpoint cuando la tarea alcanza un estado terminal. El contrato exacto del webhook está en la documentación de creación de tareas; para la mayoría de tareas de un solo clip, sondear el endpoint de detalles de tarea es suficiente.

Ramifica siempre según data.status, nunca según el código de estado HTTP de la llamada de creación. Que la creación devuelva 200 significa aceptada, no renderizada. El clip solo existe de verdad cuando el endpoint de detalles devuelve status: "success".

Trata la URL de salida como un enlace temporal. storage es temp y la URL caduca, así que descarga el MP4 en cuanto la tarea tenga éxito (o cópialo a tu propio bucket). No entregues la URL de HiAPI directamente a los usuarios finales.

Control de costes. Pagas por segundo de salida completado — $0.06/segundo — así que un clip de 5 segundos cuesta $0.30 y uno de 10 segundos $0.60. Durante la iteración de prompts y primeros fotogramas, renderiza primero a 5 segundos y vuelve a ejecutar a 10 segundos cuando estés satisfecho. Consulta los precios más recientes en la página de precios.

Notas de pruebas reales y advertencias

Todo lo que sigue procede de peticiones reales al endpoint en producción (esquema revalidado el 2026-10-21), no solo de una tabla de parámetros:

  • El campo es image_urls (plural) y el esquema es cerrado. Enviar el aparentemente natural image_url falla antes de crear la tarea:
    { "code": 400, "error_code": "INVALID_REQUEST",
      "message": "invalid input: image_urls: missing required field \"image_urls\"; <root>: additional properties 'image_url' not allowed" }
    
    Cualquier campo no reconocido (mode, una errata, etc.) se rechaza de la misma forma: no existen campos extra que se ignoren en silencio.
  • duration es una enumeración, no un rango. Solo acepta 5 y 10; 7 devuelve duration: value must be one of 5, 10.
  • image_urls contiene 1 o 2 elementos. Una URL es el primer fotograma; la segunda URL fija el último fotograma para lograr una transición controlada. Tres URL devuelven maxItems: got 3, want 2; un array vacío devuelve minItems: got 0, want 1.
  • Campos opcionales que sí existen: aspect_ratio solo acepta 16:9, 9:16, 1:1, 4:3, 3:4 y 21:9; cfg_scale tiene un máximo de 1 (pasar 99 devuelve cfg_scale: maximum: got 99, want 1); negative_prompt debe ser una cadena. Omitir aspect_ratio permite que el modelo siga tu primer fotograma.
  • La llamada de creación solo valida la estructura, no la accesibilidad: este es el punto más fácil de pasar por alto. Una URL de imagen sintácticamente válida pero inaccesible devuelve 200 y un taskId, y después la tarea pasa asíncronamente a fallida:
    { "data": { "status": "fail",
      "error": { "code": "INVALID_REQUEST",
        "message": "The image URL is not readable. Please provide a valid public HTTP(S) URL or an accessible file path and try again." } } }
    
    Esa tarea no generó output ni se facturó — los fallos no generan coste —, pero si solo compruebas la respuesta de creación creerás que tuvo éxito. Por eso el bucle de sondeo debe basarse en data.status.

Contenido relacionado

Preguntas frecuentes

¿Cuánto puede durar el clip? 5 o 10 segundos: son los únicos dos valores de duration que acepta el esquema.

¿Puedo controlar el final? Sí. Pon dos URL en image_urls: la primera es el fotograma inicial y la segunda el último fotograma. El modelo interpola el movimiento entre ambas.

¿Por qué la creación devuelve 200 pero la tarea muestra fail? La llamada de creación solo comprueba que tu JSON cumpla el esquema. La imagen se recupera cuando se ejecuta la tarea, así que una URL inaccesible o privada crea la tarea y después la hace fallar. Lee siempre data.status desde el endpoint de detalles y asegúrate de que la URL del primer fotograma sea de acceso público.

¿Se cobran las tareas fallidas? No. Se factura por segundo de salida completado, así que una tarea que falla por una entrada no válida no genera output ni se cobra.

¿Hay control de relación de aspecto? aspect_ratio es opcional y acepta 16:9, 9:16, 1:1, 4:3, 3:4 o 21:9. Si lo dejas vacío, se sigue tu primer fotograma.

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