Tutorial
Como usar a API de imagem para vídeo hailuo 2.3 Fast: curl, Python e requisições executáveis
Você tem uma imagem estática e quer transformá-la em um vídeo curto. Este guia integra o modelo hailuo-2.3-fast/image-to-video através da API de tarefas do hiapi: o schema de entrada exato (já verificado contra o validador online), uma requisição curl pronta para copiar, um script Python completo que faz polling até a tarefa concluir, e detalhes de produção — callbacks, retentativas idempotentes e as respostas de erro que você realmente vai encontrar.
O que você precisa preparar
- Uma chave de API hiapi — obtenha no seu console. A chave tem o formato
sk-...e vai no cabeçalhoAuthorization: Bearer. - Uma imagem de origem hospedada em uma URL HTTPS acessível publicamente. A API recebe uma URL, não um arquivo enviado.
- Qualquer cliente HTTP. Os exemplos abaixo usam curl e
requestsdo Python.
O preço por segundo deste modelo está listado na página de preços.
Schema de entrada (verificado)
hailuo-2.3-fast/image-to-video usa o endpoint unificado de tarefas assíncronas: POST /v1/tasks cria a tarefa, GET /v1/tasks/<taskId> consulta a tarefa. O schema de entrada é rigoroso — campos desconhecidos são rejeitados com 400, em vez de serem silenciosamente ignorados.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
prompt |
string | ✅ | Descreve o movimento desejado |
image_url |
string | ✅ | Forma singular — uma string de URL, não um array image_urls |
duration |
string | Opcional | "6" ou "10" — é uma string, não um número |
prompt_optimizer |
boolean | Opcional | Deixa o backend reescrever seu prompt para o movimento |
O validador pega três armadilhas comuns:
durationdeve ser uma string. Enviar"duration": 6retorna400com a mensagemduration: got number, want string. Envie"duration": "6".- O campo é o singular
image_url. Muitos outros modelos de vídeo da plataforma (Grok Imagine, Kling) recebem um arrayimage_urls. Este modelo recebe uma única string. - Não há
resolution,aspect_ratio,seed,watermarknemend_image_url. Todos eles retornamadditional properties ... not allowed. O formato de saída segue sua imagem de origem; o controle de movimento só é possível via prompt.
Requisição mínima executável: curl
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": "A câmera avança lentamente, vapor subindo da xícara de café, luz suave da manhã",
"image_url": "https://your-cdn.example.com/coffee.jpg",
"duration": "6"
}
}'
Resposta de sucesso:
{
"code": 200,
"data": { "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V" },
"message": "success"
}
Depois, faça polling:
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V \
-H "Authorization: Bearer sk-YOUR_KEY"
Enquanto o vídeo renderiza, data.status é "handling":
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V",
"model": "hailuo-2.3-fast/image-to-video",
"status": "handling",
"storage": "temp",
"completed": 0,
"created": 1783648872
},
"message": "success"
}
Os estados terminais são "success" (a URL do vídeo fica em data.output[0].url) e "fail" (detalhes em data.error).
Script Python completo
import os
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"] # sk-...
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def create_task(prompt: str, image_url: str, duration: str = "6") -> str:
resp = requests.post(
API_BASE,
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "hailuo-2.3-fast/image-to-video",
"input": {
"prompt": prompt,
"image_url": image_url,
"duration": duration, # string: "6" ou "10"
},
},
timeout=60,
)
body = resp.json()
if resp.status_code != 200 or not body.get("data", {}).get("taskId"):
raise RuntimeError(f"create failed: {resp.status_code} {body}")
return body["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} still running after {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
prompt="O gato pisca os olhos, vira a cabeça para a janela, uma brisa suave passa pelo seu pelo",
image_url="https://your-cdn.example.com/cat.jpg",
duration="6",
)
print("task:", task_id)
task = wait_task(task_id)
video_url = task["output"][0]["url"]
print("video:", video_url)
# A URL fica em armazenamento temporário com validade — baixe imediatamente, não a use como link direto.
mp4 = requests.get(video_url, timeout=120).content
with open("output.mp4", "wb") as f:
f.write(mp4)
print(f"saved output.mp4 ({len(mp4)} bytes)")
Este script acerta duas coisas que soluções montadas às pressas costumam ignorar:
- Ele baixa o vídeo imediatamente.
storage: "temp"significa que a URL de saída tem validade (expireAt). Persista os bytes no seu próprio armazenamento; nunca guarde a URL retornada no seu banco de dados. - Ele trata
failcomo estado terminal. Consultar novamente uma tarefa com falha não a revive — crie uma nova tarefa.
Considerações para produção
Use callbacks em vez de polling
Para casos de uso além de scripts, registre um webhook ao criar a tarefa e pule completamente o loop de polling:
{
"model": "hailuo-2.3-fast/image-to-video",
"input": { "prompt": "...", "image_url": "https://...", "duration": "6" },
"callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
Com "when": "final", seu endpoint é chamado uma vez quando a tarefa chega a success ou fail. Regra geral: polling é adequado para CLI, tarefas em lote e qualquer cenário efêmero; assim que você tem um servidor já escutando, callbacks são melhores — tarefas de vídeo levam vários minutos, e um loop de polling durante esses minutos é uma conexão ocupada e um worker desperdiçado.
Idempotência
A chamada de criação em si não é idempotente — cada POST /v1/tasks que passa na validação cria uma nova tarefa (cobrada). Se seu executor de tarefas tenta novamente em caso de timeout, armazene o taskId obtido usando como chave o seu próprio id de requisição antes de processar o resultado. Em uma retentativa, se essa chave já tiver um taskId, consulte-o em vez de criar uma tarefa duplicada.
Erros que você realmente vai encontrar
| Sintoma | Significado | Correção |
|---|---|---|
401 — {"error":{"code":"permission_denied","type":"hiapi_error"}} |
Chave inválida, ou a chave não pode usar este modelo | Verifique a chave no console; a resposta inclui um request_id para suporte |
400 INVALID_REQUEST — duration: got number, want string |
Usou um número JSON em vez de uma string | "duration": "6" |
400 INVALID_REQUEST — additional properties '...' not allowed |
Você enviou um campo fora do schema | Remova-o — a mensagem indica cada campo inválido |
400 INVALID_REQUEST — missing required field "prompt" / "image_url" |
Entrada vazia ou nome de campo errado | Os dois campos são obrigatórios |
A tarefa chega a fail após ser criada |
Falha em tempo de execução — causa comum é uma URL de imagem que o backend não consegue buscar | O validador não busca sua imagem na criação; garanta que a URL seja acessível publicamente |
A última linha merece destaque: a validação na criação cobre apenas o schema. Um image_url com erro de digitação ou privado vai te dar um taskId aparentemente normal e uma tarefa que morre alguns minutos depois — então configure alertas para fail, não apenas para erros HTTP.
Leitura relacionada
- Página do modelo hailuo-2.3-fast/image-to-video — playground e preço por segundo
- Fluxo de trabalho da API de imagem para vídeo: guia de produção — arquitetura de processamento em lote, armazenamento e retentativas em torno do endpoint i2v
- API de texto para vídeo vs imagem para vídeo — quando ancorar a geração na imagem de origem
- Guia da API de imagem para vídeo do Kling — a mesma API de tarefas, schema de entrada diferente, comparação útil
Perguntas frequentes
Posso definir resolução ou proporção?
Não. O schema de hailuo-2.3-fast/image-to-video rejeita resolution e aspect_ratio como campos desconhecidos. O formato segue sua imagem de origem; se precisar de uma proporção específica, recorte a imagem de entrada primeiro.
Quais durações são suportadas?
Exatamente duas: "6" e "10" segundos, passadas como string. Qualquer outro valor retorna 400 com a mensagem value must be one of '6', '10'.
Posso enviar várias imagens de referência?
Não — o campo é uma única string image_url. Modelos que aceitam arrays de imagens (por exemplo, image_urls do Grok Imagine) usam um schema diferente; não copie o corpo da requisição entre modelos sem verificar.
Como controlar o movimento?
Apenas pelo prompt — não há parâmetros de intensidade de movimento ou de câmera. Descreva o movimento de forma explícita ("a câmera avança lentamente", "o cabelo balança com o vento"). Opcionalmente, defina "prompt_optimizer": true para que o backend expanda seu prompt.
Existe uma variante mais lenta e de maior qualidade?
Sim — hailuo-2.3/image-to-video (sem o -fast) também está disponível na plataforma, e hailuo-2.3/text-to-video cobre cenários sem imagem de origem. Verifique o schema de cada variante antes de trocar; os campos de entrada não são necessariamente iguais.
Quanto custa? A cobrança é calculada pela quantidade de segundos do vídeo gerado e varia por modelo; confira a tarifa atual na página de preços.
É preciso uma chave de API para testar?
Sim — todas as chamadas da API de tarefas exigem uma chave Bearer sk-.... Você pode criar uma no console e testá-la primeiro no playground da página do modelo.
Artigos relacionados
Ver todos os artigos →-
Tutorial
Como chamar hailuo-2.3-fast/image-to-video pela API HiAPI: curl e Python na prática
A primeira requisição executável do nível rápido e econômico de geração de vídeo a partir de imagem — do ID do modelo ao download do MP4
-
Tutorial
Como chamar hailuo-2.3/text-to-video pela API HiAPI: curl, Python e exemplos de requisição executáveis
-
Tutorial
Usar Kandinsky 6.0 Pro text-to-video na HiAPI: tutorial de curl e Python
Demonstração prática com foco na requisição: montar a chamada de prompt para clipe de vídeo, enviar a requisição, consultar o status de conclusão e baixar o resultado