curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-omni-1.2-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 15
}'
import time
import requests
base_url = "https://api.apimart.ai"
headers = {"Authorization": "Bearer <token>"}
payload = {
"model": "gemini-omni-1.2-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 15,
}
response = requests.post(
f"{base_url}/v1/videos/generations",
headers=headers, json=payload, timeout=30,
)
response.raise_for_status()
task_id = response.json()["data"][0]["task_id"]
print(task_id)
deadline = time.monotonic() + 600
while time.monotonic() < deadline:
response = requests.get(
f"{base_url}/v1/tasks/{task_id}", headers=headers, timeout=30,
)
response.raise_for_status()
task = response.json()["data"]
if task["status"] == "completed":
print(task["result"]["videos"][0]["url"][0])
break
if task["status"] == "failed":
raise RuntimeError(task["error"]["message"])
time.sleep(5)
else:
raise TimeoutError(f"Continue polling task {task_id}")
const baseUrl = "https://api.apimart.ai";
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
const response = await fetch(`${baseUrl}/v1/videos/generations`, {
method: "POST",
headers,
signal: AbortSignal.timeout(30_000),
body: JSON.stringify({
model: "gemini-omni-1.2-flash",
prompt: "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
aspect_ratio: "16:9",
resolution: "720p",
duration: 15,
}),
});
if (!response.ok) throw new Error(await response.text());
const taskId = (await response.json()).data[0].task_id;
console.log(taskId);
async function waitForTask(taskId) {
const deadline = Date.now() + 600_000;
while (Date.now() < deadline) {
const response = await fetch(`${baseUrl}/v1/tasks/${taskId}`, {
headers,
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) throw new Error(await response.text());
const task = (await response.json()).data;
if (task.status === "completed") return task.result.videos[0].url[0];
if (task.status === "failed") throw new Error(task.error.message);
await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error(`Continue polling task ${taskId}`);
}
console.log(await waitForTask(taskId));
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01EXAMPLE"
}
]
}
Gemini Omni 1.2 Flash
Geração de vídeo Gemini Omni 1.2 Flash
Vídeos a partir de texto ou imagens, referências de personagens, interpolação de quadros inicial/final, edição e extensão. Até 4K, 24fps, com áudio.
POST
/
v1
/
videos
/
generations
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-omni-1.2-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 15
}'
import time
import requests
base_url = "https://api.apimart.ai"
headers = {"Authorization": "Bearer <token>"}
payload = {
"model": "gemini-omni-1.2-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 15,
}
response = requests.post(
f"{base_url}/v1/videos/generations",
headers=headers, json=payload, timeout=30,
)
response.raise_for_status()
task_id = response.json()["data"][0]["task_id"]
print(task_id)
deadline = time.monotonic() + 600
while time.monotonic() < deadline:
response = requests.get(
f"{base_url}/v1/tasks/{task_id}", headers=headers, timeout=30,
)
response.raise_for_status()
task = response.json()["data"]
if task["status"] == "completed":
print(task["result"]["videos"][0]["url"][0])
break
if task["status"] == "failed":
raise RuntimeError(task["error"]["message"])
time.sleep(5)
else:
raise TimeoutError(f"Continue polling task {task_id}")
const baseUrl = "https://api.apimart.ai";
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
const response = await fetch(`${baseUrl}/v1/videos/generations`, {
method: "POST",
headers,
signal: AbortSignal.timeout(30_000),
body: JSON.stringify({
model: "gemini-omni-1.2-flash",
prompt: "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
aspect_ratio: "16:9",
resolution: "720p",
duration: 15,
}),
});
if (!response.ok) throw new Error(await response.text());
const taskId = (await response.json()).data[0].task_id;
console.log(taskId);
async function waitForTask(taskId) {
const deadline = Date.now() + 600_000;
while (Date.now() < deadline) {
const response = await fetch(`${baseUrl}/v1/tasks/${taskId}`, {
headers,
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) throw new Error(await response.text());
const task = (await response.json()).data;
if (task.status === "completed") return task.result.videos[0].url[0];
if (task.status === "failed") throw new Error(task.error.message);
await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error(`Continue polling task ${taskId}`);
}
console.log(await waitForTask(taskId));
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01EXAMPLE"
}
]
}
A geração a partir de texto ou imagens aceita segundos inteiros de 3 a 15, com padrão 10. A interpolação inicial/final e o trecho adicionado na extensão permitem até 10 segundos. A edição ignora
duration e mantém a duração do vídeo de origem. Entradas de vídeo são editadas por padrão; a extensão exige "omni_reference_task_type": "extend".curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "gemini-omni-1.2-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 15
}'
import time
import requests
base_url = "https://api.apimart.ai"
headers = {"Authorization": "Bearer <token>"}
payload = {
"model": "gemini-omni-1.2-flash",
"prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 15,
}
response = requests.post(
f"{base_url}/v1/videos/generations",
headers=headers, json=payload, timeout=30,
)
response.raise_for_status()
task_id = response.json()["data"][0]["task_id"]
print(task_id)
deadline = time.monotonic() + 600
while time.monotonic() < deadline:
response = requests.get(
f"{base_url}/v1/tasks/{task_id}", headers=headers, timeout=30,
)
response.raise_for_status()
task = response.json()["data"]
if task["status"] == "completed":
print(task["result"]["videos"][0]["url"][0])
break
if task["status"] == "failed":
raise RuntimeError(task["error"]["message"])
time.sleep(5)
else:
raise TimeoutError(f"Continue polling task {task_id}")
const baseUrl = "https://api.apimart.ai";
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
const response = await fetch(`${baseUrl}/v1/videos/generations`, {
method: "POST",
headers,
signal: AbortSignal.timeout(30_000),
body: JSON.stringify({
model: "gemini-omni-1.2-flash",
prompt: "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
aspect_ratio: "16:9",
resolution: "720p",
duration: 15,
}),
});
if (!response.ok) throw new Error(await response.text());
const taskId = (await response.json()).data[0].task_id;
console.log(taskId);
async function waitForTask(taskId) {
const deadline = Date.now() + 600_000;
while (Date.now() < deadline) {
const response = await fetch(`${baseUrl}/v1/tasks/${taskId}`, {
headers,
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) throw new Error(await response.text());
const task = (await response.json()).data;
if (task.status === "completed") return task.result.videos[0].url[0];
if (task.status === "failed") throw new Error(task.error.message);
await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error(`Continue polling task ${taskId}`);
}
console.log(await waitForTask(taskId));
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01EXAMPLE"
}
]
}
Autenticação
string
obrigatório
Use autenticação Bearer Token. Obtenha uma chave na página de gerenciamento de API Keys e envie solicitações com
Content-Type: application/json.Parâmetros da solicitação
string
obrigatório
Deve ser
gemini-omni-1.2-flash.string
obrigatório
Instruções de texto obrigatórias: descreva a cena para texto em vídeo, ou movimentos, estilo e alterações para os demais modos.
prompt é obrigatório mesmo com imagens de referência, quadros inicial/final, vídeo ou extend_from_task_id. Omiti-lo retorna HTTP 400.integer
padrão:"10"
Duração da saída para geração a partir de texto ou imagens, inteiro de
3 a 15, com padrão 10. A interpolação inicial/final e a extensão aceitam apenas 3–10 segundos. Na extensão, representa a duração do trecho adicionado; o vídeo retornado inclui o original e o novo trecho. A edição ignora duration e mantém a duração do vídeo de origem. Valores do parâmetro fora da faixa fazem a tarefa falhar com invalid_duration.string
padrão:"720p"
360p / 720p / 1080p / 4k, sem diferenciar maiúsculas; 2160p equivale a 4k. As saídas 1080p e 4k são ampliadas por upsampling. A resolução afeta os tokens de saída e o saldo reservado. Outros valores fazem a tarefa falhar com invalid_resolution.string
padrão:"16:9"
Apenas
16:9 (horizontal, padrão) e 9:16 (vertical). Outros valores são tratados como 16:9.string[]
Imagens de referência apenas como URLs HTTP(S) diretas e acessíveis publicamente. Data URLs e Base64 não são aceitos. Uma imagem serve como quadro inicial; várias servem como referências de sujeitos. Até 10 imagens no total, incluindo os quadros inicial/final. Para personagens, recomenda-se no máximo 2 personagens com até 3 imagens cada, totalizando até 6 imagens.
string
Quadro inicial. Sozinho, define o início do vídeo; com
last_frame_image, ativa a interpolação entre os dois quadros. Somente URLs HTTP(S) diretas de imagem e acessíveis publicamente são aceitas.string
Quadro final; exige
first_frame_image, caso contrário a tarefa falha com invalid_frame_images. Use a mesma proporção nas duas imagens, correspondente a aspect_ratio. Somente URLs HTTP(S) diretas de imagem e acessíveis publicamente são aceitas.object[]
Imagens com funções, equivalentes aos campos diretos dos quadros inicial/final. Escolha uma forma de especificá-los. Todas as imagens usadas contam para o limite total de 10.
string[]
Vídeo para editar ou estender: no máximo 1 clipe de até 15 segundos. Somente URLs HTTP(S) diretas de vídeo e acessíveis publicamente são aceitas. Data URLs e Base64 não são aceitos. O padrão é editar.
string
padrão:"auto"
Tipo de tarefa:
auto (padrão, deduzido das entradas) / edit (edição) / extend (extensão) / reference (várias imagens de referência). Também aceita text_to_video / image_to_video / reference_to_video. Se omitido ou definido como auto, video_urls e extend_from_task_id editam por padrão. Para estender, informe extend explicitamente.string
ID de uma tarefa de geração anterior sua para reutilizar o vídeo sem novo upload. O padrão é editar. Com
"omni_reference_task_type": "extend", adiciona um trecho de até 10 segundos ao final.Recursos e limites
- A saída tem 24fps e inclui diálogos, música ou efeitos sonoros. Descreva o áudio desejado em
prompt. - Entrada de áudio, system prompt,
temperaturee parâmetros de prompt negativo não são suportados. Escreva as exclusões diretamente emprompt. - Restrições regionais do provedor: no EEE, na Suíça e no Reino Unido, não são suportadas a edição ou extensão de vídeos enviados nem a edição de imagens com menores de idade.
- Todas as saídas contêm uma marca d’água invisível SynthID.
Exemplos
Envie cada corpo JSON paraPOST /v1/videos/generations. Substitua URLs e IDs de exemplo por suas próprias entradas disponíveis.
Vídeo vertical de 15 segundos em 4K
{
"model": "gemini-omni-1.2-flash",
"prompt": "Aerial shot over a misty mountain lake at sunrise, birds flying, slow forward camera move.",
"aspect_ratio": "9:16",
"resolution": "4k",
"duration": 15
}
Imagem em vídeo e referências de sujeitos
{
"model": "gemini-omni-1.2-flash",
"prompt": "The cat playfully bats at the ball of yarn.",
"image_urls": [
"https://example.com/cat.png",
"https://example.com/yarn.png"
],
"duration": 12
}
Interpolação entre quadros inicial e final
{
"model": "gemini-omni-1.2-flash",
"prompt": "Smooth transition, camera slowly pushes in.",
"first_frame_image": "https://example.com/start.jpg",
"last_frame_image": "https://example.com/end.jpg",
"aspect_ratio": "16:9",
"duration": 8
}
Definir quadros usando funções
{
"model": "gemini-omni-1.2-flash",
"prompt": "A smooth cinematic transition from sunrise to a starry night.",
"image_with_roles": [
{
"url": "https://example.com/sunrise.jpg",
"role": "first_frame"
},
{
"url": "https://example.com/night.jpg",
"role": "last_frame"
}
],
"duration": 8
}
Edição de vídeo
{
"model": "gemini-omni-1.2-flash",
"prompt": "Make the violin invisible. Keep everything else the same.",
"video_urls": [
"https://example.com/clip.mp4"
]
}
duration não tem efeito.
Use instruções de edição curtas e específicas. Para uma alteração local, acrescente Keep everything else the same.
Estender uma tarefa existente
{
"model": "gemini-omni-1.2-flash",
"prompt": "The camera continues panning across the mountains.",
"extend_from_task_id": "task_01PREVIOUS",
"omni_reference_task_type": "extend",
"duration": 8
}
extend_from_task_id por video_urls e mantenha "omni_reference_task_type": "extend". O vídeo retornado contém o original seguido do trecho adicionado. duration controla apenas a duração adicionada, limitada a 10 segundos; somente os segundos adicionados são cobrados. Por exemplo, um vídeo original de 5 segundos com duration: 4 retorna um vídeo de aproximadamente 9 segundos.
Resposta de envio e consulta de tarefa
Um envio bem-sucedido retorna HTTP 200; leiadata[0].task_id. Consulte o status da tarefa a cada 5–10 segundos até completed ou failed. Recomenda-se uma espera total de 10 minutos. Se o cliente atingir o tempo limite, continue consultando a tarefa original sem reenviá-la.
curl --request GET \
--url https://api.apimart.ai/v1/tasks/task_01EXAMPLE \
--header 'Authorization: Bearer <token>'
{
"code": 200,
"data": {
"id": "task_01EXAMPLE",
"status": "completed",
"progress": 100,
"result": {
"videos": [
{
"url": [
"https://cdn.example.com/gemini_omni_video.mp4"
]
}
]
}
}
}
data na resposta de consulta é o objeto da tarefa. data.result.videos[0].url é um array; a primeira URL é data.result.videos[0].url[0]. É possível reproduzir ou baixar diretamente. Arquive o arquivo para armazenamento de longo prazo. data.cost é a cobrança final em USD.
| Status | Ação |
|---|---|
pending / processing | Continue consultando; veja o progresso em data.progress. |
completed | Leia a URL e salve o vídeo. |
failed | Leia data.error.message. Tarefas que falham não são cobradas. |
Cobrança e saldo reservado
Cobrança por tokens: a resolução afeta os tokens de vídeo por segundo. Na geração a partir de texto ou imagens,duration define a duração da saída. A edição ignora esse parâmetro e mantém a duração do vídeo de origem; a extensão o usa apenas para o trecho adicionado. Consulte os preços da APIMart.
No envio, o saldo é reservado conforme a resolução e max(10, duration) segundos; com vídeo de entrada, a estimativa é de 15 segundos. A reserva não é a cobrança final. Após o sucesso, o valor é ajustado ao uso real; consulte data.cost para o total final.
A extensão é cobrada apenas pelos segundos adicionados. Falhas não são cobradas. Saldo insuficiente para a reserva retorna HTTP 402.
Tratamento de erros
Erros de parâmetros (invalid_* / unsupported_*) mudam imediatamente a tarefa para failed, sem cobrança. Consulte o status mesmo após um envio bem-sucedido.
| Erro / status | Causa e ação |
|---|---|
invalid_duration | duration fora de 3–15, ou interpolação / extensão acima de 10 segundos. Use um inteiro dentro da faixa. |
invalid_task_type | Valor de omni_reference_task_type não suportado. Use auto / edit / extend / reference; text_to_video / image_to_video / reference_to_video também são aceitos. |
invalid_resolution | Use 360p / 720p / 1080p / 4k; 2160p também é aceito. |
invalid_frame_images | Apenas o quadro final foi informado. Adicione o inicial. |
unsupported_image_count | Mais de 10 imagens, incluindo quadros inicial/final. Reduza a quantidade. |
unsupported_video_count | Mais de 1 vídeo de entrada. Use um único clipe de até 15 segundos. |
HTTP 400 | O parâmetro obrigatório prompt está ausente. Envie instruções de texto mesmo ao fornecer mídia. |
HTTP 401 | Chave inválida. Verifique Authorization. |
HTTP 402 | Saldo insuficiente para a reserva. Recarregue ou reduza a resolução. |
HTTP 429 | Limite de solicitações atingido. Tente novamente com espera progressiva. |
status: failed | Falha do provedor ou rejeição por política de conteúdo. Leia data.error.message e ajuste a solicitação. |
Perguntas frequentes
prompt é obrigatório quando envio imagens ou vídeo?
Sim. Todos os modos exigem prompt, incluindo geração a partir de imagens, interpolação inicial/final, edição, extensão e reutilização de vídeo por extend_from_task_id. A ausência desse campo retorna HTTP 400.
Posso enviar imagens ou vídeo diretamente em Base64?
Não.image_urls, first_frame_image, last_frame_image, image_with_roles[].url e video_urls aceitam somente URLs HTTP(S) diretas e acessíveis publicamente. Não envie data:image/..., data:video/... nem strings Base64 brutas.