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
O que a requisição kandinsky-6.0-pro/text-to-video faz
kandinsky-6.0-pro/text-to-video converte um prompt de texto em um clipe de vídeo curto. Você envia o prompt e alguns parâmetros de geração, e o modelo produz um arquivo de vídeo que pode ser salvo e reproduzido. É isso: entra prompt, sai clipe de vídeo.
O detalhe arquitetural crucial é que esta não é uma chamada síncrona. Você não recebe o vídeo diretamente no corpo da resposta da primeira requisição. Em vez disso, você cria uma tarefa, a API retorna o identificador dessa tarefa, e o modelo trabalha em segundo plano. Seu código precisa verificar o status da tarefa até que ela reporte conclusão, momento em que o resultado fica disponível para download.
Esse padrão tem algumas consequências que você deve considerar desde o início:
- O cliente precisa fazer polling. Um único
POSTnão devolve o vídeo pronto, então qualquer integração precisa de um laço de verificação de status ou de uma reverificação periódica similar a webhook. - A requisição deve ser idempotente do seu lado. Se o script falhar após o envio, você não quer criar silenciosamente uma segunda tarefa. Capture o identificador da tarefa e persista-o.
- A latência é variável. A geração de vídeo é mais lenta que chamadas de imagem ou texto, então esperar é normal, não é defeito.
O restante deste tutorial segue essa ordem de ciclo de vida: preparação, envio com curl, polling, download e, por fim, reconstruir o mesmo fluxo em Python. Trate o código como um esqueleto funcional — o caminho do endpoint e os nomes de campos devem sempre ser confirmados na referência da API do modelo, pois esses detalhes mudam conforme a plataforma evolui.
Antes de enviar a primeira requisição
Quatro coisas precisam estar prontas antes da primeira chamada.
1. Conta HiAPI e chave de API
A autenticação usa uma chave de API emitida pela sua conta HiAPI. Mantenha a chave fora do controle de versão e do histórico do shell sempre que possível. O procedimento habitual é exportá-la como variável de ambiente e deixar o código lê-la de lá:
export HIAPI_API_KEY="your-key-here"
Todas as requisições abaixo assumem que a chave é enviada como bearer token no cabeçalho Authorization. Se você ainda não criou uma chave, faça isso primeiro no painel da sua conta.
2. Cliente HTTP
curl é suficiente para validar se a requisição funciona. Para qualquer operação que precise ser repetida, use Python 3 com a biblioteca requests — apenas uma dependência, código legível e fácil de colocar depois em um agendador ou serviço:
python3 -m pip install requests
3. Onde armazenar a saída
Arquivos de vídeo são bem maiores que respostas JSON. Decida de antemão se vai gravar em um diretório local ou fazer streaming para um object storage. Neste tutorial, um diretório local ./output é suficiente:
mkdir -p output
4. Conhecer bem o seu prompt
Escreva o prompt antes de escrever o código. Um prompt específico e descritivo — sujeito, ação, comportamento de câmera, estilo visual — fornece uma linha de base para comparação quando algo der errado. Quando o prompt é uma constante nomeada no script, e não uma string digitada no shell, fica muito mais fácil alterar uma variável por vez.
Essa é a lista completa de pré-requisitos. Não há SDK para instalar nem etapa de build; a plataforma é acessada via HTTPS comum.
A requisição curl funcional
O primeiro objetivo é obter um comando que retorne uma tarefa (e não um vídeo). Faça isso funcionar antes de adicionar qualquer código.
A requisição tem três partes: o endpoint do modelo, o cabeçalho Authorization e o corpo JSON com o prompt e os parâmetros de geração.
curl -X POST "https://api.hiapi.ai/v1/models/kandinsky-6.0-pro/text-to-video/jobs" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A slow drone shot over a misty pine forest at sunrise, soft golden light, cinematic",
"duration_seconds": 5,
"aspect_ratio": "16:9"
}'
Leia a resposta com atenção. Você deve procurar:
- Um identificador de tarefa — o handle que você usará para o polling. Pode se chamar
id,job_idou algo similar. - Um campo de status inicial, geralmente algo como
queuedouprocessing. - Quaisquer parâmetros ecoados que confirmem que o corpo foi interpretado como você esperava.
Uma resposta que retorna um identificador de tarefa e um status que não seja de erro significa que a requisição foi aceita. Se essa resposta já contiver o arquivo de vídeo, então algo diferente do descrito neste artigo está acontecendo.
Confirme o contrato antes de construir sobre ele
Os nomes de campos acima — caminho do endpoint, duration_seconds, aspect_ratio, chave do identificador — são os detalhes mais propensos a mudar com o modelo e o tempo. A fonte confiável de verdade é a página de referência da API do modelo. Verifique uma vez, copie os nomes exatos como constantes no script e estruture o código de modo que mudar um nome seja uma edição de uma linha, não uma busca no código inteiro.
Se receber um 4xx, o corpo de erro traz mais informação que o código de status. 401 indica chave errada ou ausente; erros de validação do tipo 422 geralmente apontam o campo com problema.
Enviar e consultar a tarefa até a conclusão
Com a chamada de envio funcionando, o ciclo de vida é: enviar, capturar o identificador, consultar, parar no estado terminal.
Envio
O POST da seção anterior cria a tarefa. Independentemente do que o código faça em seguida, armazene o identificador retornado em um local persistente — uma variável no script, uma linha na tabela de tarefas, uma mensagem na fila. Se o processo morrer após receber a resposta de envio e antes de persistir o identificador, você perde a capacidade de consultar essa tarefa.
Polling
O polling é uma requisição GET ao recurso da tarefa, usando o identificador que você capturou:
curl "https://api.hiapi.ai/v1/models/kandinsky-6.0-pro/text-to-video/jobs/$JOB_ID" \
-H "Authorization: Bearer $HIAPI_API_KEY"
A resposta reporta o status atual da tarefa. Na prática você verá poucos estados: na fila ou pendente, processando, concluída e alguma forma de falha ou cancelamento. Projete o laço em torno dessas categorias, e não das strings exatas — mapeie o que a API retornar para running, done, failed no seu código, assim uma renomeação não quebra sua lógica de retry.
Decidir quanto esperar
Dois números importam: o intervalo de polling e o timeout geral.
- Intervalo. Consulte a cada poucos segundos, não em laço apertado. Laço apertado não traz benefício extra e pode disparar rate limiting. Para tarefas de vídeo, alguns segundos entre requisições é razoável.
- Timeout. Defina um teto. A geração de vídeo leva tempo, mas "esperar para sempre" não é uma resposta aceitável para um script de produção. Escolha um orçamento máximo de tempo realista e trate o estouro como falha a ser registrada e retentada conscientemente.
Um padrão que aguenta uso real
Em produção, a etapa de polling geralmente é desacoplada da etapa de envio, em vez de ficar em um processo dormindo. O worker envia, registra a tarefa e sai; uma reverificação periódica pega as tarefas pendentes e as consulta. Isso é mais robusto a reinícios e mais fácil de observar. Para este tutorial, um laço simples em um único processo basta — apenas organize-o como funções em vez de código inline, para que movê-lo depois para um worker agendado seja simples.
Baixar o clipe de vídeo gerado
Uma tarefa concluída ainda não é um arquivo no seu disco. A resposta de status da tarefa concluída aponta para a saída — geralmente uma URL, às vezes um objeto aninhado contendo a URL. Leia esse campo e use-o como entrada da etapa de download.
curl -L "$OUTPUT_URL" -o output/clip.mp4
Verifique os pontos a seguir para confirmar que o download realmente funcionou:
- Siga redirecionamentos. URLs de saída muitas vezes são servidas via redirecionamento; curl trata com
-L, Python comallow_redirects=True. - Valide o content type. Uma tarefa concluída deve produzir um payload de vídeo. Se o que foi salvo como
clip.mp4for JSON ou uma página de erro HTML, o problema foi no download, não na geração. - Cheque o tamanho. Arquivo de zero byte ou suspeitosamente pequeno indica download com falha. Se houver cabeçalhos de resposta, compare os bytes com o tamanho declarado.
- Considere a expiração. URLs de saída costumam ter prazo. Baixe logo após a conclusão e, se precisar de persistência, copie o arquivo para o seu próprio storage em vez de guardar a URL como referência permanente.
Para qualquer uso além do tutorial, faça streaming do download direto para o destino em vez de carregar o arquivo inteiro em memória, e grave primeiro em um nome temporário e renomeie — assim downloads incompletos nunca parecem arquivos completos para o código downstream.
Implementar a mesma requisição em Python
Veja a reconstrução do fluxo curl como uma função chamável: enviar, consultar, baixar. Os nomes que precisam de ajuste estão reunidos no topo como constantes.
import os
import time
import requests
API_BASE = "https://api.hiapi.ai/v1"
MODEL_PATH = "/models/kandinsky-6.0-pro/text-to-video"
API_KEY = os.environ["HIAPI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
RUNNING_STATES = {"queued", "pending", "processing", "running"}
DONE_STATES = {"completed", "succeeded", "done"}
FAILED_STATES = {"failed", "cancelled", "error"}
def generate_clip(prompt, out_path, timeout_s=600, interval_s=5):
# 1. submit
resp = requests.post(
API_BASE + MODEL_PATH + "/jobs",
headers={**HEADERS, "Content-Type": "application/json"},
json={"prompt": prompt, "duration_seconds": 5, "aspect_ratio": "16:9"},
timeout=30,
)
resp.raise_for_status()
job = resp.json()
job_id = job["id"]
print(f"submitted job {job_id}")
# 2. poll
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
status_resp = requests.get(
f"{API_BASE}{MODEL_PATH}/jobs/{job_id}",
headers=HEADERS,
timeout=30,
)
status_resp.raise_for_status()
data = status_resp.json()
state = str(data.get("status", "")).lower()
if state in DONE_STATES:
break
if state in FAILED_STATES:
raise RuntimeError(f"job {job_id} ended in state {state}: {data}")
time.sleep(interval_s)
else:
raise TimeoutError(f"job {job_id} did not finish within {timeout_s}s")
# 3. download
url = data["output"]["url"] if isinstance(data.get("output"), dict) else data["output"]
with requests.get(url, stream=True, allow_redirects=True, timeout=60) as r:
r.raise_for_status()
tmp = out_path + ".part"
with open(tmp, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 16):
f.write(chunk)
os.replace(tmp, out_path)
print(f"saved {out_path}")
return job_id
if __name__ == "__main__":
generate_clip(
"A slow drone shot over a misty pine forest at sunrise, soft golden light, cinematic",
"output/clip.mp4",
)
Por que foi escrito assim
- Usar conjuntos de estados em vez de comparação exata. Mapear os estados retornados para running/done/failed significa que um novo estado intermediário não quebra o laço.
- Deadline monotônico.
time.monotonic()não é afetado por ajustes de relógio, então o timeout é preciso. - Escrita atômica. Gravar em
.parte renomear significa que um download interrompido nunca deixa um arquivo truncado aparentemente válido. - Retornar o ID da tarefa. O chamador pode registrar, armazenar e consultar novamente quando necessário — é o primeiro passo para mover o polling para fora deste processo.
Ajuste o caminho do endpoint, os nomes dos campos da requisição e as chaves da resposta para corresponder à referência da API do modelo. Todo o resto — o laço, o timeout, o download — é genérico.
Estados de erro e checklist de depuração
Quando algo falhar, isole o estágio antes de mudar qualquer coisa. Cada estágio tem uma assinatura de falha diferente.
Falha de autenticação
Um 401 ou 403 no envio significa chave ausente, errada ou não enviada. Verifique se a variável de ambiente está de fato definida no shell ou processo que executa o código — uma chave exportada em um terminal é invisível para um cron job. Imprima os primeiros caracteres da chave para confirmar que foi resolvida, nunca a chave completa.
Erro de formato da requisição
Erros do tipo 400 ou 422 no envio indicam que o corpo não passou na validação. O corpo da resposta geralmente aponta o campo. Causas comuns: parâmetro com erro de digitação, duração fora do intervalo suportado ou prompt vazio. Compare seu JSON campo a campo com a referência da API; uma única chave renomeada é a causa mais frequente.
Tarefa presa em estado de execução
Se o polling nunca chega ao estado terminal, confirme três coisas: o identificador consultado é o mesmo que você enviou; o intervalo de polling não é tão frequente a ponto de sofrer rate limiting; o timeout é suficientemente longo para o modelo. Registre a resposta bruta de status a cada polling para ver se o estado avança ou congela.
Tarefa concluída, mas download falha
Tarefa concluída com download falhando é problema de manipulação de arquivo, não de geração. Verifique se os redirecionamentos são seguidos, se a URL não expirou e se o content type é vídeo e não JSON. Teste a URL separadamente com curl -L, isolando-a do script.
O mesmo prompt falha repetidamente
Se um prompt falha continuamente enquanto outros funcionam, suspeite primeiro de política de conteúdo ou tamanho do prompt, não de infraestrutura. Altere uma variável — encurte o prompt, simplifique a descrição da cena — e tente novamente.
Uma regra geral
Registre quatro coisas para cada tarefa: identificador da tarefa, estado final, tempo real decorrido e o status HTTP do download. Esses quatro valores convertem a maioria dos relatos de "não funcionou" em um estágio específico e corrigível em menos de um minuto.
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
Como usar kling-4.0/text-to-video através da API HiAPI: curl, Python e um exemplo de requisição executável
Guia prático para desenvolvedores: prompts cinematográficos, áudio sincronizado, polling assíncrono e download da saída