Tutorial
API FLUX 3 Max: geração de vídeo a partir de texto, de imagem para vídeo e keyframes no hiapi
Três IDs de modelo, um fluxo /v1/tasks: curl, script auxiliar em Python, regras da linha do tempo de keyframes e erros de validação reais.
Resumo
- O FLUX 3 Max no hiapi são três IDs de modelo independentes no mesmo endpoint
POST /v1/tasks:flux-3-max/text-to-video,flux-3-max/image-to-videoeflux-3-max/keyframes-to-video. Alternar de modo exige apenas trocarmodele um campo de entrada. - Os três geram clipes de 5–20 segundos em 720p ou 1080p, cobrados por segundo de saída e por resolução. Consulte os preços em tempo real em /en/pricing.
- As regras de numeração de frames dos keyframes não são verificadas no momento do envio. Com uma linha do tempo incorreta, a API ainda retorna HTTP 200 e
taskId, mas a tarefa falha após cerca de 2 segundos. Valide localmente antes de enviar.
Este guia é específico para o nível Max. Para o modelo base flux-3, com modo rascunho e continuação de vídeo, veja o guia da API de vídeo FLUX.3; para editar material existente, veja edição de vídeo com flux-3.
Pré-requisitos
Crie uma chave no console do hiapi e exporte-a:
export HIAPI_KEY=sk-your-key
O fluxo de requisição é igual para todos os modos: POST /v1/tasks retorna um taskId; em seguida, faça polling em GET /v1/tasks/<taskId> (ou use callback) até que status seja success e baixe data.output[0].url.
Qual ID de modelo usar para cada entrada
| Você tem como entrada | ID do modelo | Campo de entrada a alterar |
|---|---|---|
| Apenas um prompt de texto | flux-3-max/text-to-video |
prompt |
| Uma imagem estática (opcionalmente, mais uma imagem de quadro final) | flux-3-max/image-to-video |
image_url, opcionalmente end_image_url |
| 1–10 imagens que devem aparecer em momentos específicos | flux-3-max/keyframes-to-video |
keyframes: [{image_url, frame_index}] |
Campos opcionais compartilhados pelos três: duration (segundos inteiros, 5–20, padrão 5), resolution (720p ou 1080p), aspect_ratio (auto, 21:9, 2:1, 16:9, 4:3, 1:1, 3:4, 9:16), generate_audio (booleano, ativado por padrão) e reasoning_level (low ou high, padrão high). Páginas dos modelos: texto para vídeo, imagem para vídeo, keyframes para vídeo.
Exemplo mínimo: texto para vídeo com curl
curl -X POST "https://api.hiapi.ai/v1/tasks" \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-3-max/text-to-video",
"input": {
"prompt": "a slow aerial shot of ocean waves at sunrise, photorealistic",
"duration": 5,
"resolution": "720p",
"generate_audio": false,
"reasoning_level": "low"
}
}'
Quando a requisição é válida, retorna {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}. Em seguida:
curl https://api.hiapi.ai/v1/tasks/tk-hiapi-... -H "Authorization: Bearer $HIAPI_KEY"
A configuração com generate_audio desativado e 5 segundos de raciocínio low é uma forma barata de testar prompts; a página do modelo indica que o áudio não altera o preço.
Um script auxiliar em Python para os três modos
# pip install requests
import os, time, requests
KEY = os.environ["HIAPI_KEY"]
H = {"Authorization": f"Bearer {KEY}"}
BASE = "https://api.hiapi.ai/v1/tasks"
def submit(mode: str, **inp) -> str:
"""mode: text-to-video | image-to-video | keyframes-to-video"""
body = {"model": f"flux-3-max/{mode}", "input": inp}
res = requests.post(BASE, json=body, headers=H, timeout=30).json()
if res.get("code") != 200:
# sync 400s look like {"code":400,"error_code":"INVALID_REQUEST","message":"invalid input: ..."}
raise RuntimeError(res)
return res["data"]["taskId"]
def wait(task_id: str, timeout_s: int = 900, every: int = 10) -> str:
deadline = time.time() + timeout_s
while time.time() < deadline:
d = requests.get(f"{BASE}/{task_id}", headers=H, timeout=30).json()["data"]
if d["status"] == "success":
return d["output"][0]["url"]
if d["status"] == "fail":
raise RuntimeError(d.get("error"))
time.sleep(every)
raise TimeoutError(task_id)
# 1) text-to-video
t2v = submit("text-to-video",
prompt="A single white sneaker rotates slowly on a wet black plinth, studio softbox lighting, macro product shot",
duration=5, resolution="720p", aspect_ratio="16:9", generate_audio=False)
# 2) image-to-video: first frame, optional last frame
i2v = submit("image-to-video",
prompt="Morning mist drifts over the harbor; the boats rock gently and the camera slowly pushes forward.",
image_url="https://example.com/harbor.jpg",
# end_image_url="https://example.com/harbor-end.jpg", # optional fixed ending
duration=5, resolution="720p", generate_audio=False)
# 3) keyframes-to-video
FPS = 24
def keyframes_ok(duration: int, frames: list[dict]) -> None:
idx = [f["frame_index"] for f in frames]
assert 1 <= len(frames) <= 10, "1-10 keyframes"
assert len(set(idx)) == len(idx), "frame_index must be unique"
assert all(0 <= i <= duration * FPS for i in idx), f"frame_index must be 0..{duration * FPS}"
frames = [
{"image_url": "https://example.com/harbor.jpg", "frame_index": 0},
{"image_url": "https://example.com/latte.jpg", "frame_index": 120},
]
keyframes_ok(5, frames)
kf = submit("keyframes-to-video",
prompt="A continuous cinematic morph from the misty harbor into a close-up of an iced matcha latte.",
keyframes=frames, duration=5, resolution="720p", generate_audio=False)
url = wait(kf)
open("clip.mp4", "wb").write(requests.get(url).content)
As URLs de saída expiram, portanto, após a tarefa ser concluída com sucesso, baixe ou copie o arquivo imediatamente, em vez de guardar o link.
Keyframes: como funciona a linha do tempo
frame_index é uma posição em um relógio de 24 fps que começa em 0, e não uma porcentagem. O valor máximo permitido é duration × 24: 120 para 5 segundos, 240 para 10 segundos, 480 para 20 segundos. Os índices devem ser únicos e é possível enviar de 1 a 10 keyframes. Para uma transição limpa de A para B, coloque o primeiro ponto de ancoragem em 0 e o último em duration × 24; adiantar o último ponto de ancoragem mantém o final, enquanto atrasá-lo comprime a mudança. Mantenha a proporção de tela igual em todos os keyframes; para um loop contínuo, faça as imagens inicial e final parecerem o mesmo instante.
Considerações para produção
- Polling ou callback. A API de tarefas aceita
callback.urlewhen: "final", então não é preciso fazer polling; fazer polling a cada 10 segundos, como acima, também funciona bem para scripts e tarefas em lote. - Defina sempre um timeout no loop de polling e persista o
taskIdantes de fazer polling, para que uma falha do programa não faça você perder uma tarefa já paga. - Baixe imediatamente. Trate
output[0].urlcomo de validade curta. - Controle de custos. A cobrança é por segundo de saída e por resolução, então um clipe de 20 segundos em 1080p custa várias vezes mais que um teste de 5 segundos em 720p. Prototipe primeiro com 5 segundos e 720p e aumente ambos depois que o prompt funcionar. Consulte as tarifas atuais na página de preços.
O que testei e o que não testei
Essas verificações foram feitas em 23 de outubro de 2026 contra a API de produção usando uma chave de teste somente leitura. Este artigo não renderizou clipes completos, portanto não faço nenhuma afirmação sobre a qualidade da saída; os prompts de exemplo vêm dos exemplos incluídos nas páginas dos modelos.
Validação síncrona (HTTP 400, não enfileirado). Valores fora do intervalo são rejeitados no momento do envio, retornando error_code: INVALID_REQUEST e uma message legível:
| Requisição | message da resposta |
|---|---|
duration: 3 |
invalid input: duration: minimum: got 3, want 5 |
resolution: "4k" |
value must be one of '720p', '1080p' |
aspect_ratio: "5:4" |
value must be one of 'auto', '21:9', '2:1', '16:9', '4:3', '1:1', '3:4', '9:16' |
reasoning_level: "medium" |
value must be one of 'low', 'high' |
image-to-video usando image_urls em vez de image_url |
image_url: missing required field "image_url"; ... additional properties 'image_urls' not allowed |
A última linha é um erro comum: outros modelos de entrada de imagem do hiapi usam o campo no plural, mas o FLUX 3 Max image-to-video aceita apenas um único image_url. Campos desconhecidos são rejeitados, não ignorados.
Erros na linha do tempo de keyframes são assíncronos. Enviei duas requisições de keyframes de 5 segundos, ambas com problemas na linha do tempo: uma usava frame_index: 121 (acima do limite de 120) e a outra tinha dois keyframes em frame_index: 0. Ambas foram aceitas, retornando HTTP 200 e taskId. Cerca de 1–2 segundos após a criação, o polling retornou o estado final:
{"code":200,"data":{"status":"fail","model":"flux-3-max/keyframes-to-video",
"error":{"code":"INVALID_REQUEST","message":"Invalid request parameters for this model. Please check the request and try again."},
"taskId":"tk-hiapi-..."},"message":"success"}
Duas conclusões decorrem disso. Primeiro, um envio que retorna 200 não significa que a linha do tempo seja válida, então verifique status e error.code ao fazer polling. Segundo, a mensagem de falha é genérica e não indica qual frame tem problema, e é por isso que vale a pena executar a verificação keyframes_ok acima antes de enviar. A página do modelo informa que tarefas com falha não são cobradas; não verifiquei o registro de cobrança dessas duas tarefas.
Perguntas frequentes
Qual ID de modelo devo usar para quadro inicial mais quadro final? Use flux-3-max/image-to-video, passando image_url e end_image_url. Use keyframes apenas quando precisar de pontos de ancoragem entre o início e o fim.
Adicionar mais keyframes custa mais caro? Segundo a página do modelo, não: a cobrança é por segundo de saída e por resolução, e a quantidade de pontos de ancoragem não afeta o preço.
Qual é a diferença em relação ao flux-3? flux-3-max/* são IDs de modelo independentes, divididos por modo (texto, imagem, keyframes); já o flux-3 base é um único ID que alterna de modo conforme a entrada e também oferece modo rascunho e continuação. Veja o guia da API de vídeo FLUX.3. Não comparei a qualidade de saída dos dois, então escolha com base nos recursos e nas tarifas da página de preços.
Posso usar outro modelo de imagem para vídeo? Sim. Veja outras opções de imagem para vídeo em como usar a API de imagem para vídeo do Ray 3.2.
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