HiAPI
Blog

Tutorial

Cómo llamar a happyhorse-1.1/image-to-video en la API de hiapi: guía con curl y Python

Nov 3, 2026
hiapi.ai 博客封面图:错位堆叠的骨白纸页与一片锈红内页,扁平几何风格。

Qué hace este endpoint y cuándo usarlo

happyhorse-1.1/image-to-video convierte una sola imagen estática en un vídeo corto. Envías una imagen de primer fotograma a este endpoint y el modelo genera animación a partir de ese fotograma. Lo importante en la práctica es la continuidad: el sujeto, la composición y el aspecto de la imagen inicial se mantienen en el clip generado. Eso es lo que llamamos aquí preservación de identidad: el modelo no crea una escena nueva desde cero basándose solo en un prompt de texto, sino que continúa una escena que ya has creado con una imagen.

Por eso este endpoint encaja cuando la identidad visual importa más que la improvisación:

  • Ya tienes un fotograma de referencia —un retrato, una foto de producto, una hoja de personaje— y quieres un movimiento fiel a ese fotograma.
  • Estás produciendo un corto dentro de un pipeline en el que todos los demás materiales se diseñan primero como imágenes.
  • Necesitas storyboards animados o previsualizaciones de movimiento para fotogramas de guion gráfico.

No es tan adecuado cuando quieres que el modelo reinvente libremente la escena desde cero, o cuando no tienes un fotograma estático que ancle la salida. En esos casos, un flujo de trabajo que prioriza la imagen suele implicar generar primero la imagen de anclaje y luego pasarla a este endpoint.

La llamada en sí es asíncrona: envías una tarea y sondeas hasta que el vídeo esté listo. El resto de esta guía recorre ese ciclo de vida de principio a fin.

Antes de enviar la solicitud

Hay que tener dos cosas listas antes de la primera llamada.

Clave de API

Todas las llamadas pasan por la plataforma hiapi, y la clave de API se adjunta como credencial bearer. Guarda la clave en una variable de entorno en lugar de en el control de código fuente, para que el mismo código funcione tanto en desarrollo local como en CI:

export HIAPI_API_KEY="your_key_here"

En Python, léela en tiempo de ejecución con os.environ["HIAPI_API_KEY"]. Nunca registres el valor bruto de la cabecera.

Una imagen de primer fotograma a la que se pueda hacer referencia

Este endpoint necesita una imagen de inicio. Decide de antemano cómo pasarla: como una URL que la plataforma pueda recuperar, o como un recurso subido o codificado en base64, según lo que admitan tu cuenta y la documentación del endpoint. Lo importante es que la referencia sea estable y accesible en el momento del envío. Si la tarea puede quedar en cola, una URL firmada que caduca en cinco minutos es una mala elección.

También ayuda conocer antes de llamar la relación de aspecto y la duración que esperas en la salida, porque el primer fotograma suele condicionarlas. Tomar esa decisión por adelantado evita tener que reenviar la tarea después.

Con la clave exportada y la referencia de imagen fijada, ya puedes enviar la tarea.

Construir la entrada de primer fotograma

El primer fotograma es el ancla de todo lo que el modelo genere a partir de él. En la práctica, trátalo como un contrato de identidad: cualquier cosa claramente visible en esa imagen —rostros, ropa, logotipos, esquema de color, ángulo de cámara— es algo a lo que el modelo debe ceñirse. Si algún detalle del fotograma está borroso u oculto, la salida también lo estará.

Independientemente de los parámetros concretos del modelo, se aplican estos principios de preparación:

  • Elige un fotograma nítido y bien iluminado. Los artefactos de compresión y el ruido intenso reducen lo que el modelo puede conservar. Una imagen nítida e iluminada de forma uniforme es un mejor anclaje que una imagen llamativa pero borrosa.
  • Coloca al sujeto donde quieres que empiece el movimiento. Recortar y encuadrar en el fotograma estático es más rentable que esperar que el modelo reencuadre.
  • Mantén la relación de aspecto que esperas en la salida. Si el vídeo final es horizontal, prepara una imagen de anclaje horizontal; rellenar después no recuperará la composición perdida.
  • Evita pistas contradictorias. Un fotograma estático que se lee de una manera pero sugiere implícitamente una acción fuera de plano le da al modelo un punto de partida inestable.

No supongas parámetros específicos del modelo que no estén en la documentación del endpoint. El enfoque más seguro es dejar que la propia imagen cargue con la intención y que los campos de la solicitud solo gestionen lo que cubren explícitamente.

Enviar una solicitud funcional con curl

Enviar una tarea es un único POST. La estructura es: enviar una solicitud autenticada al endpoint, con un cuerpo JSON que lleva el identificador del modelo y la entrada de imagen.

curl -sS -X POST "https://api.hiapi.ai/v1/video/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.1/image-to-video",
    "input": {
      "image": "https://your-bucket.example.com/first-frame.jpg"
    }
  }'

Explicación paso a paso:

  1. Endpoint. El destino del POST es la ruta de generación de vídeo de la API de hiapi. Si vas a escribir scripts para varios entornos, ponlo en una variable.
  2. Cabecera de autenticación. Authorization: Bearer $HIAPI_API_KEY: el shell expande la variable de entorno que exportaste antes.
  3. Tipo de contenido. application/json, porque el cuerpo es JSON.
  4. Cuerpo de la solicitud. model selecciona happyhorse-1.1/image-to-video; input.image es tu referencia de primer fotograma. Consulta la documentación de referencia del endpoint para conocer el nombre exacto del campo de imagen y la estructura aceptados en tu cuenta.

Una respuesta correcta no es el vídeo en sí, sino un identificador de tarea. Espera recibir un identificador y un campo de estado, normalmente algo como queued o processing. Anota ese ID; lo usarás para sondear en los pasos siguientes. Ejecuta el comando una vez e imprime la respuesta para ver su estructura antes de empezar a escribir el script.

Enviar la misma solicitud con Python

La versión en Python es una traslación directa, no una integración nueva. La misma ruta, las mismas cabeceras, el mismo cuerpo JSON.

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
URL = "https://api.hiapi.ai/v1/video/generations"

payload = {
    "model": "happyhorse-1.1/image-to-video",
    "input": {
        "image": "https://your-bucket.example.com/first-frame.jpg"
    },
}

resp = requests.post(
    URL,
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=60,
)
resp.raise_for_status()
job = resp.json()
print(job)

Notas sobre la correspondencia:

  • requests con json=payload serializa el diccionario igual que la cadena -d de curl; si usas json=, no establezcas manualmente Content-Type; la biblioteca se encarga de ello. La cabecera explícita de arriba es inofensiva pero redundante.
  • raise_for_status() convierte un fallo de la capa HTTP en una excepción lo antes posible, antes de que empieces a sondear una tarea que no existe.
  • timeout es solo una protección del cliente en la llamada de envío. La generación se ejecuta en el servidor y no se ve afectada por él.

Guarda el payload en una variable y reutilízalo. Cuando más adelante cambies el modelo o la imagen, deberías editar un solo diccionario, no dos implementaciones paralelas.

Gestionar tareas asíncronas y el sondeo

La generación de imagen a vídeo tarda más que un ciclo de solicitud/respuesta. Por eso la API devuelve inmediatamente una referencia de tarea y espera que la consultes más tarde. El ciclo de vida es: enviar, recibir el ID, sondear el estado, obtener el resultado.

Extrae el ID de tarea de la respuesta del envío; el nombre del campo depende del esquema de respuesta documentado de ese endpoint, así que léelo una vez y fija la búsqueda de la clave, no el valor:

job_id = job["id"]  # check the endpoint docs for the exact field

Luego sondea a intervalos:

import time

poll_url = f"https://api.hiapi.ai/v1/video/generations/{job_id}"

while True:
    status = requests.get(
        poll_url,
        headers={"Authorization": f"Bearer {API_KEY}"},
        timeout=30,
    ).json()

    if status["status"] == "succeeded":
        break
    if status["status"] == "failed":
        raise RuntimeError(status)
    time.sleep(5)

Reglas para mantener un sondeo razonable:

  • Sondea a intervalos fijos, no en un bucle apretado. Para tareas de este tamaño, unos segundos entre comprobaciones bastan; martillear el endpoint añade carga pero no hace que el resultado aparezca antes.
  • Limita el tiempo total de espera. Un while True sin límite es un bloqueo que acabará ocurriendo. Lleva la cuenta del tiempo transcurrido y falla de forma ruidosa tras un presupuesto razonable.
  • Gestiona los dos estados terminales. El éxito y el fallo son respuestas. Trata las cadenas de estado desconocidas como no terminales, pero regístralas para que notes cambios en los patrones.
  • No sondees una misma tarea desde varios workers en paralelo. Un sondeador por tarea, o coordina mediante una cola.

Una vez que el estado sea terminal, pasa a descargar el resultado.

Descargar y almacenar la salida

El vídeo terminado se expone como un recurso en la respuesta de la tarea completada, normalmente una URL, a veces con caducidad. El primer paso tras un sondeo correcto es capturar esa referencia y copiar los bytes en un almacenamiento que controles.

video_url = status["output"]["video_url"]  # inspect the real response shape

with requests.get(video_url, stream=True, timeout=120) as r:
    r.raise_for_status()
    with open(f"out/{job_id}.mp4", "wb") as f:
        for chunk in r.iter_content(chunk_size=1 << 20):
            f.write(chunk)

Recomendaciones de almacenamiento aplicables a cualquier pipeline:

  • Copia los artefactos duraderos, no los enlaces. Una URL firmada o con tiempo limitado es un medio de transporte, no almacenamiento. Persiste el archivo y luego guarda tu propia clave de objeto en la base de datos junto con el ID de la tarea.
  • Procesa en streaming los archivos grandes. iter_content mantiene la memoria estable; cargar el vídeo entero en una variable ata el límite de memoria al tamaño del recurso.
  • Registra la procedencia. Guarda el job_id, la referencia de la imagen de entrada y el identificador del modelo junto al recurso. Cuando necesites reproducir el clip, ese registro es la receta.
  • Comprueba el estado HTTP antes de escribir. Una escritura parcial causada por una respuesta de error es peor que un fallo limpio, porque parece un archivo válido.

Una vez que el archivo está en disco o en el almacenamiento de objetos, el pipeline se cierra y puedes pasar al siguiente fotograma.

Errores y trampas a tener en cuenta

La mayoría de los fallos de este endpoint son predecibles. Una lista breve:

  • Entrada de primer fotograma mal formada o inaccesible. La causa más común de rechazo en el envío. Comprueba que la URL de la imagen resuelva desde la red pública, que el formato sea el aceptado por el endpoint y que el payload anide correctamente el campo de imagen. Reproduce con una llamada curl para distinguir problemas de autenticación de problemas de payload.
  • Sondear antes de que exista la tarea. Leer el ID del campo equivocado, o sondear una ruta que no coincide con la respuesta del envío, produce un 404 que parece un fallo de la tarea. Imprime una vez la respuesta del envío y fija la búsqueda de la clave a partir de ella.
  • Espera sin límite. Sin timeout, una tarea atascada bloquea el worker indefinidamente. Establece un presupuesto, falla y alerta.
  • Pérdida del enlace al recurso. La generación tiene éxito, pero la URL se consume una vez y ya no se copia. Guarda los bytes al capturarlos y conserva tus propias claves; no dependas del enlace devuelto como almacenamiento a largo plazo.
  • Fuga de credenciales. Pegar la clave en un notebook y confirmarlo por accidente es un problema recurrente. Cárgala desde el entorno y, ante la duda, rótala.
  • Suponer parámetros no documentados del endpoint. Si necesitas un parámetro que no aparece listado, es que no existe. Expresa la intención solo mediante la imagen de primer fotograma y los campos documentados.

Si gestionas todo esto, el flujo asíncrono se vuelve anodino, que es justo lo que quieres en un pipeline de producción. En cuanto a los nombres de campo específicos del endpoint y los valores aceptados, mantén abierta la documentación de referencia del endpoint mientras construyes.

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