HiAPI
Blogue

Tutorial

Tutorial de kandinsky-6.0-pro/image-to-video na HiAPI: curl + Python

Faça uma requisição de imagem para vídeo funcional na HiAPI: do upload do primeiro quadro ao polling assíncrono e ao download final

Nov 3, 2026
深色底上青绿与石板灰的扁平液态色块相互交叠,构成 kandinsky-6.0-pro 视频教程的封面图。

Visão geral do fluxo image-to-video na HiAPI

Cada chamada de imagem para vídeo na HiAPI segue o mesmo ciclo de vida em três fases. Entender isso desde o início faz o restante do tutorial parecer passo a passo, em vez de algo misterioso.

Fase 1: Enviar a tarefa

Você envia uma requisição POST para o endpoint kandinsky-6.0-pro/image-to-video, anexando a imagem do primeiro quadro e um prompt curto que descreve o movimento esperado. A resposta não retorna o fluxo de bytes do vídeo; em vez disso, aceita a tarefa e retorna um identificador de tarefa — todas as operações seguintes dependem desse identificador.

Fase 2: Consultar o status (polling)

A geração de vídeo leva tempo, então o endpoint é assíncrono. Você chama a rota de status com o identificador da tarefa, e ela informa o estado atual da tarefa: na fila, em processamento, sucesso ou falha. Você repete a verificação em intervalos curtos até o status atingir um estado terminal.

Fase 3: Obter a saída

Assim que a tarefa reporta sucesso, o payload de status traz a localização do vídeo finalizado. Você o baixa e grava em disco. Esse é todo o contrato.

Por que esse formato importa

A separação entre envio e polling não é acidental. Isso significa que seu cliente HTTP não precisa manter o socket aberto durante toda a renderização, e também que você pode persistir o identificador da tarefa, sair e retomar depois. Em caso de erro, o campo de status informa onde ocorreu o erro, o que é bem mais útil do que um timeout opaco.

Memorize as três fases: enviar, consultar, baixar. Os exemplos em curl e Python abaixo são apenas duas formas de escrever a mesma sequência.

Preparar o primeiro quadro e as credenciais da API

Na maioria das primeiras chamadas, só há dois pontos de falha: a chave e a imagem. Resolva ambos agora e o restante do tutorial fluirá bem.

Definir a chave de API como variável de ambiente

Não cole a chave em arquivos de código-fonte. Exporte-a no shell para que curl e Python possam obtê-la sem codificar nada diretamente:

export HIAPI_API_KEY="your_api_key_here"

No Windows PowerShell, o equivalente é $env:HIAPI_API_KEY="your_api_key_here". Antes de continuar, confirme que o shell consegue lê-la:

echo "$HIAPI_API_KEY" | head -c 4; echo

Você deve ver os primeiros caracteres da chave. Se não vir nada, a variável não foi persistida na sessão atual do shell — uma causa comum de respostas 401 mais adiante.

Escolher uma imagem de primeiro quadro válida

O primeiro quadro determina o sujeito, a composição e a proporção de aspecto de todo o vídeo. Algumas restrições práticas evitam a maioria das rejeições:

  • Formato: use formatos de imagem web padrão, como JPEG ou PNG. Evite codecs obscuros, casos extremos de progressivo ou perfis de cor CMYK.
  • Acessibilidade: a API precisa realmente ler esses bytes. Se você passar uma URL, garanta que ela seja acessível publicamente ou esteja devidamente autenticada; se passar dados inline, garanta que a codificação esteja completa.
  • Tamanho: imagens de tamanho razoável são validadas mais rápido. Arquivos muito grandes atrasam a requisição e frequentemente são a origem de erros de upload.
  • Conteúdo: escolha um quadro que faça sentido como ponto de partida do movimento — sujeito nítido e fundo limpo. O prompt de movimento descreve como sair desse quadro, então quadros confusos geram vídeos confusos.

Decidir como referenciar a imagem

O corpo da requisição permite apontar para o primeiro quadro via URL ou dados codificados inline. Escolha conforme onde a imagem está:

  • Se o arquivo já está hospedado e pode ser lido publicamente, URL é a opção mais limpa.
  • Se a imagem é local ou privada, a codificação inline torna a requisição inteira autocontida, ao custo de um payload maior.

De qualquer forma, mantenha a referência de imagem no mesmo formato de variável em curl e Python, para que os dois exemplos permaneçam diretamente comparáveis.

Fazer a requisição com curl

Esta é uma requisição de envio completa. Substitua pela sua própria referência de imagem e prompt e execute.

curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "https://your-host.example/first-frame.jpg",
    "prompt": "slow dolly-in on the subject, gentle ambient motion, stable camera",
    "duration": 5,
    "aspect_ratio": "16:9"
  }'

O papel de cada parte

  • URL aponta especificamente para o modelo kandinsky-6.0-pro/image-to-video. A escolha do modelo está no caminho, não no corpo da requisição, então um erro de digitação aqui gera 404, e não uma mensagem de validação amigável.
  • Authorization carrega o token bearer da variável de ambiente exportada. Nada mais autentica a chamada.
  • Content-Type: application/json é importante para qualquer POST com corpo JSON; se omiti-lo, alguns proxies podem corromper o payload antes de ele chegar à API.
  • image é a referência do seu primeiro quadro — aqui na forma de URL, ou como string codificada inline se a imagem for privada.
  • prompt descreve o movimento. Mantenha-o sobre movimento e comportamento de câmera, não repetindo o que a imagem já contém.
  • duration e aspect_ratio moldam a saída. A proporção de aspecto deve corresponder ao primeiro quadro; incompatibilidades causam recorte ou barras pretas. A cobrança é medida pela saída gerada, então essas configurações também determinam seu custo.

Ler a resposta

Um envio bem-sucedido retorna o payload da tarefa, não o vídeo. Capture o identificador da tarefa — você o passará ao endpoint de status depois:

curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @body.json | jq -r '.id'

Usar um arquivo body.json em vez de -d inline mantém prompts longos e imagens codificadas legíveis. O jq é opcional, mas transforma a resposta em uma linha pronta para colar na próxima chamada.

Chamar o mesmo endpoint com Python

A versão em Python é a mesma requisição, o mesmo corpo, apenas encapsulada em funções para reutilização. Mantenha o corpo idêntico ao da versão curl — esse é justamente o sentido de mostrar os dois.

import os
import json
import requests

API_BASE = "https://api.hiapi.ai/v1"
ENDPOINT = f"{API_BASE}/kandinsky-6.0-pro/image-to-video"

def submit_video_job(image_ref: str, prompt: str, duration: int = 5, aspect_ratio: str = "16:9") -> str:
    """Submit a first-frame image-to-video job and return the job id."""
    api_key = os.environ.get("HIAPI_API_KEY")
    if not api_key:
        raise RuntimeError("HIAPI_API_KEY is not set in this environment")

    body = {
        "image": image_ref,
        "prompt": prompt,
        "duration": duration,
        "aspect_ratio": aspect_ratio,
    }

    response = requests.post(
        ENDPOINT,
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        },
        json=body,
        timeout=60,
    )

    if response.status_code >= 400:
        raise RuntimeError(f"submit failed: {response.status_code} {response.text}")

    payload = response.json()
    return payload["id"]

if __name__ == "__main__":
    job_id = submit_video_job(
        image_ref="https://your-host.example/first-frame.jpg",
        prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
    )
    print(json.dumps({"job_id": job_id}, indent=2))

Notas sobre a versão em Python

  • Falha rápida quando falta a chave. A verificação explícita do ambiente transforma o erro mais comum em um erro local claro, em vez de um 401 remoto.
  • json=body versus data=json.dumps(body). Passar json= faz o requests definir o tipo de conteúdo por você, mantendo os cabeçalhos mínimos. Se usar data=, defina Content-Type explicitamente.
  • Timeout generoso. O envio de vídeo às vezes envolve transmitir payloads grandes de imagem. Timeouts curtos demais produzem falhas falsas.
  • Ler o corpo da resposta em caso de erro. Lançar tanto o código de status quanto o corpo da resposta significa que a mensagem de falha realmente informa o que a API rejeitou.

Se o primeiro quadro for um arquivo local, leia-o, codifique em base64 e substitua image_ref dentro de submit_video_job por essa string. A assinatura da função não muda — é exatamente por isso que os dois estilos de chamada compartilham a mesma definição de corpo de requisição.

Consultar a tarefa e baixar o vídeo

Uma tarefa enviada não é o vídeo finalizado. Consulte até a tarefa atingir um estado terminal e então baixe.

Loop de polling

import time
import requests

def wait_for_video(job_id: str, interval: float = 10.0, max_wait: float = 600.0) -> str:
    """Poll the job until it finishes; return the output URL."""
    import os
    api_key = os.environ["HIAPI_API_KEY"]
    url = f"https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video/{job_id}"
    headers = {"Authorization": f"Bearer {api_key}"}

    deadline = time.time() + max_wait
    while time.time() < deadline:
        response = requests.get(url, headers=headers, timeout=30)
        response.raise_for_status()
        payload = response.json()
        status = payload.get("status")

        if status == "succeeded":
            return payload["output"]
        if status == "failed":
            raise RuntimeError(f"job failed: {payload.get('error', 'unknown error')}")

        time.sleep(interval)

    raise TimeoutError(f"job {job_id} did not finish within {max_wait}s")

Três detalhes fazem esse loop se comportar bem:

  • Espere por intervalo, não por sorte. Um sleep fixo de cerca de dez segundos é um ponto de partida razoável; não martele o endpoint em um loop apertado.
  • Trate cada estado terminal. succeeded entrega a saída, failed entrega a mensagem de erro. Ambos devem ser tratados como saída. Um loop que só verifica sucesso continuaria girando em uma tarefa morta até o prazo final.
  • Limite o tempo de espera. max_wait garante que o script termine, em vez de rodar para sempre atrás de uma tarefa travada.

Baixar o vídeo finalizado

Depois de obter a URL de saída, grave em disco em streaming, em vez de carregar o arquivo inteiro na memória:

def download_video(output_url: str, path: str = "result.mp4") -> str:
    with requests.get(output_url, stream=True, timeout=120) as response:
        response.raise_for_status()
        with open(path, "wb") as handle:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    handle.write(chunk)
    return path

Juntando as peças:

job_id = submit_video_job(
    image_ref="https://your-host.example/first-frame.jpg",
    prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
)
output_url = wait_for_video(job_id)
saved = download_video(output_url, "kandinsky_result.mp4")
print(f"saved to {saved}")

Em produção, persista o job_id no momento em que o envio for bem-sucedido. Se o processo reiniciar, você pode retomar o loop de polling com o identificador armazenado, sem pagar por um novo envio.

Solucionar erros comuns de requisição e de tarefa

A maioria das falhas se enquadra em três categorias: chave, imagem ou estado da tarefa. Isole a categoria antes de mudar qualquer outra coisa.

Chave rejeitada

Sintoma: erro de autenticação ou autorização antes de criar qualquer tarefa.

  • Confirme que a variável está de fato exportada no shell atual: echo "$HIAPI_API_KEY".
  • Verifique se você colou espaços ou quebras de linha junto com a chave; remova-os.
  • Confirme que o cabeçalho está escrito Authorization e que o valor começa com Bearer seguido de um espaço.
  • Se o curl funciona mas o Python não, imprima os.environ.get("HIAPI_API_KEY") a partir do mesmo interpretador — a variável pode existir no seu shell, mas não no ambiente herdado pelo script.

Imagem rejeitada

Sintoma: erro de validação no envio, ou tarefa que falha imediatamente.

  • Formato incorreto ou obscuro. Reexporte como JPEG ou PNG padrão e tente novamente. Perfis CMYK e codecs exóticos são culpados comuns.
  • URL inacessível. Abra a URL da sua imagem em uma janela anônima do navegador; se você não consegue obter os bytes, a API também não consegue.
  • Codificação inline corrompida. Se você fez a codificação base64 localmente, decodifique a string uma vez e confirme que é uma imagem válida antes de enviar.
  • Proporção de aspecto incompatível. Se o vídeo voltar cortado ou com barras pretas, alinhe aspect_ratio com o primeiro quadro, em vez de lutar com a saída depois.

Tarefa que não termina ou falha

Sintoma: o status permanece em queued/processing, ou reporta failed.

  • Leia o campo error. Tarefas com falha carregam uma mensagem que geralmente indica o campo ou condição problemática. Não adivinhe — registre o payload de status inteiro.
  • Respeite o design assíncrono. Esperar alguns segundos antes de verificar é normal. Um loop de retry apertado que desiste após dois segundos não é um mecanismo de status.
  • Limite o tempo de espera. Se a tarefa ultrapassar um limite razoável, trate como falha, exponha o id da tarefa e envie uma nova tarefa, em vez de consultar para sempre.
  • Compare com uma chamada comprovadamente boa. Se uma imagem personalizada falha, execute o curl exato do início deste tutorial com uma imagem pública pequena e um prompt curto. Se funcionar, o problema está na sua entrada; se também falhar, o problema está nas credenciais ou no formato da requisição.

Erro de download após sucesso

Se a tarefa reporta succeeded mas o download falha, a URL de saída pode ter expirado ou estar sujeita a controle de acesso. Consulte a tarefa novamente para obter uma nova localização de saída, em vez de repetir a URL expirada.

Trate essas categorias em ordem — chave, depois imagem, depois estado da tarefa — e cada erro se reduz rapidamente a uma causa. Esse é o ciclo completo: enviar o primeiro quadro, consultar até concluir, baixar o resultado.

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