HiAPI
Blogue

Tutorial

Como usar a API de referência para vídeo do vidu-q4-preview (curl + Python)

Oct 19, 2026
Como usar a API de referência para vídeo do vidu-q4-preview (curl + Python)

O que você vai construir

Faça uma chamada de referência para vídeo na API assíncrona /v1/tasks da hiapi, combinando várias imagens de referência — e, opcionalmente, clipes de áudio — em um plano de 3–16 segundos, com até 4K. Você envia um único POST, depois faz polling (ou recebe um callback) até a tarefa concluir, e baixa o MP4.

Primeiro obtenha sua chave no console da hiapi; toda requisição abaixo usa Authorization: Bearer sk-<your-key>.

Referência para vídeo vs. imagem para vídeo. Este endpoint combina 1–15 imagens fixas — envie uma imagem de uma pessoa, uma de um cenário e uma de um objeto, e ele as funde em um único plano. Se você tem apenas um único primeiro frame para animar, use vidu-q4-preview/image-to-video; ele recebe um único image_url e rejeita reference_image_urls.

Requisição mínima executável (curl)

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vidu-q4-preview/reference-to-video",
    "input": {
      "prompt": "A pessoa da imagem de referência 1 caminha pela cafeteria da imagem de referência 2, luz da manhã quente, movimento lento de aproximação",
      "reference_image_urls": [
        "https://your-cdn.com/person.jpg",
        "https://your-cdn.com/cafe.jpg"
      ],
      "resolution": "1080p",
      "duration": 5,
      "aspect_ratio": "16:9"
    }
  }'

Esse POST retorna um id de tarefa, não o vídeo:

{ "code": 200, "data": { "taskId": "task_abc123" } }

Faça polling em GET /v1/tasks/<taskId> até data.status ser success, depois leia o MP4 em data.output[0].url:

curl https://api.hiapi.ai/v1/tasks/task_abc123 \
  -H "Authorization: Bearer sk-<your-key>"
{
  "code": 200,
  "data": {
    "status": "success",
    "output": [
      { "url": "https://temp.hiapi.ai/....mp4", "expireAt": 1760000000 }
    ]
  }
}

A URL de saída é temporária — ela tem expireAt (expira em alguns dias) — então baixe os bytes imediatamente, não faça hotlink.

Python: enviar → polling → baixar

import time
import requests

BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {
    "Authorization": "Bearer sk-<your-key>",
    "Content-Type": "application/json",
}

def submit() -> str:
    payload = {
        "model": "vidu-q4-preview/reference-to-video",
        "input": {
            "prompt": (
                "A pessoa da imagem de referência 1 caminha pela cafeteria "
                "da imagem de referência 2, luz da manhã quente, movimento lento de aproximação"
            ),
            "reference_image_urls": [
                "https://your-cdn.com/person.jpg",
                "https://your-cdn.com/cafe.jpg",
            ],
            "resolution": "1080p",
            "duration": 5,
            "aspect_ratio": "16:9",
        },
    }
    r = requests.post(BASE, json=payload, headers=HEADERS, timeout=60)
    r.raise_for_status()
    body = r.json()
    task_id = (body.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"envio rejeitado: {body}")  # erros 400 caem aqui
    return task_id

def wait(task_id: str, timeout_s: int = 600, interval: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=40)
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            raise RuntimeError(f"tarefa falhou: {task.get('error')}")
        time.sleep(interval)
    raise TimeoutError(task_id)

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 << 16):
                f.write(chunk)

task_id = submit()
url = wait(task_id)
download(url, "out.mp4")

Um ponto para internalizar: uma renderização com falha ainda retorna HTTP 200, com o motivo em data.status: "fail" e data.error.code / data.error.message. Uma falha de geração não é um erro HTTP, então ramifique pelo corpo da resposta, não pelo código de status.

Adicionar referência de voz

O campo de voz é reference_audio_urls — um array de até 3 clipes de áudio. O áudio define o timbre; seu prompt ainda carrega o texto e conduz a sincronia labial.

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": {
    "prompt": "A apresentadora da imagem de referência 1 diz, com a voz do áudio de referência 1: 'Bem-vindos de volta ao canal.'",
    "reference_image_urls": ["https://your-cdn.com/presenter.jpg"],
    "reference_audio_urls": ["https://your-cdn.com/voice.mp3"],
    "resolution": "1080p",
    "duration": 8
  }
}

Armadilha de nome de campo: o intuitivo voice_reference_urls é rejeitado (o validador só aceita reference_audio_urls). Veja a tabela de sondagem abaixo.

Produção: callbacks e idempotência

Para fluxos de servidor, você normalmente não quer manter um loop de polling ativo. Anexe um callback de nível superior (no mesmo nível de input, não dentro dele) e a hiapi fará um POST da tarefa concluída para sua URL:

{
  "model": "vidu-q4-preview/reference-to-video",
  "input": { "prompt": "...", "reference_image_urls": ["..."] },
  "callback": { "url": "https://your-app.com/hooks/vidu", "when": "final" }
}
  • when só aceita "final" — você recebe uma única notificação no estado terminal (sucesso ou falha), nunca notificações de progresso intermediário.
  • O corpo do callback é o mesmo payload retornado por GET /v1/tasks/<id>.
  • As entregas são repetidas algumas vezes e podem ser duplicadas, então deduplique por taskId e torne seu handler idempotente.
  • Mantenha o polling como fallback, para cobrir janelas em que seu endpoint estiver temporariamente inacessível.

Salve o taskId no momento em que recebê-lo. Se seu poller encontrar um erro de rede temporário, faça polling novamente do id salvo — nunca reenvie, ou você pagará pela segunda renderização.

O que eu validei (contrato de schema)

Sondei o endpoint ao vivo com valores deliberadamente inválidos (gratuito — requisições rejeitadas não são cobradas e valores inválidos nunca criam uma tarefa). O validador é rigoroso e retorna um formato plano { "code": 400, "error_code": "INVALID_REQUEST", "message": ... }:

O que você envia O que é retornado
resolution: "9999p" resolution: value must be one of '540p', '720p', '1080p', '2k', '4k'
duration: 999 duration: maximum: got 999, want 16
aspect_ratio: "banana" aspect_ratio: value must be one of '16:9', '9:16', '1:1', '4:3', '3:4'
voice_reference_urls: [...] additional properties 'voice_reference_urls' not allowed
quatro reference_audio_urls reference_audio_urls: maxItems: got 4, want 3
omitir reference_image_urls missing required field "reference_image_urls"

Portanto, a estrutura de entrada confirmada é:

Campo Obrigatório Valores
prompt Sim Texto
reference_image_urls Sim 1–15 URLs de imagem
reference_audio_urls Não Até 3 URLs de áudio (campo de voz)
resolution Não 540p / 720p / 1080p / 2k / 4k
duration Não Inteiro 3–16 (segundos)
aspect_ratio Não 16:9 / 9:16 / 1:1 / 4:3 / 3:4

duration é inteiro (5), não string — diferente de alguns outros modelos de vídeo na hiapi que esperam "6". Enviar chaves extras é erro fatal (additional properties ... not allowed), então não copie campos do schema de imagem para vídeo.

Cuidados no lado da saída antes de integrar o download

  • Todo clipe tem uma trilha de áudio AAC, mesmo que você não envie reference_audio_urls. O vocabulário sonoro do prompt conduz a trilha ambiente, então não presuma que “sem referência de voz = arquivo mudo”.
  • A saída 4K do Vidu Q4 Preview é entregue em HEVC/H.265. Ela toca na maioria dos players nativos, mas muitos navegadores não conseguem reproduzir MP4 H.265 inline dentro de uma tag <video> — se for embutir na web, recodifique para H.264. Os níveis inferiores retornam H.264 padrão.

Modelo de preview — trate as enumerações como instantâneos

vidu-q4-preview/reference-to-video é um modelo de preview: pode ser chamado hoje, mas não está listado em /v1/models, e o schema de preview pode mudar. Antes de processar em lote, execute novamente uma sondagem de valores inválidos (como a tabela acima) para confirmar que as enumerações ainda são válidas. A especificação autoritativa são as regras que o validador realmente aplica, mais a página do modelo.

Relacionados

Perguntas frequentes

Referência para vídeo é o mesmo que imagem para vídeo? Não. Referência para vídeo combina 1–15 imagens fixas (opcionalmente mais até 3 clipes de áudio) em um único plano composto; imagem para vídeo anima um único primeiro frame. São endpoints separados, com entradas diferentes — referência para vídeo chega a rejeitar o campo image_url de imagem para vídeo, e vice-versa.

Como adiciono voz? Anexe reference_audio_urls (até 3 clipes) e indique no prompt (“...com a voz do áudio de referência 1”). O nome do campo deve ser exatamente reference_audio_urls; voice_reference_urls e outros nomes são rejeitados.

Qual é o clipe mais longo que posso solicitar? 16 segundos. duration é um inteiro de 3 a 16.

Preciso fazer polling? Não — anexe callback: { "url": ..., "when": "final" } e receba uma notificação no estado terminal. Deduplique por taskId e mantenha o polling como fallback.

Quanto custa um clipe 4K? Cobrado por segundo, com taxa que cresce conforme a resolução, e 4K é o nível mais alto — veja Preços da hiapi. O fluxo prático é iterar em 720p e re-renderizar em 4k apenas a versão final que você vai manter.

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