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
Pembuatan Video Gemini Omni 1.2 Flash
Video dari teks atau gambar, referensi beberapa subjek, interpolasi frame awal/akhir, pengeditan dan perpanjangan. Hingga 4K, 24fps, dengan audio.
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"
}
]
}
Pembuatan video dari teks atau gambar mendukung bilangan bulat 3–15 detik, dengan default 10. Interpolasi frame awal/akhir dan segmen tambahan pada perpanjangan mendukung maksimal 10 detik. Pengeditan mengabaikan
duration dan mempertahankan durasi video sumber. Input video secara default diedit; perpanjangan memerlukan "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"
}
]
}
Autentikasi
string
wajib
Gunakan autentikasi Bearer Token. Dapatkan kunci di halaman pengelolaan API Key dan kirim permintaan dengan
Content-Type: application/json.Parameter permintaan
string
wajib
Harus
gemini-omni-1.2-flash.string
wajib
Instruksi teks wajib: jelaskan adegan untuk teks ke video, atau gerakan, gaya, dan perubahan untuk mode lainnya.
prompt wajib disertakan meskipun Anda memberikan gambar referensi, frame awal/akhir, video, atau extend_from_task_id. Jika dihilangkan, API mengembalikan HTTP 400.integer
default:"10"
Durasi output untuk pembuatan video dari teks atau gambar, bilangan bulat
3–15, default 10. Interpolasi frame awal/akhir dan perpanjangan hanya mendukung 3–10 detik. Untuk perpanjangan, ini adalah panjang segmen tambahan; video yang dikembalikan mencakup video asli dan segmen tambahan. Pengeditan mengabaikan duration dan mempertahankan durasi video sumber. Nilai parameter di luar rentang membuat tugas gagal dengan invalid_duration.string
default:"720p"
360p / 720p / 1080p / 4k, tidak peka huruf besar/kecil; 2160p dianggap 4k. 1080p dan 4k menggunakan upsampling. Resolusi memengaruhi token output dan saldo yang dicadangkan. Nilai lain membuat tugas gagal dengan invalid_resolution.string
default:"16:9"
Hanya
16:9 (lanskap, default) dan 9:16 (potret). Nilai lain dianggap 16:9.string[]
Gambar referensi hanya berupa URL HTTP(S) langsung ke gambar yang dapat diakses publik. Data URL dan Base64 tidak didukung. Satu gambar menjadi frame awal; beberapa gambar menjadi referensi subjek. Maksimal 10 gambar termasuk frame awal/akhir. Untuk karakter, disarankan maksimal 2 karakter dengan hingga 3 gambar per karakter, total tidak lebih dari 6 gambar.
string
Gambar frame awal. Jika digunakan sendiri, video dimulai dari gambar ini; bersama
last_frame_image, mengaktifkan interpolasi antara frame awal dan akhir. Hanya URL HTTP(S) langsung ke gambar yang dapat diakses publik yang didukung.string
Gambar frame akhir; memerlukan
first_frame_image, jika tidak tugas gagal dengan invalid_frame_images. Gunakan rasio yang sama untuk kedua gambar dan sesuaikan dengan aspect_ratio. Hanya URL HTTP(S) langsung ke gambar yang dapat diakses publik yang didukung.object[]
Array gambar dengan peran, setara dengan kolom langsung frame awal/akhir. Pilih salah satu cara. Semua gambar yang digunakan dihitung dalam batas total 10.
string[]
Video untuk diedit atau diperpanjang: maksimal 1 klip dengan durasi paling lama 15 detik. Hanya URL HTTP(S) langsung ke video yang dapat diakses publik yang didukung. Data URL dan Base64 tidak didukung. Input video secara default diedit.
string
default:"auto"
Jenis tugas:
auto (default, ditentukan dari input) / edit (pengeditan) / extend (perpanjangan) / reference (beberapa gambar referensi). Juga menerima text_to_video / image_to_video / reference_to_video. Jika dihilangkan atau diatur ke auto, video_urls dan extend_from_task_id secara default melakukan pengeditan. Untuk memperpanjang, tetapkan extend secara eksplisit.string
ID tugas pembuatan Anda sebelumnya untuk menggunakan kembali video tanpa mengunggah ulang. Defaultnya adalah pengeditan. Dengan
"omni_reference_task_type": "extend", segmen hingga 10 detik ditambahkan di akhir.Kemampuan dan batasan
- Output video adalah 24fps dengan dialog, musik, atau efek suara. Jelaskan audio yang diinginkan dalam
prompt. - Input audio, system prompt,
temperature, dan parameter prompt negatif tidak didukung. Tulis hal yang perlu dihindari langsung dalamprompt. - Batasan wilayah penyedia: di EEA, Swiss, dan Inggris, pengeditan atau perpanjangan video yang diunggah serta pengeditan gambar berisi anak di bawah umur tidak didukung.
- Semua output menyertakan watermark SynthID yang tidak terlihat.
Contoh penggunaan
Kirim setiap JSON kePOST /v1/videos/generations. Ganti URL media dan ID tugas contoh dengan input milik Anda yang dapat digunakan.
Video potret 4K berdurasi 15 detik
{
"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
}
Gambar ke video dan referensi subjek
{
"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
}
Interpolasi frame awal dan akhir
{
"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
}
Menetapkan frame melalui peran gambar
{
"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
}
Pengeditan video
{
"model": "gemini-omni-1.2-flash",
"prompt": "Make the violin invisible. Keep everything else the same.",
"video_urls": [
"https://example.com/clip.mp4"
]
}
duration tidak berpengaruh.
Gunakan instruksi pengeditan yang singkat dan spesifik. Untuk perubahan sebagian, tambahkan Keep everything else the same.
Memperpanjang tugas sebelumnya
{
"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 dengan video_urls dan pertahankan "omni_reference_task_type": "extend". Video yang dikembalikan berisi video asli diikuti segmen tambahan. duration hanya mengatur durasi tambahan, maksimal 10 detik; biaya hanya dikenakan untuk detik tambahan. Misalnya, video sumber 5 detik dengan duration: 4 menghasilkan video sekitar 9 detik.
Respons pengiriman dan status tugas
Pengiriman berhasil mengembalikan HTTP 200; bacadata[0].task_id. Periksa status tugas setiap 5–10 detik hingga completed atau failed. Disarankan waktu tunggu total 10 menit. Jika klien mengalami timeout, terus periksa tugas awal tanpa mengirim ulang.
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 dalam respons status adalah objek tugas. data.result.videos[0].url adalah array; URL pertama berada di data.result.videos[0].url[0]. Video dapat diputar atau diunduh langsung. Simpan salinan untuk penyimpanan jangka panjang. data.cost adalah biaya akhir dalam USD.
| Status | Tindakan |
|---|---|
pending / processing | Terus periksa; kemajuan tersedia di data.progress. |
completed | Baca URL dan simpan video. |
failed | Baca data.error.message. Tugas gagal tidak dikenakan biaya. |
Penagihan dan saldo cadangan
Penagihan berdasarkan token: resolusi memengaruhi token video output per detik. Untuk pembuatan video dari teks atau gambar,duration menentukan durasi output. Pengeditan mengabaikan parameter ini dan mempertahankan durasi video sumber; perpanjangan menggunakannya hanya untuk segmen tambahan. Lihat harga APIMart untuk tarif aktual.
Saat dikirim, saldo dicadangkan berdasarkan resolusi dan max(10, duration) detik; jika ada input video, estimasinya 15 detik. Cadangan bukan biaya akhir. Setelah berhasil, jumlah disesuaikan dengan penggunaan aktual; baca data.cost untuk biaya akhir.
Perpanjangan hanya ditagih untuk detik tambahan. Tugas gagal tidak dikenakan biaya. Saldo yang tidak mencukupi untuk cadangan menghasilkan HTTP 402.
Penanganan kesalahan
Kesalahan parameter (invalid_* / unsupported_*) langsung mengubah tugas menjadi failed tanpa biaya. Periksa status meskipun pengiriman berhasil.
| Kesalahan / status | Penyebab dan tindakan |
|---|---|
invalid_duration | duration di luar 3–15, atau interpolasi / perpanjangan melebihi 10 detik. Gunakan bilangan bulat dalam rentang. |
invalid_task_type | Nilai omni_reference_task_type tidak didukung. Gunakan auto / edit / extend / reference; text_to_video / image_to_video / reference_to_video juga diterima. |
invalid_resolution | Gunakan 360p / 720p / 1080p / 4k; 2160p juga diterima. |
invalid_frame_images | Hanya frame akhir yang diberikan. Tambahkan frame awal. |
unsupported_image_count | Lebih dari 10 gambar termasuk frame awal/akhir. Kurangi jumlahnya. |
unsupported_video_count | Lebih dari 1 video input. Gunakan satu klip berdurasi maksimal 15 detik. |
HTTP 400 | Parameter wajib prompt tidak ada. Sertakan instruksi teks meskipun memberikan media. |
HTTP 401 | Kunci tidak valid. Periksa Authorization. |
HTTP 402 | Saldo tidak cukup untuk cadangan. Isi saldo atau turunkan resolusi. |
HTTP 429 | Batas permintaan tercapai. Coba lagi dengan jeda yang meningkat. |
status: failed | Kesalahan penyedia atau penolakan kebijakan konten. Baca data.error.message dan sesuaikan permintaan. |
Pertanyaan umum
Apakah prompt tetap wajib jika saya memberikan gambar atau video?
Ya. Semua mode memerlukan prompt, termasuk pembuatan dari gambar, interpolasi frame awal/akhir, pengeditan, perpanjangan, dan penggunaan kembali video melalui extend_from_task_id. Jika kolom ini dihilangkan, API mengembalikan HTTP 400.
Bisakah saya mengirim gambar atau video Base64 secara langsung?
Tidak.image_urls, first_frame_image, last_frame_image, image_with_roles[].url, dan video_urls hanya menerima URL HTTP(S) langsung yang dapat diakses publik. Jangan mengirim data:image/..., data:video/..., atau string Base64 mentah.