HiAPI
Blogue

Tutorial

Como usar a API de imagem para vídeo do Kling 2.5 Turbo (curl + Python)

Um passo a passo executável de geração de vídeo a partir do primeiro quadro: criar tarefa, consultar tarefa, baixar o MP4 — com o schema de entrada estrito listado por completo.

Oct 21, 2026
Como usar a API de imagem para vídeo do Kling 2.5 Turbo (curl + Python)

TL;DR

  • kling-2.5-turbo/image-to-video converte uma imagem de primeiro quadro em um clipe de 5 ou 10 segundos; passar a URL de uma segunda imagem fixa o último quadro. O modelo roda na API de tarefas assíncronas da HiAPI — primeiro POST /v1/tasks para criar a tarefa, depois consultar GET /v1/tasks/{taskId} para obter o MP4 gerado.
  • O custo da saída é $0.06 por segundo: clipe de 5 segundos $0.30, clipe de 10 segundos $0.60. A cobrança é feita por segundo de saída concluído; tarefas que falham por entrada inválida não produzem saída e não são cobradas.
  • O schema de entrada é estrito e fechado. Obrigatórios: image_urls (array, 1–2 itens — atenção ao plural), prompt, duration (apenas 5 ou 10). Opcionais: aspect_ratio, negative_prompt, cfg_scale. A forma singular image_url é rejeitada diretamente.
  • O modelo já está disponível na HiAPI: abra a página do modelo para experimentar no navegador antes de integrar a API abaixo.

O que você vai construir e o que precisa preparar

Ao final deste artigo, você terá uma chamada funcional de primeiro quadro → vídeo: enviar a imagem e o prompt de movimento, consultar a tarefa, baixar o MP4. Primeiro você precisa de duas coisas:

  1. Uma API Key obtida no painel da HiAPI — toda requisição deve ser enviada no formato Authorization: Bearer sk-.... Se ainda não criou uma, consulte a documentação de autenticação.
  2. Uma URL de imagem de primeiro quadro publicamente acessível. A chamada de criação verifica apenas a estrutura da entrada; a imagem só é buscada quando a tarefa executa, portanto URLs de localhost ou privadas criam uma tarefa que falha em seguida (veja detalhes abaixo).

Isto é imagem para vídeo, então o id do modelo é kling-2.5-turbo/image-to-video. Se você quer gerar vídeo apenas a partir de um prompt, existe um endpoint de texto para vídeo separado.

Exemplo mínimo executável (curl)

Crie a tarefa. O nome do modelo fica no nível superior; tudo que o modelo lê fica dentro de input:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-2.5-turbo/image-to-video",
    "input": {
      "prompt": "The perfume bottle rotates slowly on the marble stand, light glints across the glass, petals drift down, slow orbit",
      "image_urls": ["https://static.hiapi.ai/gallery/2026/10/4852c542c4447593.jpg"],
      "duration": 5,
      "aspect_ratio": "9:16"
    }
  }'

A criação bem-sucedida retorna um id de tarefa — não o vídeo:

{ "code": 200, "data": { "taskId": "tk-hiapi-01M5CW..." }, "message": "success" }

Depois consulte o endpoint de detalhes até que status atinja um estado terminal:

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01M5CW... \
  -H "Authorization: Bearer sk-YOUR_KEY"

Enquanto a tarefa executa você verá estados não terminais; ao concluir, a URL do MP4 fica em data.output[0].url:

{
  "code": 200,
  "data": {
    "status": "success",
    "model": "kling-2.5-turbo/image-to-video",
    "storage": "temp",
    "output": [{ "url": "https://temp.hiapi.ai/kling-i2v/tk-hiapi-01M5CW.mp4?expireAt=1761350400" }]
  },
  "message": "success"
}

O output[0].url é um link temporário — baixe imediatamente em vez de usá-lo como hotlink direto na sua aplicação (veja Considerações para produção).

Exemplo mínimo executável (Python)

Sem SDK — a API de tarefas da HiAPI é uma interface HTTP pura, então a biblioteca padrão já basta:

import time
import requests

API = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-YOUR_KEY", "Content-Type": "application/json"}


def create(image_url: str, prompt: str, duration: int = 5) -> str:
    payload = {
        "model": "kling-2.5-turbo/image-to-video",
        "input": {
            "prompt": prompt,
            "image_urls": [image_url],   # 1–2 items; 2nd = last frame
            "duration": duration,        # 5 or 10 only
        },
    }
    r = requests.post(API, json=payload, headers=HEADERS, timeout=60)
    body = r.json()
    task_id = (body.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"create failed: {body}")
    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"{API}/{task_id}", headers=HEADERS, timeout=30)
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(interval)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")


task_id = create(
    "https://static.hiapi.ai/gallery/2026/10/4852c542c4447593.jpg",
    "slow orbit around the product, light glints across the glass, petals drift down",
    duration=5,
)
mp4_url = wait(task_id)

# Download immediately — the URL is short-lived.
with requests.get(mp4_url, stream=True, timeout=120) as resp:
    resp.raise_for_status()
    with open("clip.mp4", "wb") as f:
        for chunk in resp.iter_content(1 << 16):
            f.write(chunk)
print("saved clip.mp4")

Considerações para produção

Polling ou callback. Consultar a cada 5 segundos (como mostrado acima) é o caminho mais simples e é o que o exemplo usa. Se você prefere receber o resultado por push, a chamada de criação aceita um objeto callback no nível superior — {"url": "https://you/webhook", "when": "final"} — e a HiAPI envia um POST para o seu endpoint quando a tarefa atinge um estado terminal. O contrato exato do webhook está na documentação de criação de tarefa; para a maioria das tarefas de clipe único, consultar o endpoint de detalhes da tarefa já é suficiente.

Sempre ramifique com base em data.status, nunca no código de status HTTP da chamada de criação. A criação retornar 200 significa aceito, não renderizado. O clipe só existe de fato quando o endpoint de detalhes retorna status: "success".

Trate a URL de saída como um link temporário. O storage é temp e a URL expira, então baixe o MP4 assim que a tarefa for concluída com sucesso (ou copie-o para o seu próprio bucket). Não entregue a URL da HiAPI diretamente aos usuários finais.

Controle de custos. Você paga por segundo de saída concluído — $0.06/segundo — portanto um clipe de 5 segundos custa $0.30 e um de 10 segundos custa $0.60. Durante a iteração de prompts e do primeiro quadro, renderize primeiro em 5 segundos e, quando estiver satisfeito, execute novamente em 10 segundos. Os preços mais recentes estão na página de preços.

Notas de teste e armadilhas

Todo o conteúdo deste artigo vem de requisições reais ao endpoint em produção (schema revalidado em 2026-10-21), e não apenas de uma tabela de parâmetros:

  • O campo é image_urls (plural), e o schema é fechado. Enviar o aparentemente natural image_url falha antes da criação da tarefa:
    { "code": 400, "error_code": "INVALID_REQUEST",
      "message": "invalid input: image_urls: missing required field \"image_urls\"; <root>: additional properties 'image_url' not allowed" }
    
    Qualquer campo não reconhecido (mode, erros de digitação etc.) é rejeitado da mesma forma — não existem campos extras silenciosamente ignorados.
  • duration é um enum, não um intervalo. Só aceita 5 e 10; 7 retorna duration: value must be one of 5, 10.
  • image_urls contém 1 ou 2 itens. Uma URL é o primeiro quadro; a segunda URL fixa o último quadro, permitindo uma transição controlada. Três URLs retornam maxItems: got 3, want 2; um array vazio retorna minItems: got 0, want 1.
  • Campos opcionais que realmente existem: aspect_ratio só aceita 16:9, 9:16, 1:1, 4:3, 3:4, 21:9; cfg_scale tem limite de 1 (passar 99 retorna cfg_scale: maximum: got 99, want 1); negative_prompt deve ser uma string. Omitir aspect_ratio faz o modelo seguir o seu primeiro quadro.
  • A chamada de criação valida apenas a estrutura, não a acessibilidade — esta é a armadilha mais comum. Uma URL de imagem sintaticamente válida mas inacessível retorna 200 e um taskId, e em seguida a tarefa falha de forma assíncrona:
    { "data": { "status": "fail",
      "error": { "code": "INVALID_REQUEST",
        "message": "The image URL is not readable. Please provide a valid public HTTP(S) URL or an accessible file path and try again." } } }
    
    Essa tarefa não produziu output e não foi cobrada — falhas não geram custo —, mas se você verificar apenas a resposta de criação, vai achar que deu certo. É justamente por isso que o loop de polling verifica data.status.

Conteúdo relacionado

Perguntas frequentes

Qual o comprimento máximo do clipe? 5 ou 10 segundos — são os únicos dois valores de duration aceitos pelo schema.

Posso controlar o final? Sim. Coloque duas URLs em image_urls: a primeira é o quadro de abertura, a segunda é o último quadro. O modelo interpola o movimento entre as duas.

Por que a criação retorna 200, mas a tarefa mostra fail? A chamada de criação só verifica se o seu JSON está em conformidade com o schema. A imagem só é buscada quando a tarefa executa, então uma URL inacessível ou privada cria a tarefa e depois faz a tarefa falhar. Sempre leia data.status no endpoint de detalhes e garanta que a URL do primeiro quadro seja publicamente acessível.

Tarefas com falha são cobradas? Não. Você é cobrado por segundo de saída concluído, portanto tarefas que falham por entrada inválida não produzem output e não são cobradas.

Há controle de proporção? aspect_ratio é opcional e aceita 16:9, 9:16, 1:1, 4:3, 3:4 ou 21:9. Se deixado em branco, segue o seu primeiro quadro.

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