HiAPI
Blogue

Tutorial

Como chamar hailuo-2.3/text-to-video pela API HiAPI: curl, Python e exemplos de requisição executáveis

Nov 3, 2026
极简封面图:浅藕紫色与墨黑色两块纯色平面以一道清晰的硬边相接,边缘有一条细紫缝,构图庄重平静。

O que o endpoint hailuo-2.3/text-to-video faz

Se você tem um prompt de texto e quer gerar a partir dele um clipe de vídeo curto, o hailuo-2.3/text-to-video é o endpoint que você procura. Ele recebe um prompt em linguagem natural que descreve a cena, o sujeito e o movimento que você quer ver, e então retorna o clipe gerado. O modelo é ajustado para saídas curtas, portanto rende mais quando você pede um momento compacto e autocontido, em vez de uma narrativa longa.

Na HiAPI, a chamada segue o mesmo padrão de outros endpoints de geração assíncrona: você envia a requisição, o serviço aceita a tarefa e então você faz polling até o resultado ficar pronto. Isso torna o endpoint ideal para pipelines de backend — ferramentas de conteúdo, geradores de protótipos, tarefas em lote ou qualquer cenário que precise obter alguns segundos de vídeo sob demanda, sem alguém sentado manualmente em um editor de vídeo.

A requisição carrega um prompt e alguns parâmetros de controle de geração; a resposta traz um identificador de tarefa, seguido da URL do vídeo finalizado. Você não precisa gerenciar GPUs nem pesos de modelo — a HiAPI cuida da computação e retorna o link de saída. Se você já usou outras APIs de texto para vídeo, o formato geral vai parecer familiar, mas o estilo de prompt do hailuo-2.3 recompensa mais pensar na física do movimento do que apenas na descrição visual (mais detalhes adiante).

Pré-requisitos e credenciais da API

Antes da primeira chamada, garanta que você tem três coisas prontas:

  • Uma chave de API da sua conta HiAPI. Trate-a como senha: não a coloque no controle de versão, carregue-a de variáveis de ambiente e rotacione-a se vazar.
  • Um cliente HTTP. Os exemplos de shell abaixo só precisam de curl. Os exemplos em Python precisam de Python 3.8+ e da biblioteca requests (pip install requests).
  • A URL base da API HiAPI. Todas as requisições vão para o host da API HiAPI, com o caminho do endpoint hailuo-2.3/text-to-video. Você se autentica enviando um bearer token no cabeçalho Authorization.

Defina a chave em uma variável de ambiente, para que ela não apareça no seu código:

export HIAPI_API_KEY="your_api_key_here"

Em Python, você pode lê-la com os.environ["HIAPI_API_KEY"]. No curl, você referencia a mesma variável com $HIAPI_API_KEY.

Há mais uma coisa a decidir com antecedência: onde os vídeos gerados ficarão armazenados. A API retorna a URL da saída, que deve ser buscada e armazenada em seu próprio bucket ou sistema de arquivos prontamente — não construa um pipeline que assuma que essa URL é um ativo permanente.

Requisição executável com curl

Abaixo está uma chamada curl completa para enviar uma tarefa de texto para vídeo. Substitua o prompt pela descrição da sua própria cena. O corpo da requisição é JSON, e os campos principais são o prompt e os parâmetros de geração que controlam a duração e a forma da saída.

curl -X POST "https://api.hiapi.ai/v1/hailuo-2.3/text-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "uma bolinha de gude rola por uma rampa de madeira, ganha velocidade e cai em um piso de pedra, quica duas vezes e para",
    "duration": 6
  }'

Um envio bem-sucedido retorna um objeto JSON contendo um identificador de tarefa. Mais ou menos assim:

{
  "id": "job_abc123",
  "status": "queued"
}

A parte crítica é o id. A geração não é concluída de forma síncrona — o endpoint enfileira a tarefa e retorna imediatamente. Guarde o id; você vai usá-lo para consultar o status e, por fim, obter a URL do vídeo.

Se você receber um erro de autenticação, verifique se a chave foi exportada na mesma sessão de shell. Se receber um erro de validação, verifique se o corpo JSON está bem formado e se o prompt está presente. Uma resposta 429 significa que você enviou requisições rápido demais e deve recuar — a seção de produção detalha isso.

A mesma chamada em Python

A versão em Python faz a mesma coisa, mas encapsulada em uma função reutilizável para você colocar no pipeline. Ela envia a tarefa e retorna o identificador da tarefa.

import os
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def submit_text_to_video(prompt: str, duration: int = 6) -> str:
    """Envia uma tarefa hailuo-2.3/text-to-video e retorna o id da tarefa."""
    api_key = os.environ["HIAPI_API_KEY"]
    response = requests.post(
        f"{HIAPI_BASE}/hailuo-2.3/text-to-video",
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json={"prompt": prompt, "duration": duration},
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()
    return data["id"]


if __name__ == "__main__":
    job_id = submit_text_to_video(
        "uma bolinha de gude rola por uma rampa de madeira, ganha velocidade e cai em um piso de pedra, quica duas vezes e para"
    )
    print("submitted job:", job_id)

Alguns detalhes vale a pena manter:

  • raise_for_status() converte respostas não 2xx em exceções, que é exatamente o comportamento desejado em um pipeline. Falhar alto na fase de envio é melhor do que consultar uma tarefa que nunca foi criada.
  • O timeout da requisição de envio é intencionalmente curto. O envio deve ser rápido; a espera longa acontece na fase de polling, não aqui.
  • O parâmetro duration é um parâmetro separado, para que quem chama possa pedir um clipe mais curto ou mais longo sem duplicar a lógica de montagem da requisição.

Assim que a função retorna, você tem tudo de que precisa para prosseguir com o polling de status.

Escrevendo prompts de física de movimento para clipes de 6 a 10 segundos

Clipes curtos não perdoam. Em seis a dez segundos, você não consegue estabelecer personagens, construir um mundo e concluir um enredo — então os prompts mais eficazes descrevem uma única ação contínua, com consequências físicas claras. Pense no prompt como a descrição de um instante de câmera, não como uma história.

Comece pelo sujeito e pela ação

Comece pelo que se move e pelo que ele está fazendo. "uma bolinha de gude rola por uma rampa de madeira" já dá ao modelo sujeito, material e direção de deslocamento. Uma abertura vaga como "uma cena bonita" não lhe dá nada para animar.

Descreva forças, não apenas aparência

Prompt de física de movimento significa nomear as forças em jogo: gravidade, atrito, momento, peso, elasticidade. Palavras como rolar, acelerar, quicar, parar, balançar, tombar, espirrar e rasgar sugerem um modelo físico. Para objetos que quicam, diga quantas vezes eles quicam e onde finalmente param. Para objetos que caem, diga sobre o que caem e se quebram, amassam ou rebatem.

Mantenha a câmera explícita e simples

Uma câmera fixa ou um único movimento lento de câmera geralmente basta para um clipe curto. Se tanto a câmera quanto o sujeito fazem coisas complexas, o clipe fica confuso e o movimento parece ruído. Especifique o tipo de câmera apenas quando ele importa para a ação — close-up, plano aberto, acompanhamento.

Construa um arco de evento

Um modelo útil para clipes de 6 a 10 segundos é: preparação → ação → consequência. A bolinha está no topo da rampa; ela rola e acelera; cai, quica duas vezes e para. Esse arco dá ao modelo começo, meio e fim, tudo cabendo no comprimento do clipe. Evite pedir várias ações não relacionadas; um evento físico bem descrito lê muito melhor do que três eventos pela metade.

Por fim, mantenha o prompt específico. Materiais, iluminação e textura de superfície ajudam o modelo a fundamentar o movimento — uma bolinha em madeira se comporta diferente de uma em gelo, e dizer isso orienta o resultado.

Tratando tarefas assíncronas com polling

A geração leva tempo, então o endpoint é assíncrono. Após enviar a tarefa, você recebe um id; então faz polling no endpoint de status até a tarefa atingir um estado terminal. Um laço de polling robusto lida com três coisas: intervalo, timeout e exposição de erros.

import time
import requests

HIAPI_BASE = "https://api.hiapi.ai/v1"


def wait_for_video(job_id: str, api_key: str, interval: float = 3.0, max_wait: float = 600.0) -> str:
    """Faz polling até a tarefa concluir e retorna a URL do vídeo de saída."""
    deadline = time.time() + max_wait
    url = f"{HIAPI_BASE}/hailuo-2.3/text-to-video/{job_id}"

    while time.time() < deadline:
        response = requests.get(
            url,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30,
        )
        response.raise_for_status()
        data = response.json()
        status = data.get("status")

        if status == "completed":
            return data["output"]["video_url"]
        if status in ("failed", "cancelled"):
            raise RuntimeError(f"tarefa {job_id} terminou com status {status}: {data.get('error')}")

        time.sleep(interval)

    raise TimeoutError(f"tarefa {job_id} não concluiu em {max_wait} segundos")

Notas sobre esse laço:

  • Faça polling em intervalos, não em laço apertado. Alguns segundos entre verificações bastam e evitam sobrecarregar a API.
  • Sempre limite o tempo total de espera. Uma tarefa travada não deve deixar um worker pendurado para sempre. O valor de max_wait aqui é conservador; ajuste conforme o comprimento do seu clipe e a situação da fila.
  • Trate failed como um ramo real. Exponha o payload de erro em vez de tentar novamente às cegas — problemas de prompt ou parâmetros não se corrigem sozinhos.
  • Retorne a URL do vídeo, não a resposta bruta. Quem chama essa função não deve precisar conhecer a estrutura da resposta.

Para cargas maiores, coloque as etapas de envio e polling em workers diferentes: um worker enfileira as tarefas e armazena os IDs, outro faz o polling e o download. Isso desacopla a latência das requisições do tempo de geração.

Baixando e armazenando a saída

Assim que o polling retornar a URL do vídeo, busque os bytes e grave em um local persistente. Faça isso prontamente: a URL retornada é um link de entrega, não um armazenamento permanente de ativos. Baixe em streaming, em vez de carregar o arquivo inteiro na memória; grave primeiro em um caminho temporário e depois renomeie, para que downloads parciais nunca pareçam arquivos completos.

import os
import tempfile
import requests


def download_video(video_url: str, dest_path: str) -> None:
    """Grava o vídeo concluído em dest_path via streaming, de forma atômica."""
    os.makedirs(os.path.dirname(dest_path) or ".", exist_ok=True)
    with requests.get(video_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(dest_path) or ".")
        try:
            with os.fdopen(fd, "wb") as f:
                for chunk in response.iter_content(chunk_size=1 << 16):
                    f.write(chunk)
            os.replace(tmp_path, dest_path)
        except Exception:
            if os.path.exists(tmp_path):
                os.unlink(tmp_path)
            raise


api_key = os.environ["HIAPI_API_KEY"]
video_url = wait_for_video("job_abc123", api_key)
download_video(video_url, f"out/{'job_abc123'}.mp4")

Algumas escolhas práticas:

  • Nomeie arquivos pelo ID da tarefa. Isso lhe dá uma chave estável e livre de colisões, e torna trivial associar o arquivo de volta à requisição que o produziu.
  • Armazene metadados junto com o vídeo. Guarde o prompt original, a duração e o timestamp em um JSON ou banco de dados associado. Daqui a seis meses, você vai querer saber o que gerou um determinado clipe.
  • Em produção, envie para armazenamento de objetos. Gravar no disco local serve para protótipos; um pipeline real deve enviar arquivos para o seu bucket e registrar a chave do objeto, para que os vídeos sobrevivam a reinícios de workers.

Dicas de produção e modos de falha comuns

A maioria das primeiras integrações tropeça nos mesmos pontos. Aqui está o que observar.

Tente novamente o que é correto

Tente novamente em falhas transitórias — erros de rede, timeouts, respostas 429 e 5xx — usando backoff exponencial com jitter. Não tente novamente em erros de validação 4xx; um prompt malformado ou parâmetro errado falhará da mesma forma todas as vezes. Se a própria tarefa de geração falhar, exponha o erro e decida com prudência se deve reenviar.

Separe envio e polling

Em produção, envio e polling devem ser etapas distintas, geralmente em processos diferentes. Armazene o ID da tarefa em uma fila ou banco de dados imediatamente após o envio bem-sucedido. Se um worker cair, você pode retomar o polling em vez de perder a tarefa.

Defina timeouts em todos os lugares

Requisições de envio, polling de status e download de arquivos devem ter, cada uma, seu próprio timeout. A falta de timeout na etapa de download é a causa clássica de workers pendurados.

Mantenha os prompts dentro da força do modelo

Peça uma única ação fisicamente plausível dentro da faixa de seis a dez segundos. Quando o prompt pede demais, você recebe um clipe confuso com movimento embaralhado. Se a qualidade da saída for inconsistente, encurte o prompt e simplifique a ação antes de considerar mudar parâmetros.

Gerencie credenciais corretamente

Carregue chaves de API de variáveis de ambiente ou de um gerenciador de segredos, nunca de arquivos versionados. Use chaves diferentes por ambiente, para que uma chave de desenvolvimento vazada não alcance a produção.

Cuidado com suposições de expiração de URL

O erro mais comum em produção é tratar a URL de vídeo retornada como um link permanente e renderizá-la diretamente na interface meses depois. Baixe e hospede novamente o arquivo como parte da tarefa, e armazene a sua própria URL.

Com esses hábitos, a integração fica pequena: enviar, consultar, baixar, armazenar.

Artigos relacionados

Ver todos os artigos →

Comece a criar com artefactos de IA persistentes

Obtenha a sua chave de API e chame modelos de imagem, vídeo e áudio através de uma única API baseada em tasks.

Ler a documentação da API