Tutorial
Cómo usar veo-3.1-lite/text-to-video a través de la API de hiapi: curl, Python y una solicitud ejecutable
veo-3.1-lite/text-to-video genera clips de vídeo cortos a partir de un único prompt de texto, sin necesidad de una imagen inicial. Esta guía ofrece ejemplos de curl y Python listos para copiar y pegar contra la API real de tareas de hiapi, el esquema de entrada exacto (verificado contra el endpoint en producción) y las formas de error que realmente encontrarás en producción.
1. Requisitos previos
- Una cuenta de hiapi y una API key (
sk-...) obtenida desde el panel de API Keys. - curl, o Python 3 con
requestsinstalado (pip install requests). - No necesitas nada más:
text-to-videosolo requiere una cadena de prompt.
Todos los modelos de generación de hiapi funcionan a través de la misma API unificada de tareas asíncronas: POST /v1/tasks crea la tarea y luego se consulta mediante sondeo o se espera una callback para obtener el resultado. veo-3.1-lite/text-to-video se invoca exactamente igual que cualquier otro modelo de vídeo (mismas cabeceras de autenticación, mismo ciclo de vida de la tarea); solo cambian model e input. El id del modelo es veo-3.1-lite/text-to-video, con el sufijo /text-to-video; la misma familia también ofrece veo-3.1-lite/image-to-video, un id de modelo independiente para animar una imagen de origen en su lugar.
2. Ejemplo mínimo ejecutable
2.1 Crear una tarea (curl)
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-lite/text-to-video",
"input": {
"prompt": "a paper boat drifting down a rain-slicked city street at night, neon signs reflecting on wet asphalt",
"duration": 6,
"resolution": "720p",
"aspect_ratio": "16:9",
"generate_audio": true
}
}'
Una llamada correcta devuelve inmediatamente un id de tarea; la generación es asíncrona:
{"code":200,"data":{"taskId":"tk-hiapi-01XXXXXXXXXXXXXXXXXXXXXXXX"},"message":"success"}
2.2 Consultar el resultado
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01XXXXXXXXXXXXXXXXXXXXXXXX \
-H "Authorization: Bearer sk-<your-api-key>"
Mientras el clip se está renderizando, status es "handling". Cuando termina:
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01XXXXXXXXXXXXXXXXXXXXXXXX",
"model": "veo-3.1-lite/text-to-video",
"status": "success",
"storage": "temp",
"output": [
{"artifactId": "...", "type": "video", "url": "https://temp.hiapi.ai/.../result.mp4", "expireAt": 1786932195}
]
},
"message": "success"
}
output[0].url es un enlace temporal que caduca: descarga el archivo antes de que expire expireAt (o transfiere la salida a un almacenamiento persistente).
2.3 Ejemplo completo en Python
import time
import requests
API_KEY = "sk-<your-api-key>"
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
def create_task(prompt: str) -> str:
resp = requests.post(BASE, headers=HEADERS, json={
"model": "veo-3.1-lite/text-to-video",
"input": {
"prompt": prompt,
"duration": 6,
"resolution": "720p",
"aspect_ratio": "16:9",
},
}, timeout=30)
resp.raise_for_status()
return resp.json()["data"]["taskId"]
def wait_for_result(task_id: str, poll_seconds: int = 5, timeout_seconds: int = 600) -> str:
deadline = time.time() + timeout_seconds
while time.time() < deadline:
resp = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30)
resp.raise_for_status()
data = resp.json()["data"]
if data["status"] == "success":
return data["output"][0]["url"]
if data["status"] == "failed":
raise RuntimeError(f"task {task_id} failed: {data}")
time.sleep(poll_seconds)
raise TimeoutError(f"task {task_id} did not finish in {timeout_seconds}s")
if __name__ == "__main__":
tid = create_task("a paper boat drifting down a rain-slicked city street at night")
video_url = wait_for_result(tid)
print(video_url)
3. Esquema de entrada
Todos los campos siguientes van dentro de input. El esquema es estricto: enviar un campo inexistente devuelve 400 (additional properties '<field>' not allowed), lo que constituye una buena forma de validar rápidamente la solicitud antes del renderizado.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
prompt |
string | Sí | Descripción de la escena; especifica el sujeto, el movimiento y el comportamiento de cámara. |
duration |
integer | No | Uno de 4, 6 u 8 (segundos). |
resolution |
string | No | "720p" o "1080p". |
aspect_ratio |
string | No | "16:9" o "9:16". |
generate_audio |
boolean | No | Incluye audio ambiente/efectos sincronizados en el renderizado. |
negative_prompt |
string | No | Elementos de contenido que el renderizado debe evitar. |
seed |
integer | No | Valor fijo para reproducir la misma composición/movimiento entre reintentos. |
Duraciones más largas y resoluciones más altas aumentan el coste de renderizado; antes de escalar tareas por lotes, consulta la tarifa actual por modelo en la página de precios.
4. Patrones de producción
Prefiere callbacks al sondeo a gran escala
Para cualquier caso que vaya más allá de un script puntual, registra una callback en lugar de sondear en un bucle:
{
"model": "veo-3.1-lite/text-to-video",
"input": {"prompt": "..."},
"callback": {"url": "https://your-app.example.com/webhooks/hiapi", "when": "final"}
}
callback.url debe ser una URL http(s) accesible, y when solo acepta "final": hiapi hará un único POST cuando la tarea alcance un estado terminal (success o failed). Esto evita desperdiciar cuota de solicitudes en bucles de sondeo y obtiene el resultado en el instante en que está listo, algo aún más importante para vídeo (el tiempo de renderizado es mayor que en la generación de imágenes).
Idempotencia y reintentos
Si tu ejecutor de tareas puede reintentar el envío (caídas, timeouts, redespliegues), registra tu propia clave de idempotencia junto con el taskId devuelto antes de realizar la solicitud, de modo que al reintentar puedas comprobar "¿ya envié esto?" en lugar de crear un renderizado duplicado y pagar dos veces por él.
Manejo de errores
En la práctica aparecen dos formas de error distintas:
- Entrada incorrecta (
400): errores de validación del cuerpo de la solicitud:{"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: prompt: missing required field \"prompt\""} - Fallo de autenticación/permisos (
401): clave ausente, inválida o sin permisos suficientes:{"error":{"code":"permission_denied","message":"This API key cannot use the selected model...","request_id":"...","type":"hiapi_error"}}
Ramifica primero según el código de estado HTTP y luego revisa el cuerpo de la respuesta: 400 casi siempre significa un nombre de campo o un valor incorrecto (corrige la solicitud), mientras que 401 significa que la clave en sí requiere atención (permisos en el panel o una nueva clave).
5. Páginas relacionadas
- Página del modelo veo-3.1-lite/text-to-video: precios en tiempo real y un playground en el navegador para probar prompts antes de integrar el código.
- Página del modelo veo-3.1-lite/image-to-video: el modelo hermano condicionado por imagen, para animar material visual existente en lugar de partir de texto.
- Introducción a la API asíncrona unificada: el ciclo de vida de tarea que comparten todos los modelos de hiapi (imagen, vídeo, audio).
- Documentación de autenticación: formato de API key y detalles de las cabeceras de solicitud.
- Guía de la API de seedance-2.5/text-to-video: un segundo modelo de texto a vídeo sobre la misma API de tareas, útil para comparar esquemas y precios.
Preguntas frecuentes
¿veo-3.1-lite/text-to-video necesita una imagen inicial?
No. Genera completamente a partir de la cadena prompt. Si tienes una imagen de origen que quieres animar, usa en su lugar el id de modelo independiente veo-3.1-lite/image-to-video.
¿Qué resoluciones y duraciones se admiten?
resolution es "720p" o "1080p"; duration es 4, 6 u 8 segundos. Enviar cualquier otro valor devuelve 400 con el conjunto de valores permitidos.
¿Los clips generados pueden incluir audio?
Sí: establece "generate_audio": true en input para incluir audio ambiente/efectos sincronizados.
¿Cómo evito sondear en un bucle?
Pasa un objeto callback con la url de tu webhook y "when": "final". hiapi hará un POST a esa URL cuando la tarea finalice, sin que tengas que revisar periódicamente GET /v1/tasks/<id>.
¿Por qué mi solicitud devuelve 401 en lugar de 400?
Un 401 con error_code/code igual a "permission_denied" indica que la API key en sí no es válida o no tiene acceso a ese modelo; revisa el panel de API Keys. Un 400 indica que el cuerpo de la solicitud está mal formado para una clave que sí es válida.
¿La URL del vídeo devuelto es permanente?
No: output[0].url es un enlace temporal con una marca de tiempo expireAt. Descárgalo antes de que caduque o transfiérelo a un almacenamiento persistente.
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