HiAPI
Blogue

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

Nov 3, 2026
深棕与燕麦色宽带交织的扁平编织纹理封面图,点缀克制黄铜色调,几何秩序感强

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=payload faz o requests serializar o corpo e definir o tipo de conteúdo, então você não esquece o cabeçalho JSON.
  • **options manté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=60 evita 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 token Bearer. Verifique cuidadosamente o cabeçalho, incluindo o espaço após Bearer.
  • 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 incluem audio_url ausente, image_url ausente, 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 →

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