Tutorial
Tutorial de kandinsky-6.0-pro/image-to-video en HiAPI: curl + Python
Realiza una solicitud de imagen a video funcional en HiAPI: desde la carga del primer fotograma hasta el sondeo asíncrono y la descarga final
Visión general del flujo de image-to-video en HiAPI
Cada llamada de imagen a video en HiAPI sigue el mismo ciclo de vida de tres fases. Conocerlo de antemano hace que el resto del tutorial parezca metódico en lugar de misterioso.
Fase 1: enviar la tarea
Envías una solicitud POST al endpoint kandinsky-6.0-pro/image-to-video con la imagen del primer fotograma y un breve prompt que describe el movimiento que esperas. La respuesta no devuelve un flujo de bytes de vídeo; acepta la tarea y devuelve un identificador de tarea: todas las operaciones posteriores dependen de este identificador.
Fase 2: sondear el estado
La generación de vídeo lleva tiempo, por lo que el endpoint es asíncrono. Llamas a la ruta de estado con el identificador de la tarea, y esta informa el estado actual de la tarea: en cola, procesando, exitosa o fallida. Repites la comprobación a intervalos cortos hasta que el estado alcance un estado terminal.
Fase 3: obtener la salida
Una vez que la tarea informa éxito, la carga útil del estado incluye la ubicación del vídeo final. Lo descargas y lo escribes en disco. Ese es todo el contrato.
Por qué importa esta forma
La separación entre envío y sondeo no es casualidad. Significa que tu cliente HTTP no necesita mantener un socket abierto durante todo el renderizado, y también que puedes persistir el identificador de la tarea, irte y retomarla después. Cuando algo falla, el campo de estado te dice dónde falló, lo cual es mucho más útil que un timeout opaco.
Recuerda las tres fases: enviar, sondear, descargar. Los ejemplos de curl y Python a continuación son solo dos formas de escribir la misma secuencia.
Preparar el primer fotograma y las credenciales de la API
Solo hay dos lugares donde suelen surgir problemas antes de la primera llamada: la clave y la imagen. Resuelve ambos ahora y el resto del tutorial irá sobre ruedas.
Configurar la clave de API como variable de entorno
No pegues la clave en el archivo fuente. Expórtala en el shell para que tanto curl como Python puedan obtenerla sin codificar nada de forma rígida:
export HIAPI_API_KEY="your_api_key_here"
En Windows PowerShell, el equivalente es $env:HIAPI_API_KEY="your_api_key_here". Antes de continuar, confirma que el shell puede leerla:
echo "$HIAPI_API_KEY" | head -c 4; echo
Deberías ver los primeros caracteres de la clave. Si no ves nada, la variable no se persistió en la sesión de shell actual; esta es una causa común de respuestas 401 posteriores.
Elegir una imagen de primer fotograma válida
El primer fotograma determina el sujeto, la composición y la relación de aspecto de todo el vídeo. Algunas restricciones prácticas evitan la mayoría de los rechazos:
- Formato: usa un formato de imagen web estándar, como JPEG o PNG. Evita códecs poco comunes, casos límite progresivos o perfiles de color CMYK.
- Accesibilidad: la API necesita leer realmente esos bytes. Si pasas una URL, asegúrate de que sea accesible públicamente o esté correctamente autenticada; si pasas datos en línea, asegúrate de que la codificación esté completa.
- Tamaño: las imágenes de tamaño razonable se validan más rápido. Los archivos extremadamente grandes ralentizan la solicitud y a menudo son la raíz de errores de carga.
- Contenido: elige un fotograma que tenga sentido como punto de partida del movimiento: sujeto claro y fondo sencillo. El prompt de movimiento describe cómo alejarse de este fotograma, por lo que un fotograma desordenado producirá un vídeo desordenado.
Decidir cómo referenciar la imagen
El cuerpo de la solicitud te permite apuntar al primer fotograma mediante una URL o datos codificados en línea. Elige según dónde esté la imagen:
- Si el archivo ya está alojado y es legible públicamente, la URL es la opción más limpia.
- Si la imagen es local o privada, la codificación en línea hace que toda la solicitud sea autocontenida, a costa de una carga útil más grande.
De cualquier manera, mantén la misma forma de variable para la referencia de imagen en curl y Python, para que ambos ejemplos sigan siendo directamente comparables.
Realizar la solicitud con curl
Esta es una solicitud de envío completa. Sustituye tu propia referencia de imagen y prompt y ejecútala.
curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": "https://your-host.example/first-frame.jpg",
"prompt": "slow dolly-in on the subject, gentle ambient motion, stable camera",
"duration": 5,
"aspect_ratio": "16:9"
}'
Qué hace cada parte
- URL apunta específicamente al modelo
kandinsky-6.0-pro/image-to-video. La selección del modelo está en la ruta, no en el cuerpo de la solicitud, así que un error tipográfico aquí dará un 404 en lugar de un mensaje de validación amable. Authorizationlleva el token bearer de la variable de entorno que exportaste. Nada más autentica la llamada.Content-Type: application/jsones importante para cualquier POST con cuerpo JSON; si lo omites, algunos proxies lo estropean antes de que la carga útil llegue a la API.imagees tu referencia al primer fotograma: aquí en forma de URL, o una cadena codificada en línea si la imagen es privada.promptdescribe el movimiento. Mantenlo centrado en el movimiento y el comportamiento de la cámara, no en repetir lo que ya contiene la imagen.durationyaspect_ratiodan forma a la salida. La relación de aspecto debe coincidir con el primer fotograma; una discrepancia provocará recorte o barras negras. La facturación se mide por la salida que generas, así que estos ajustes también determinan tu coste.
Leer la respuesta
Un envío exitoso devuelve la carga útil de la tarea, no el vídeo. Captura el identificador de la tarea: lo pasarás más adelante al endpoint de estado:
curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @body.json | jq -r '.id'
Usar un archivo body.json en lugar de -d en línea mantiene legibles los prompts largos y las imágenes codificadas. jq es opcional, pero convierte la respuesta en una sola línea que puedes pegar directamente en la siguiente llamada.
Llamar al mismo endpoint con Python
La versión en Python es la misma solicitud, el mismo cuerpo, solo envuelta en una función para reutilizarla. Mantén el cuerpo idéntico al de la versión curl: esa es precisamente la razón de mostrar ambos.
import os
import json
import requests
API_BASE = "https://api.hiapi.ai/v1"
ENDPOINT = f"{API_BASE}/kandinsky-6.0-pro/image-to-video"
def submit_video_job(image_ref: str, prompt: str, duration: int = 5, aspect_ratio: str = "16:9") -> str:
"""Submit a first-frame image-to-video job and return the job id."""
api_key = os.environ.get("HIAPI_API_KEY")
if not api_key:
raise RuntimeError("HIAPI_API_KEY is not set in this environment")
body = {
"image": image_ref,
"prompt": prompt,
"duration": duration,
"aspect_ratio": aspect_ratio,
}
response = requests.post(
ENDPOINT,
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json=body,
timeout=60,
)
if response.status_code >= 400:
raise RuntimeError(f"submit failed: {response.status_code} {response.text}")
payload = response.json()
return payload["id"]
if __name__ == "__main__":
job_id = submit_video_job(
image_ref="https://your-host.example/first-frame.jpg",
prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
)
print(json.dumps({"job_id": job_id}, indent=2))
Notas sobre la versión en Python
- Falla rápido si falta la clave. La comprobación explícita del entorno convierte el error más común en un mensaje de error local claro, en lugar de un 401 remoto.
json=bodyfrente adata=json.dumps(body). Pasarjson=hace que requests configure el tipo de contenido por ti, manteniendo las cabeceras mínimas. Si usasdata=, estableceContent-Typeexplícitamente.- Timeout holgado. El envío de vídeo a veces implica transmitir cargas útiles de imagen grandes. Un timeout demasiado corto produce fallos falsos.
- Leer el cuerpo de la respuesta en caso de error. Lanzar tanto el código de estado como el cuerpo de la respuesta significa que el mensaje de error realmente te dice qué rechazó la API.
Si el primer fotograma es un archivo local, léelo, codifícalo en base64 y usa esa cadena para reemplazar image_ref dentro de submit_video_job. La firma de la función no cambia, que es exactamente por lo que ambos estilos de llamada comparten la misma definición de cuerpo de solicitud.
Sondear la tarea y descargar el vídeo
Una tarea enviada no es el vídeo final. Sondea hasta que la tarea alcance un estado terminal y luego descarga.
Bucle de sondeo
import time
import requests
def wait_for_video(job_id: str, interval: float = 10.0, max_wait: float = 600.0) -> str:
"""Poll the job until it finishes; return the output URL."""
import os
api_key = os.environ["HIAPI_API_KEY"]
url = f"https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video/{job_id}"
headers = {"Authorization": f"Bearer {api_key}"}
deadline = time.time() + max_wait
while time.time() < deadline:
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
payload = response.json()
status = payload.get("status")
if status == "succeeded":
return payload["output"]
if status == "failed":
raise RuntimeError(f"job failed: {payload.get('error', 'unknown error')}")
time.sleep(interval)
raise TimeoutError(f"job {job_id} did not finish within {max_wait}s")
Tres detalles hacen que este bucle funcione bien:
- Esperar por intervalos, no confiar en la suerte. Un sueño fijo de unos diez segundos es un punto de partida razonable; no bombardees el endpoint en un bucle ajustado.
- Manejar cada estado terminal.
succeededte da la salida,failedte da el mensaje de error. Ambos deben tratarse como salida. Un bucle que solo comprueba el éxito seguirá girando hasta la fecha límite en una tarea muerta. - Limitar el tiempo de espera.
max_waitgarantiza que el script termine, en lugar de ejecutarse indefinidamente tras una tarea atascada.
Descargar el vídeo final
Una vez que tengas la URL de salida, escribe en disco en streaming en lugar de cargar todo el archivo en memoria:
def download_video(output_url: str, path: str = "result.mp4") -> str:
with requests.get(output_url, stream=True, timeout=120) as response:
response.raise_for_status()
with open(path, "wb") as handle:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
handle.write(chunk)
return path
Combina las partes:
job_id = submit_video_job(
image_ref="https://your-host.example/first-frame.jpg",
prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
)
output_url = wait_for_video(job_id)
saved = download_video(output_url, "kandinsky_result.mp4")
print(f"saved to {saved}")
En producción, persiste el job_id en el momento en que el envío tenga éxito. Si el proceso se reinicia, puedes reanudar el bucle de sondeo con el identificador almacenado, sin pagar por un nuevo envío.
Solucionar errores comunes de solicitud y tarea
La mayoría de los fallos se agrupan en tres categorías: clave, imagen o estado de la tarea. Aísla la categoría antes de cambiar cualquier otra cosa.
Clave rechazada
Síntoma: error de autenticación o autorización antes de crear cualquier tarea.
- Confirma que la variable está realmente exportada en el shell actual:
echo "$HIAPI_API_KEY". - Comprueba si se pegó espacio en blanco o un salto de línea junto con la clave; elimínalos.
- Verifica que la cabecera esté escrita como
Authorization, con un valor que empiece porBearerseguido de un espacio. - Si curl funciona pero Python no, imprime
os.environ.get("HIAPI_API_KEY")desde el mismo intérprete: puede que la variable exista en tu shell pero no en el entorno que hereda el script.
Imagen rechazada
Síntoma: error de validación al enviar, o la tarea falla de inmediato.
- Formato incorrecto o poco común. Vuelve a exportar como JPEG o PNG estándar y reintenta. Los perfiles CMYK y los códecs exóticos son culpables habituales.
- URL inaccesible. Abre la URL de tu imagen en una ventana de navegación privada; si tú no obtienes los bytes, la API tampoco.
- Codificación en línea dañada. Si codificaste en base64 localmente, decodifica la cadena una vez y confirma que es una imagen válida antes de enviarla.
- Relación de aspecto no coincidente. Si el vídeo vuelve recortado o con barras negras, alinea
aspect_ratiocon el primer fotograma en lugar de pelearte con la salida después.
La tarea no termina o falla
Síntoma: el estado se queda en queued/processing, o informa failed.
- Lee el campo error. Las tareas fallidas llevan un mensaje. Normalmente indica el campo o la condición que falló. No adivines: registra toda la carga útil del estado.
- Respeta el diseño asíncrono. Es normal esperar unos segundos antes de comprobar. Un bucle de reintentos ajustado que se rinde a los dos segundos no es un mecanismo de estado.
- Limita el tiempo de espera. Si una tarea supera un límite razonable, trátala como fallida, expón el id de la tarea y envía una nueva, en lugar de sondear para siempre.
- Compara con una llamada que sabes que funciona. Si una imagen personalizada falla, ejecuta el curl exacto de la parte anterior de este tutorial con una imagen pública pequeña y un prompt corto. Si funciona, el problema está en tu entrada; si también falla, el problema está en las credenciales o en la forma de la solicitud.
Errores de descarga tras el éxito
Si la tarea informa succeeded pero la descarga falla, la URL de salida puede haber caducado o estar bajo control de acceso. Vuelve a sondear la tarea para obtener una nueva ubicación de salida, en lugar de reintentar la caducada.
Aborda estas categorías en orden: clave, luego imagen, luego estado de la tarea. Cada error se reduce rápidamente a una causa. Ese es todo el ciclo: enviar el primer fotograma, sondear hasta completar, descargar el resultado.
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