Tutorial
Como usar o omnihuman-1.5 através da API HiAPI: tutorial com curl e Python
Demonstração completa de requisição para geração de vídeo de avatar a partir de áudio, polling assíncrono e download da saída
Funcionalidades e cenários de aplicação da API omnihuman-1.5
O omnihuman-1.5 converte um trecho de áudio e uma imagem de retrato em um vídeo de avatar falante: o rosto na imagem é animado para que os movimentos da boca e da cabeça acompanhem a fala fornecida. Na HiAPI, o modelo é disponibilizado como endpoint áudio para vídeo — você envia o áudio, uma imagem de referência e alguns parâmetros de geração, a API retorna uma tarefa, e você consulta essa tarefa para obter o vídeo final.
Vantagens da API em relação a ferramentas manuais
Ferramentas de navegador são adequadas para edições pontuais. Quando a geração de vídeo é uma etapa de um sistema maior, a API é a escolha certa:
- Pipelines em lote — gerar grandes quantidades de clipes de avatar a partir de filas de scripts e faixas de áudio, sem intervenção manual.
- Funcionalidades de produto — narração em aplicativos, vídeos de integração localizados ou mensagens personalizadas, usando áudios diferentes e retratos diferentes a cada renderização.
- Automação de backend — fluxos de trabalho de conteúdo que geram vídeo e o encaminham para um CMS, bucket de armazenamento ou serviço de entrega.
Estrutura da requisição
Toda chamada ao omnihuman-1.5 na HiAPI segue o mesmo formato: um POST envia a tarefa, e requisições subsequentes verificam seu status. Como a renderização não é instantânea, o padrão de integração é enviar → consultar → baixar, e não enviar → receber o vídeo na mesma resposta. O restante deste tutorial constrói esse fluxo primeiro com curl e depois com Python.
Pré-requisitos e suas credenciais HiAPI
Antes da primeira chamada, confirme três coisas.
1. Conta e chave de API
Você precisa de uma conta HiAPI e de uma chave de API criada no console. Trate a chave como confidencial: não a coloque em controle de versão, código de cliente ou logs. Em desenvolvimento, carregue-a de variáveis de ambiente; em produção, do gerenciador de segredos da plataforma.
export HIAPI_API_KEY="your-api-key-here"
2. Acesso à rede e ferramentas de requisição
Com curl, qualquer shell razoavelmente recente serve. Para a versão em Python, basta a biblioteca requests — nenhum SDK específico de fornecedor é necessário, pois a API é HTTPS simples baseada em corpo JSON.
pip install requests
3. Entradas exigidas pelo modelo
Prepare os itens a seguir antes de escrever a requisição:
- Áudio — a faixa de voz que anima os movimentos da boca, fornecida como URL ou referência de arquivo já enviado, dependendo do formato de entrada aceito pelo endpoint.
- Imagem de retrato — o rosto a ser animado. Fotos nítidas, frontais e com a boca visível produzem os resultados mais previsíveis.
- Parâmetros de geração — quaisquer opções de resolução, duração ou qualidade expostas pelo modelo. Envie apenas os campos que você realmente precisa; nos primeiros testes os valores padrão geralmente são adequados.
Cada requisição transmite a chave no cabeçalho Authorization no formato Bearer <your-key>. Se a primeira chamada retornar 401, verifique esse cabeçalho primeiro.
Fazendo a requisição com curl
A chamada de envio é um POST com corpo JSON. O caminho exato e os nomes de campo do omnihuman-1.5 estão na página de referência da API do modelo; a estrutura abaixo mostra o formato da chamada e os campos que você preencherá.
curl -X POST "https://api.hiapi.ai/v1/omnihuman-1.5/generate" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://your-bucket.example.com/speech.mp3",
"image_url": "https://your-bucket.example.com/portrait.jpg"
}'
Explicação campo a campo
Authorization— transporta a chave de API. Sem ele, a requisição é rejeitada antes de qualquer trabalho começar.Content-Type: application/json— o corpo é JSON; omitir este cabeçalho é uma causa comum de erros de validação confusos.audio_url— a faixa de voz. Use uma URL publicamente legível ou de outra forma acessível pela API, e prefira locais estáveis a links assinados que expiram no meio da renderização.image_url— o retrato a ser animado. Aplicam-se as mesmas regras de acessibilidade.
O que é retornado
Um envio bem-sucedido não retorna o vídeo, mas um objeto de tarefa contendo um identificador (geralmente o campo id) e um status como queued ou processing. Guarde esse identificador; ele é o handle usado em cada verificação de status subsequente.
{
"id": "job_abc123",
"status": "queued"
}
Você pode confirmar o envio bem-sucedido verificando o código de status HTTP e a presença do identificador da tarefa. Se a resposta contiver mensagens de validação, elas apontarão para os campos com erro — geralmente URLs ausentes ou malformadas.
Implementando a mesma requisição em Python
A chamada curl se traduz diretamente para Python. A versão abaixo foi pensada para ser colocada diretamente em um serviço: a chave vem de variáveis de ambiente, o payload é um dicionário construído dinamicamente e os erros são lançados em vez de silenciados.
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def submit_omnihuman_job(audio_url: str, image_url: str, **options) -> str:
payload = {
"audio_url": audio_url,
"image_url": image_url,
}
payload.update(options)
response = requests.post(
f"{BASE_URL}/omnihuman-1.5/generate",
headers=HEADERS,
json=payload,
timeout=60,
)
response.raise_for_status()
data = response.json()
return data["id"]
Por que escrever assim
json=payloadfaz orequestsserializar o corpo e definir o tipo de conteúdo, então você não esquece o cabeçalho JSON.**optionsmantém a função flexível: parâmetros de geração adicionais são passados como argumentos nomeados, sem precisar alterar o literal do payload.timeout=60evita que conexões travadas bloqueiem indefinidamente o processo de trabalho. O envio é uma chamada rápida; esperas longas devem ficar na etapa de polling, não aqui.raise_for_status()converte respostas não-2xx em exceções que podem ser capturadas e registradas, com acesso ao corpo da resposta para diagnóstico.
Guarde o identificador de tarefa retornado e passe-o para a função auxiliar de polling — construída na próxima seção.
Tratando o ciclo de vida assíncrono: polling até a conclusão
A geração de vídeo leva tempo, então a API é assíncrona por design. Após o envio, você consulta repetidamente o status da tarefa até que ela atinja um estado terminal.
Loop de polling
import time
def wait_for_job(job_id: str, interval: int = 5, max_wait: int = 600) -> dict:
waited = 0
while waited < max_wait:
response = requests.get(
f"{BASE_URL}/omnihuman-1.5/jobs/{job_id}",
headers=HEADERS,
timeout=30,
)
response.raise_for_status()
job = response.json()
status = job["status"]
if status == "succeeded" or status == "completed":
return job
if status == "failed" or status == "error":
raise RuntimeError(f"Job {job_id} failed: {job}")
time.sleep(interval)
waited += interval
raise TimeoutError(f"Job {job_id} did not finish within {max_wait}s")
Decidindo quando parar
Três resultados encerram o loop, e seu código deve tratar cada um deles:
- Sucesso — a tarefa reporta um estado de conclusão e contém uma referência ao vídeo de saída. Saia e prossiga para o download.
- Falha — a tarefa reporta um estado de erro. Não tente novamente às cegas; verifique a mensagem de erro primeiro, pois falhas geralmente são causadas por URLs de entrada ilegíveis ou áudio não suportado.
- Tempo esgotado — seu próprio limite de tempo real foi atingido. Trate isso como um caso diferente de falha: a tarefa pode ainda ser concluída no servidor, então decida conscientemente se continua o polling, estende a janela de tempo ou desiste.
Etiqueta de polling
Use um intervalo moderado em vez de um loop apertado. Para renderização de vídeo, alguns segundos entre verificações são suficientes e mantêm o volume de requisições previsível. Se uma fila longa for esperada, aumente o intervalo gradualmente e sempre defina um limite, para que um processo de trabalho travado não consulte para sempre. Em produção, prefira processos de trabalho em segundo plano ou filas de tarefas em vez de polling dentro de um handler de requisição web.
Baixando e armazenando o vídeo de saída
Depois que o polling retorna uma tarefa concluída, a resposta traz uma referência ao vídeo — geralmente um campo de URL dentro do objeto de resultado. Busque-o e persista no seu próprio armazenamento, em vez de depender do link a longo prazo.
def download_video(job: dict, destination: str) -> None:
video_url = job.get("output_url") or job.get("result", {}).get("video_url")
if not video_url:
raise ValueError(f"No video reference in job payload: {job}")
with requests.get(video_url, stream=True, timeout=120) as response:
response.raise_for_status()
with open(destination, "wb") as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
Cuidados que economizam tempo de depuração
- Download em streaming. Vídeos são grandes; gravar em blocos evita carregar o arquivo inteiro na memória, o que é importante em processos de trabalho com memória limitada.
- Use nomes de arquivo determinísticos. Derive-os do identificador da tarefa mais um timestamp, para que as execuções sejam rastreáveis e novas execuções não entrem em conflito.
- Baixe primeiro para um arquivo temporário, depois mova. Grave em um caminho temporário e renomeie após a conclusão, para que downloads parciais nunca sejam confundidos com arquivos completos.
- Trate a URL retornada como temporária. Copie os bytes para seu próprio bucket ou sistema de arquivos, e registre o identificador da tarefa junto com o objeto armazenado para consulta futura.
- Valide antes de declarar sucesso. Antes de marcar a tarefa como concluída no banco de dados, verifique se o arquivo baixado não está vazio e tem tamanho razoável.
Solução de problemas comuns de requisição e polling
A maioria dos problemas de integração se enquadra em algumas categorias. Verifique-as em ordem.
Erros de autenticação e requisição
401 Unauthorized— chave ausente, malformada ou não enviada como tokenBearer. Verifique cuidadosamente o cabeçalho, incluindo o espaço apósBearer.403— chave válida, mas sem acesso a este endpoint; confirme se a chave pertence ao projeto esperado.- Erros de validação
422/400— leia a mensagem. Causas comuns incluemaudio_urlausente,image_urlausente, URL ilegível ou formato de áudio não suportado. - HTML inesperado na resposta — você acessou o host ou caminho errado. Verifique a URL base na referência da API, em vez de reconstruí-la de memória.
Tarefas que falham ou nunca terminam
- A API não consegue acessar a URL de entrada — links que funcionam no navegador podem ser bloqueados por rede privada, assinatura expirada ou proteção contra hotlink. Teste primeiro com uma URL pública estável.
- Áudio e imagem incompatíveis — faixas silenciosas, extremamente longas ou em formato não suportado podem travar ou falhar a renderização. Valide o pipeline primeiro com um clipe curto em formato padrão.
- Polling com frequência excessiva — loops apertados podem acionar limites de taxa e gerar erros que parecem falhas da tarefa. Diminua a velocidade e adicione backoff.
- Tempo de polling curto demais — desistir de uma tarefa enfileirada após alguns segundos produz falsos timeouts. Defina um tempo máximo de espera realista e registre o status visto antes de parar.
- Estados terminais não tratados — se o loop só verifica sucesso, as falhas ficam em espera até o timeout. Ramifique explicitamente para estados de falha.
Hábito de validação mínima
Quando algo der errado, reduza ao teste mínimo: um trecho curto de áudio, um retrato pequeno, um envio e uma verificação de status após alguns segundos. Se isso funcionar, a falha está no seu payload, na lógica de polling ou na hospedagem das entradas — não na chamada da API em si.
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