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
Funcionalidades e cenários de uso do kling-4.0/text-to-video
kling-4.0/text-to-video é um modelo de vídeo generativo disponibilizado através da API unificada HiAPI. Você fornece um prompt de texto e ele retorna um clipe de vídeo — movimento, movimento de câmera e composição da cena são totalmente determinados pela sua descrição. Este é um endpoint de texto para vídeo: não há imagem de origem para animar, portanto o modelo tem total autonomia sobre o enquadramento e a aparência do sujeito.
Cenários de uso:
- Você precisa gerar clipes cinematográficos curtos a partir de um roteiro ou modelo de prompt — b-roll, trailers, concept boards, vídeos para redes sociais.
- Você deseja que áudio sincronizado seja gerado junto com o vídeo, em vez de obter um arquivo silencioso que precisa de trilha sonora na pós-produção.
- Você está construindo um pipeline no qual a geração de vídeo é apenas uma entre várias etapas (escrita de roteiro, preparação de materiais, publicação), portanto precisa de uma API HTTP em vez de uma interface Web.
No entanto, se você precisa de controle preciso quadro a quadro sobre um sujeito real específico (modelos de imagem para vídeo ou edição têm melhor desempenho nisso), ou se precisa de resposta síncrona na requisição do usuário, este modelo não é adequado — a geração de vídeo leva tempo, então este endpoint é assíncrono por design.
Como todas as requisições passam pela HiAPI, as credenciais, o formato de requisição/resposta e o ciclo de vida da tarefa são os mesmos independentemente do modelo usado na plataforma. Essa consistência é a razão prática para construir sobre ela: adicionar ou substituir modelos no futuro não exige reescrever a camada de autenticação ou polling.
Pré-requisitos e autenticação na HiAPI
Antes de enviar a primeira requisição, certifique-se de ter:
- Uma conta HiAPI e uma chave de API de projeto. Trate-a como confidencial — nunca a envie para repositórios de código, nunca a coloque no código do cliente.
- O cliente HTTP de sua escolha. Os exemplos abaixo usam
curlerequestsdo Python 3. - O identificador do modelo, exatamente como aparece no catálogo:
kling-4.0/text-to-video. Erros de digitação no nome do modelo são a causa mais comum de falha na primeira chamada.
As credenciais são enviadas como cabeçalho HTTP em cada requisição (incluindo as de polling). O padrão usual na HiAPI é o bearer token:
export HIAPI_API_KEY="your-api-key-here"
E então na requisição:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
Guarde a URL base e a chave em variáveis de ambiente ou em um gerenciador de segredos, em vez de codificá-las diretamente. Para desenvolvimento local, um arquivo .env com consulta via os.environ no Python é suficiente. Para serviços implantados, injete os segredos em tempo de execução.
Um hábito de configuração que vale a pena adquirir cedo: construa primeiro uma pequena chamada do tipo "quem sou eu" — qualquer requisição leve de autenticação — para confirmar que a chave e a URL base estão corretas antes de depurar tarefas de vídeo. Isolar a autenticação da lógica do modelo economiza tempo no futuro.
Uma requisição curl executável
A chamada mínima cria uma tarefa e retorna o identificador da tarefa. A estrutura é:
curl -X POST "$HIAPI_BASE_URL/video/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-4.0/text-to-video",
"prompt": "A slow aerial push over a rain-soaked Tokyo alley at night, neon signs reflecting in puddles, steam rising from vents, shallow depth of field, cinematic color grading",
"generate_audio": true
}'
Interpretação campo a campo do corpo da requisição:
model— o identificador do modelo. Obrigatório.prompt— a descrição da sua cena. A maior parte do seu orçamento de qualidade está aqui; consulte a seção sobre prompts.generate_audio— solicita a geração de áudio sincronizado junto com o vídeo. Se você só precisa da faixa visual, omita ou defina como false.
A resposta é um objeto de tarefa, não o vídeo concluído. Espere um campo de status e um id que você usará para o polling — por exemplo, status queued ou processing, mais um id de tarefa. Armazene esse id imediatamente; se o seu processo terminar, o id é a única credencial do trabalho em andamento.
Duas dicas práticas. Primeiro, quando os prompts ficarem longos, salve o JSON em um arquivo e use -d @payload.json — o tratamento de quoting no shell para prompts multilinha é uma fonte comum de erros. Segundo, capture separadamente o corpo da resposta e o código de status HTTP (curl -s -w "\n%{http_code}") para distinguir requisições rejeitadas de falhas de rede.
Convertendo a requisição para Python
A mesma requisição em Python, com estrutura que pode ser usada diretamente em scripts reais:
import os
import requests
BASE_URL = os.environ["HIAPI_BASE_URL"].rstrip("/")
API_KEY = os.environ["HIAPI_API_KEY"]
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def create_video_job(prompt: str, generate_audio: bool = True) -> dict:
payload = {
"model": "kling-4.0/text-to-video",
"prompt": prompt,
"generate_audio": generate_audio,
}
resp = requests.post(
f"{BASE_URL}/video/generations",
headers=HEADERS,
json=payload,
timeout=30,
)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
job = create_video_job(
"A slow aerial push over a rain-soaked Tokyo alley at night, "
"neon signs reflecting in puddles, steam rising from vents, "
"shallow depth of field, cinematic color grading"
)
print(job)
Por que escrever assim:
requests.post(..., json=payload)cuida da serialização e do content type de uma vez, evitandojson.dumpsmanual.raise_for_status()converte 4xx/5xx em exceções capturáveis, em vez de analisar silenciosamente um corpo de erro como se fosse uma tarefa.timeouté obrigatório. Sem ele, uma conexão travada bloqueia o worker indefinidamente.- A configuração fica em constantes de módulo lidas do ambiente, de modo que a função é testável e reutilizável.
Esta função apenas cria a tarefa. Ela retorna imediatamente o handle da tarefa — que é exatamente o que você quer em um handler Web ou worker de fila. As seções seguintes mostram como aguardar o resultado.
Escrevendo prompts cinematográficos que resistem ao teste
Modelos de texto para vídeo recompensam estrutura. Um prompt que especifica sujeito, câmera, movimento e emoção sempre supera uma ideia de uma única frase, porque cada elemento elimina uma ambiguidade que o modelo decidiria aleatoriamente.
Um template útil:
[sujeito e cena], [posição da câmera e movimento],
[movimento dentro do quadro], [iluminação], [atmosfera ou color grading], [referência de estilo]
Exemplo de aplicação:
Ao amanhecer, um ciclista solitário de capa de chuva amarela atravessa uma ponte de pedra, câmera baixa acompanhando em paralelo na altura das rodas, névoa flutuando sobre a água, luz suave de hora azul com toques quentes de lanternas, calmo e levemente melancólico, textura de lente anamórfica widescreen.
O papel de cada parte:
- Sujeito e cena — substantivos concretos são melhores que conceitos abstratos. "Um ciclista solitário de capa de chuva amarela" dá ao modelo algo para renderizar; "liberdade" não.
- Câmera — posição (
câmera baixa,aérea,no nível dos olhos) e movimento (acompanhamento,push-in lento,estática) são as alavancas mais poderosas para o valor de produção visual. - Movimento dentro do quadro — névoa flutuando, tecido balançando, ondulações na água. Vídeo precisa de movimento; declare-o explicitamente.
- Iluminação e atmosfera — hora do dia, temperatura de cor, tom emocional. Mantenha-os coerentes entre si.
- Estilo — linguagem de lente ou formato (
lente anamórfica,profundidade de campo rasa,color grading cinematográfico) molda a textura de forma mais confiável do que nomear um diretor.
Mantenha o prompt como algumas frases de descrição densa, em vez de um parágrafo de ideias concorrentes. Se um plano exige duas ações claramente distintas, gere dois clipes. E itere: mude uma variável por vez — primeiro a câmera, depois a iluminação — para entender a que o modelo responde, em vez de adivinhar.
Tratando tarefas assíncronas e polling
A geração de vídeo não é instantânea, então o padrão é criar primeiro, depois fazer polling. Você já tem a parte de criação; aqui está o laço:
import time
def wait_for_job(job_id: str, timeout: int = 600) -> dict:
deadline = time.monotonic() + timeout
delay = 2.0
while time.monotonic() < deadline:
resp = requests.get(
f"{BASE_URL}/video/generations/{job_id}",
headers=HEADERS,
timeout=30,
)
resp.raise_for_status()
job = resp.json()
status = job.get("status")
if status == "succeeded":
return job
if status in ("failed", "cancelled"):
raise RuntimeError(f"Job {job_id} ended with status {status}: {job}")
time.sleep(delay)
delay = min(delay * 1.5, 15.0) # back off, cap at 15s
raise TimeoutError(f"Job {job_id} did not finish in {timeout}s")
Decisões de design importantes em produção:
Faça polling com backoff, não em loop apertado
Comece com intervalo curto e aumente gradualmente — o backoff exponencial acima tem teto em um limite fixo. Polling rápido contínuo consome seu rate limit sem benefício, porque o tempo de geração não diminui só porque você perguntou mais cedo.
Sempre defina um prazo final
Todo laço de polling precisa de tempo máximo de relógio e de um erro explícito ao ultrapassá-lo. Caso contrário, uma tarefa travada ocupa um worker para sempre silenciosamente.
Trate estados terminais como definitivos
Distinga estados em andamento (queued, processing) de estados terminais (succeeded, failed, cancelled). Só retorne a saída em caso de sucesso; outros estados devem lançar exceção ou seguir para um caminho de retry, em vez de continuar o laço.
Desacople o polling do handler de requisições
Em um servidor Web, não deixe a resposta HTTP bloquear esperando o vídeo. Crie a tarefa, devolva o id ao cliente e faça o polling a partir de um worker em background ou consumidor de fila. Persista o id da tarefa e seu último estado conhecido, para que reinícios não percam o rastreamento do trabalho em andamento.
Baixando e validando a saída
Quando a tarefa atinge succeeded, a resposta traz uma referência à mídia gerada — geralmente uma URL para o arquivo concluído. Baixe prontamente e trate essa URL como temporária: obtenha, armazene e registre sua própria localização persistente, em vez de passar a URL do provedor diretamente ao usuário final.
import pathlib
def download_output(job: dict, dest: pathlib.Path) -> pathlib.Path:
url = job["output"]["video_url"]
with requests.get(url, stream=True, timeout=120) as r:
r.raise_for_status()
dest.parent.mkdir(parents=True, exist_ok=True)
with open(dest, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 20):
f.write(chunk)
return dest
Etapas de validação que valem a pena antes de entregar o arquivo a qualquer pessoa:
- Verifique se a transferência foi concluída. Faça streaming em chunks, compare o tamanho gravado com o
Content-Length(se presente) e falhe ruidosamente em caso de leitura insuficiente. - Confirme a faixa de áudio. Se você solicitou
generate_audio, o arquivo deve ter um stream de áudio. Uma verificação rápida comffprobeé o teste mais barato:
ffprobe -v error -show_entries stream=codec_type -of csv=p=0 output.mp4
Você deve ver tanto a linha video quanto a linha audio. Se o áudio estiver ausente, verifique se a flag foi definida na chamada de criação — não é possível adicioná-lo depois.
- Faça uma validação básica de duração e resolução em relação à sua expectativa, para capturar renders truncados ou com especificações erradas antes da publicação.
- Armazene com chave determinística (id da tarefa mais hash), grave primeiro em um caminho temporário, renomeie após o sucesso e mantenha o id da tarefa junto ao ativo para rastreabilidade.
Se o download falhar no meio da transferência, tente novamente com backoff; se a URL tiver expirado, você precisará buscar novamente o registro da tarefa para obter uma nova referência.
Encapsulando em um cliente reutilizável
As partes acima formam naturalmente uma classe. Juntando tudo, você obtém algo importável entre projetos, sem precisar copiar:
class KlingTextToVideo:
def __init__(self, base_url: str, api_key: str):
self.base_url = base_url.rstrip("/")
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
def generate(self, prompt: str, generate_audio: bool = True,
timeout: int = 600) -> dict:
job = create_video_job(prompt, generate_audio) # create half
return wait_for_job(job["id"], timeout=timeout) # poll half
À medida que o cliente amadurece, algumas coisas precisam ser adicionadas:
- Logs estruturados com o id da tarefa como chave — transições de status, número de pollings, tempo decorrido e falhas. Quando um render sai errado, o id da tarefa é a chave de correlação entre os logs.
- Retries limitados apenas para erros transitórios (rede, 5xx). Nunca repita cegamente uma requisição rejeitada; um corpo de requisição malformado falhará da mesma forma todas as vezes, apenas desperdiçando cota.
- Idempotência na sua camada. Se o seu serviço pode enviar o mesmo prompt duas vezes, deduplique antes de chamar a criação, em vez de pagar por duas tarefas.
- Mantenha templates de prompt como dados, não como código. Coloque os templates cinematográficos em arquivos de configuração, para que a iteração de prompts não exija deploy.
- Contabilize custos por segundo de saída. A cobrança é baseada no uso de saída gerado, então rastreie a duração gerada por tarefa para atribuir gastos a funcionalidades ou usuários.
Com o cliente pronto, o pipeline é curto: construa o prompt a partir do template, chame generate, baixe e inspecione a saída, depois entregue o arquivo armazenado à sua aplicação. Se você adicionar outros modelos na HiAPI no futuro, os mesmos cabeçalhos de autenticação, ciclo de vida de tarefa e padrão de download se aplicam — essa é a principal razão para construir a camada de abstração uma única vez.
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
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