Tutorial
Cómo usar seedance-2.0-fast a través de la API de hiapi: curl, Python y solicitudes ejecutables
Esta guía muestra la solicitud mínima para generar video con seedance-2.0-fast, todos los campos de entrada que el modelo acepta realmente y cómo esperar el resultado mediante sondeo o callback. Cada estructura de solicitud y mensaje de error que aparece a continuación se ha ejecutado y verificado en la API real, por lo que puedes copiar el código directamente.
Qué vas a construir y qué necesitas preparar
El objetivo es solo uno: enviar un prompt de texto y obtener una URL de MP4 descargable. seedance-2.0-fast es la versión optimizada para velocidad de Seedance 2.0: sacrifica la resolución máxima (limitada a 720p) a cambio de una generación más rápida, por lo que es ideal para vistas previas, ciclos de iteración y grandes lotes de clips cortos.
Solo necesitas una cosa: una clave de API de hiapi. Obténla desde tu panel de control; su formato es similar a sk-.... Todos los modelos de video (incluido este) se sirven a través del endpoint unificado de tareas asíncronas: primero haces POST /v1/tasks para crear una tarea y luego obtienes el resultado mediante el id de la tarea. No hay modo síncrono para video.
Consulta el precio actual por clip en la página de precios (el modelo acaba de lanzarse, así que guíate por esa página y no te fíes de ninguna cifra que aparezca en artículos de blog).
Ejemplo mínimo ejecutable (curl)
Crear la tarea:
curl -X POST "https://api.hiapi.ai/v1/tasks" \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0-fast",
"input": {
"prompt": "A paper boat drifts down a rain-soaked street at dusk, cinematic, slow dolly-in",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9"
}
}'
El id de la tarea en la respuesta se encuentra en data.taskId:
{
"data": {
"taskId": "task_abc123..."
}
}
Sondea la tarea hasta que su estado sea terminal:
curl "https://api.hiapi.ai/v1/tasks/task_abc123..." \
-H "Authorization: Bearer sk-YOUR_KEY"
Cuando data.status sea "success", la URL del video estará en data.output[0].url. Esa URL está firmada y caduca; descarga el archivo de inmediato y no la enlaces en caliente:
curl -o clip.mp4 "<the output url>"
Todos los campos de entrada (verificados)
Solo prompt es obligatorio. Cualquier campo que no aparezca en esta tabla se rechazará con 400: el esquema no permite propiedades adicionales.
| Campo | Tipo | Obligatorio | Valores aceptados |
|---|---|---|---|
prompt |
string | Sí | Longitud mínima de 3 caracteres |
duration |
entero | No | 4–15 (segundos) |
resolution |
string | No | 480p, 720p |
aspect_ratio |
string | No | 1:1, 4:3, 3:4, 16:9, 9:16, 21:9, adaptive |
Hay dos puntos que merecen especial atención:
durationes un entero, no una cadena. Enviar"duration": "5"fallará la validación con el errorduration: got string, want integer.- No hay entrada de imagen.
seedance-2.0-fastsolo admite texto a video; campos comoimage_urlsserán rechazados por el esquema. Si necesitas imagen a video, consulta la guía del flujo de trabajo de la API de imagen a video para conocer los modelos que admiten esa función.
El mismo flujo en Python
No se necesita SDK: requests es suficiente:
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {
"Authorization": "Bearer sk-YOUR_KEY",
"Content-Type": "application/json",
}
def create_task(prompt: str, duration: int = 5,
resolution: str = "720p", aspect_ratio: str = "16:9") -> str:
payload = {
"model": "seedance-2.0-fast",
"input": {
"prompt": prompt,
"duration": duration,
"resolution": resolution,
"aspect_ratio": aspect_ratio,
},
}
r = requests.post(API_BASE, json=payload, headers=HEADERS, timeout=60)
r.raise_for_status()
return r.json()["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_interval: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
r.raise_for_status()
task = r.json()["data"]
if task["status"] == "success":
return task
if task["status"] == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')}: {err.get('message')}")
time.sleep(poll_interval)
raise TimeoutError(f"task {task_id} still running after {timeout_s}s")
task_id = create_task(
"A barista pours latte art in a sunlit cafe, shallow depth of field"
)
task = wait_task(task_id)
video_url = task["output"][0]["url"]
# The URL is signed and expires — persist the bytes immediately.
with open("clip.mp4", "wb") as f:
f.write(requests.get(video_url, timeout=120).content)
print("saved clip.mp4")
Trata cualquier estado distinto de success / fail como "aún en ejecución"; así el bucle seguirá siendo robusto aunque los nombres de los estados intermedios cambien en el futuro.
Consideraciones para producción
Usar callback en lugar de sondeo
Para cualquier escenario que vaya más allá de un script, registra un callback al crear la tarea y omite por completo el sondeo:
{
"model": "seedance-2.0-fast",
"input": { "prompt": "..." },
"callback": { "url": "https://your-app.com/hooks/hiapi", "when": "final" }
}
Con "when": "final", tu endpoint recibirá exactamente un POST cuando la tarea alcance un estado terminal. El sondeo es útil para CLI y notebooks; cuando ejecutas a gran escala, los callbacks son superiores (sin solicitudes desperdiciadas ni latencia por el intervalo de sondeo). Si tu hook parece no dispararse, consulta la guía de solución de problemas de callbacks: casi siempre es un problema de accesibilidad de la URL o que tu manejador devolvió una respuesta que no es 2xx.
Idempotencia
Crear tareas no es gratuito, así que evita envíos duplicados por tu parte: haz que cada evento de negocio corresponda como máximo a una llamada a POST /v1/tasks (por ejemplo, almacenando el taskId asociado a tu fila de pedido/tarea antes de reintentar). Si tu proceso se cae después de crear la tarea, puedes recuperarte volviendo a leer el taskId almacenado y reanudando con GET /v1/tasks/<id>; la tarea sigue ejecutándose en el servidor tanto si sondeas como si no.
Errores que realmente encontrarás
| Síntoma | Significado | Solución |
|---|---|---|
400 con error_code: "INVALID_REQUEST" |
La entrada no pasó la validación del esquema; message indicará el campo concreto, por ejemplo duration: maximum: got 20, want 15 |
Corrige ese campo; solo se permiten los cuatro campos de la tabla anterior |
401 con error.code: "permission_denied" |
La clave no es válida, o es válida pero no está habilitada para este modelo | Revisa la clave en el panel de control; los permisos de modelo se configuran por clave |
404 con "task not found" en el GET |
El id de tarea es incorrecto o no pertenece a esa cuenta | Usa el taskId devuelto al crear la tarea y de la misma cuenta |
Estado de la tarea "fail" con un objeto error |
La generación en sí falló | Lee error.code/error.message; ajusta el prompt y vuelve a intentarlo |
Ojo con los dos tipos de envoltura de error: los errores de validación colocan message en el nivel superior, mientras que los errores de autenticación van anidados bajo error. Si escribes middleware genérico, necesitarás manejar ambos casos.
Cuándo usar seedance-2.0-fast
Si necesitas salida en 1080p o 4K, usa el seedance-2.0 completo: mismo endpoint, mismo flujo, mayor límite de resolución (y requiere especificar aspect_ratio de forma explícita). Para una visión más completa de cómo se compara la familia Seedance con otros modelos de video de la plataforma, consulta la comparativa de modelos de video. La referencia completa de parámetros de cada modelo está en la documentación, y la página del modelo mantiene actualizadas sus capacidades y estado de precios.
Preguntas frecuentes
¿Qué resoluciones admite seedance-2.0-fast?
480p y 720p. Ese es el precio que se paga por la velocidad: el seedance-2.0 completo alcanza hasta 1080p y 4k con el mismo flujo de /v1/tasks.
¿Puedo hacer imagen a video con seedance-2.0-fast?
No. El esquema de entrada solo acepta prompt, duration, resolution y aspect_ratio; los campos de imagen se rechazan con un error de validación. Para conocer las opciones de imagen a video en hiapi, consulta la guía del flujo de trabajo de imagen a video.
¿Cuánto puede durar el video generado?
duration acepta enteros de 4 a 15 segundos. Los valores fuera de ese rango fallan la validación antes de crear la tarea (las solicitudes rechazadas no se facturan).
¿Debo usar sondeo o callback?
Para scripts y volúmenes bajos, sondear cada ~5 segundos es suficiente. A escala de producción, pasa callback: {"url": ..., "when": "final"} al crear la tarea y deja que hiapi te envíe el estado terminal: una sola solicitud en lugar de decenas.
¿Por qué una clave que funciona con otros modelos aquí devuelve 401 permission_denied?
El acceso a los modelos está limitado por clave. Un 401 con permission_denied en este modelo significa que la clave existe pero no está habilitada para seedance-2.0-fast; revisa los permisos de modelo de esa clave en el panel de control.
¿Cuánto dura la validez de la URL de salida? Es una URL firmada y caduca. Descarga el MP4 en cuanto la tarea tenga éxito y guárdalo por tu cuenta; no incrustes la URL de salida original en ningún lugar de larga duración.
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