HiAPI
Blogue

Tutorial

Chamando a API de texto para vídeo do HappyHorse 1.1 via HiAPI: um tutorial curl + Python que funciona

Jun 27, 2026
Chamando a API de texto para vídeo do HappyHorse 1.1 via HiAPI: um tutorial curl + Python que funciona
Modelo
happyhorse-1.1

O HappyHorse 1.1 é o modelo de texto para vídeo da Alibaba: suporta clipes de vídeo em 720p / 1080p, com duração de 3 a 15 segundos, gerando áudio nativo em uma única chamada (sem necessidade de uma etapa separada de trilha sonora). A HiAPI expõe esse modelo pelo mesmo endpoint assíncrono unificado de todos os outros modelos generativos, portanto, se você já chamou modelos de imagem em /v1/tasks, a única mudança é o id do modelo e alguns campos de input.

Esta página traz o mínimo necessário para entregar uma integração funcional: o schema exato, o curl pronto para copiar, um cliente de polling em Python e o padrão de callback para produção. Também aponta explicitamente duas coisas pouco óbvias que o modelo não aceita (um interruptor audio e um seed), para você não desperdiçar uma requisição por causa de um 400.

Pré-requisitos. Obtenha uma chave no Console da HiAPI e exporte-a como HIAPI_API_KEY. Toda requisição é autenticada via Authorization: Bearer sk-…; para revisar, consulte Authentication.

Endpoint e estrutura da requisição

Tudo passa pelo mesmo endpoint:

POST https://api.hiapi.ai/v1/tasks
Authorization: Bearer sk-<your-key>
Content-Type: application/json

O corpo da requisição tem três chaves de nível superior:

  • model — happyhorse-1.1/text-to-video (o id literal do modelo — a barra deve ser mantida).
  • input — campos específicos do modelo. Para o HappyHorse 1.1 T2V:
    • prompt (string, obrigatório) — descreve o clipe de vídeo.
    • resolution (720p | 1080p, padrão 1080p).
    • aspect_ratio (16:9 | 9:16 | 3:4 | 4:3 | 4:5 | 5:4 | 1:1 | 9:21 | 21:9, padrão 16:9).
    • duration (inteiro, 3–15, padrão 5). O custo aumenta com a quantidade de segundos.
  • callback (opcional, objeto) — endpoint HTTPS em callback.url + callback.when: "final". A HiAPI fará exatamente um POST do resultado final para esse endereço por tarefa.

Duas coisas que parecem funcionar, mas não funcionam:

  • ❌ Não existe o campo audio. O áudio é gerado nativamente junto com o vídeo; não há interruptor. Enviar "audio": true retorna additional properties 'audio' not allowed.
  • ❌ Não existe o campo seed. Também retorna 400. Se você precisa de determinismo entre lotes agora, gere várias versões e escolha — não há alavanca de seed ajustável.

Um corpo de requisição mínimo válido:

{
  "model": "happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "A golden retriever running on a beach, slow motion, gentle waves, warm sunset tones",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "duration": 5
  }
}

Exemplo mínimo executável: curl

Crie a tarefa — a resposta retorna imediatamente e contém apenas um taskId:

curl -sS -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.1/text-to-video",
    "input": {
      "prompt": "A snow mountain lake in morning mist, slow camera push-in, warm cinematic light",
      "resolution": "1080p",
      "aspect_ratio": "16:9",
      "duration": 5
    }
  }'
# => {"code":200,"data":{"taskId":"tk-hiapi-01KW3..."},"message":"success"}

Depois, faça polling até chegar a um estado terminal:

TASK_ID=tk-hiapi-01KW3...

curl -sS "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
  -H "Authorization: Bearer $HIAPI_API_KEY"
# while .data.status is "handling", sleep a few seconds and retry.
# On success:
# {
#   "code": 200,
#   "data": {
#     "status": "success",
#     "model": "happyhorse-1.1/text-to-video",
#     "output": [
#       {"type":"video","url":"https://temp.hiapi.ai/.../...-0.mp4","expireAt":1783130616}
#     ],
#     ...
#   }
# }

A URL do mp4 é temporária (expireAt é um timestamp Unix de cerca de 7 dias depois). Baixe e persista imediatamente após a tarefa ter sucesso — não faça hotlink. Se você preferir que a HiAPI gerencie o armazenamento de longo prazo, consulte a documentação de Output Storage para saber como promover a saída do armazenamento temporário para o persistente.

Python: um cliente pequeno e com formato de produção

Um cliente de verdade precisa de três coisas: um create_task que retorna o id, um wait_task que faz polling com prazo limite e uma etapa de download. Este esqueleto contém todos os três e fica próximo do ponto de partida da página do SDK Python da HiAPI — mantenha-o pequeno e expanda a partir daí.

# pip install requests
import os, time, json, requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}


def create_task(prompt: str, *, resolution="1080p", aspect_ratio="16:9", duration=5) -> str:
    body = {
        "model": "happyhorse-1.1/text-to-video",
        "input": {
            "prompt": prompt,
            "resolution": resolution,
            "aspect_ratio": aspect_ratio,
            "duration": duration,
        },
    }
    r = requests.post(API_BASE, headers={**HEADERS, "Content-Type": "application/json"},
                      data=json.dumps(body), timeout=60)
    r.raise_for_status()
    data = r.json()
    if data.get("code") != 200:
        raise RuntimeError(f"create failed: {data}")
    return data["data"]["taskId"]


def wait_task(task_id: str, *, timeout_s: int = 600, poll: int = 5) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
        r.raise_for_status()
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task
        if status == "fail":
            raise RuntimeError(f"task {task_id} failed: {task.get('error')}")
        time.sleep(poll)
    raise TimeoutError(f"task {task_id} did not finish within {timeout_s}s")


def download(url: str, path: str) -> None:
    with requests.get(url, stream=True, timeout=120) as r:
        r.raise_for_status()
        with open(path, "wb") as f:
            for chunk in r.iter_content(1 << 14):
                f.write(chunk)


if __name__ == "__main__":
    task_id = create_task(
        "A neon street at night after rain, reflections on the ground, "
        "cyberpunk mood, slow pan",
        resolution="720p", aspect_ratio="9:16", duration=5,
    )
    task = wait_task(task_id)
    url = task["output"][0]["url"]
    download(url, "out.mp4")
    print("saved out.mp4")

Algumas observações para produção:

  • Campo de status. Trate qualquer valor diferente de success ou fail como em andamento (a plataforma atualmente usa handling).
  • raise_for_status não basta. Para alguns erros de validação, a HiAPI retorna HTTP 200, mas com code diferente de 200 — verifique também data["code"]. Para integrações novas, o mais comum é 401 permission_denied, o que significa bearer token incorreto ou ausente — reexporte HIAPI_API_KEY e confirme no console.

Produção: prefira callbacks em vez de polling

Para qualquer cenário além do início rápido, dê à HiAPI um webhook para ela te chamar quando a tarefa terminar:

{
  "model": "happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "A snow mountain lake in morning mist, slow camera push-in, warm cinematic light",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "duration": 5
  },
  "callback": {
    "url": "https://your-domain.com/hiapi/callback",
    "when": "final"
  }
}

Garanta que seu handler de callback faça o seguinte:

  • Deduplique por taskId. Tanto success quanto fail são terminais — seu serviço deve tratar duas entregas do mesmo taskId como no-op (gravação idempotente com chave taskId).
  • Retorne 2xx rapidamente. Coloque o trabalho pesado (baixar o mp4, persistir, notificar o usuário) em uma fila. O handler de webhook deve confirmar em poucos segundos.
  • Mantenha GET /v1/tasks/:id como fallback. Se um webhook se perder (deploy, instabilidade de rede), uma tarefa agendada de reconciliação que busca por id as tarefas presas e aplica o mesmo handler é a rede de segurança mais simples.

Se você tiver que escolher um caminho: polling serve para scripts pontuais e depuração local, e qualquer lugar com tráfego real deve usar callbacks.

Escolhendo os parâmetros corretos (resolution × aspect_ratio × duration)

Necessidade resolution aspect_ratio duration
Vídeo curto vertical para redes sociais, menor custo 720p 9:16 5
Prévia quadrada / loop de thumbnail 720p 1:1 3
Narrativa horizontal / cena publicitária 1080p 16:9 5–8
Clipes de key visual em widescreen 1080p 21:9 8–12

O custo aumenta com a resolução e a duração — consulte os preços exatos por segundo em Preços da HiAPI. Quando não tiver certeza dos valores corretos, não preencha: resolution assume 1080p, aspect_ratio assume 16:9 e duration assume 5.

Perguntas frequentes

O modelo de texto para vídeo HappyHorse 1.1 tem parâmetro seed? Não. A API rejeita seed com additional properties 'seed' not allowed. Se você precisa de várias opções para escolher, envie várias tarefas com o mesmo prompt — execuções diferentes geram variações naturalmente.

Como ligar ou desligar o áudio? Você não consegue — o HappyHorse 1.1 gera a faixa de áudio nativamente na mesma chamada. Não há interruptor audio no schema; enviar um retorna 400. Se você precisar de um clipe sem som, remova o áudio na pós-produção.

Quais são as durações válidas? Um inteiro de 3 a 15 (segundos). Qualquer valor fora desse intervalo retorna duration: minimum: got 0, want 3 ou duration: maximum: got 20, want 15. Decimais também são rejeitados (o tipo do campo é inteiro).

Quais proporções de aspecto ele suporta? Nove: 16:9, 9:16, 3:4, 4:3, 4:5, 5:4, 1:1, 9:21, 21:9. O padrão é 16:9.

Por quanto tempo output[].url permanece válida? Cerca de uma semana — a resposta inclui um timestamp Unix expireAt. Baixe o mp4 imediatamente e re-hospede (S3, R2, seu CDN), ou promova-o para armazenamento persistente pela Output Storage API.

E imagem para vídeo? O HappyHorse 1.1 tem uma variante I2V no mesmo endpoint — consulte HappyHorse 1.1 I2V. Mesma autenticação, mesmo ciclo de vida assíncrono, schema de input diferente.

Onde está a referência completa da API assíncrona? O envelope da requisição está em Create Task, o endpoint de polling em Get Task Detail e o schema canônico de entrada na página do modelo HappyHorse 1.1 T2V. Se você está começando do zero, o Quickstart guia você pela primeira chamada de ponta a ponta.

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