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
Gemini Omni 1.2 Flash 動画生成
テキスト・画像からの動画生成、複数の被写体参照、開始・終了フレーム補間、動画編集・延長に対応。最大 4K、24fps、音声付き。
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"
}
]
}
テキスト・画像からの動画生成は 3~15 秒の整数で指定でき、既定値は 10 秒です。開始・終了フレーム補間と延長の追加部分は最大 10 秒です。編集では
duration が無視され、出力時間は元動画と同じになります。動画入力の既定動作は編集です。延長には "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"
}
]
}
認証
string
必須
Bearer Token 認証を使用します。API Key 管理ページでキーを取得し、送信時は
Content-Type: application/json を指定してください。リクエストパラメータ
string
必須
gemini-omni-1.2-flash を指定します。string
必須
必須のテキスト指示。テキストからの生成では場面を、画像からの生成・編集・延長では動き、スタイル、変更内容を記述します。参照画像、開始・終了フレーム、動画、または
extend_from_task_id を指定する場合も prompt は必須です。省略すると HTTP 400 が返されます。integer
デフォルト:"10"
テキスト・画像から生成する動画の出力時間。
3~15 の整数で、既定値は 10 です。開始・終了フレーム補間と延長は 3~10 秒のみ。延長では追加部分の長さを指定し、元動画と追加部分を含む動画が返されます。編集では duration が無視され、出力時間は元動画と同じになります。パラメータが許容範囲外の場合、タスクは invalid_duration で失敗します。string
デフォルト:"720p"
360p / 720p / 1080p / 4k。大文字・小文字を区別せず、2160p は 4k として扱います。1080p と 4k はアップサンプリング出力です。解像度は出力トークン数と仮押さえ額に影響します。その他の値ではタスクが invalid_resolution で失敗します。string
デフォルト:"16:9"
16:9(横向き、既定値)または 9:16(縦向き)のみ。その他の値は 16:9 として扱います。string[]
参照画像の配列。公開アクセス可能な HTTP(S) の画像直リンクのみ対応し、Data URL や Base64 は使用できません。1 枚なら開始画面、複数なら被写体参照として使用します。開始・終了フレームを含め合計 10 枚まで。キャラクター参照は最大 2 人、各 3 枚まで、合計 6 枚以内を推奨します。
string
開始フレーム画像。単独指定ではこの画像から生成し、
last_frame_image と併用すると開始・終了フレーム補間になります。公開アクセス可能な HTTP(S) の画像直リンクのみ対応します。string
終了フレーム画像。
first_frame_image が必要で、ない場合は invalid_frame_images で失敗します。両画像の比率を揃え、aspect_ratio と一致させてください。公開アクセス可能な HTTP(S) の画像直リンクのみ対応します。object[]
string[]
編集・延長する動画の配列。最大 1 本、15 秒以内。公開アクセス可能な HTTP(S) の動画直リンクのみ対応し、Data URL や Base64 は使用できません。動画入力時は既定で編集します。
string
デフォルト:"auto"
タスク種別:
auto(既定、入力から自動判定)/ edit(編集)/ extend(延長)/ reference(複数画像の参照)。text_to_video / image_to_video / reference_to_video も使用できます。省略時または auto の場合、video_urls と extend_from_task_id は既定で編集です。延長するには extend を明示してください。string
自分の前回の生成タスク ID を参照し、動画の再アップロードなしで再利用します。既定は編集。
"omni_reference_task_type": "extend" を指定すると、末尾に最大 10 秒の映像を追加します。機能と制限
- 出力は 24fps で、会話・音楽・効果音を含みます。希望する音を
promptに記述できます。 - 音声入力、system prompt、
temperature、ネガティブプロンプト用パラメータには対応しません。避けたい内容はpromptに直接記述してください。 - 上流サービスの地域制限:EEA・スイス・英国では、アップロード動画の編集・延長、および未成年者を含む画像の編集に対応しません。
- すべての出力に不可視の SynthID ウォーターマークが含まれます。
使用例
各 JSON をPOST /v1/videos/generations に送信します。例の素材 URL とタスク ID は利用可能な自分のものに置き換えてください。
15 秒の 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
}
画像からの生成と複数の被写体参照
{
"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
}
開始・終了フレーム補間
{
"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
}
画像の役割によるフレーム指定
{
"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
}
動画編集
{
"model": "gemini-omni-1.2-flash",
"prompt": "Make the violin invisible. Keep everything else the same.",
"video_urls": [
"https://example.com/clip.mp4"
]
}
duration は適用されません。
編集指示は短く具体的にします。一部分だけを変える場合は Keep everything else the same を追加できます。
既存タスクの延長
{
"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 を video_urls に置き換え、"omni_reference_task_type": "extend" を維持してください。返される動画は元動画と末尾の追加部分を含みます。duration は追加部分の長さのみを指定し、最大 10 秒です。課金対象も追加された秒数のみです。例えば 5 秒の元動画に duration: 4 を指定すると、約 9 秒の動画が返されます。
送信レスポンスとタスク照会
送信成功時は HTTP 200 が返ります。data[0].task_id を取得し、タスク照会 APIを 5~10 秒間隔で、completed または failed になるまで呼び出してください。全体の待機時間は 10 分を推奨します。クライアントがタイムアウトした場合も、再送信せず同じタスクを照会します。
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 がタスクオブジェクトです。data.result.videos[0].url は配列で、最初の動画 URL は data.result.videos[0].url[0] です。直接再生・ダウンロードでき、長期保存には自身のストレージへ保存してください。data.cost は最終請求額(米ドル)です。
| 状態 | 対応 |
|---|---|
pending / processing | 照会を継続し、data.progress で進捗を確認します。 |
completed | 動画 URL を取得して保存します。 |
failed | data.error.message を確認します。失敗タスクは課金されません。 |
課金と残高の仮押さえ
トークン単位の課金です。解像度は 1 秒あたりの出力トークン数に影響します。テキスト・画像からの動画生成ではduration が出力時間を指定します。編集ではこの値は無視され、元動画と同じ長さになります。延長では追加部分の長さのみを指定します。実際の料金は APIMart 料金ページで確認してください。
送信時は解像度と max(10, duration) 秒で残高を仮押さえし、動画入力がある場合は 15 秒で見積もります。仮押さえ額は最終料金ではありません。成功後に実使用量で差額を精算し、最終額は data.cost で確認できます。
延長は追加秒数のみ課金されます。失敗は課金されません。仮押さえ額に残高が足りない場合は HTTP 402 が返ります。
エラー処理
パラメータエラー(invalid_* / unsupported_*)ではタスクが直ちに failed になり、課金されません。送信成功後も状態を確認してください。
| エラー / 状態 | 原因と対応 |
|---|---|
invalid_duration | duration が 3~15 の範囲外、または補間・延長で 10 秒超。許容範囲の整数に変更します。 |
invalid_task_type | omni_reference_task_type の値が未対応です。auto / edit / extend / reference を使用してください。text_to_video / image_to_video / reference_to_video も使用できます。 |
invalid_resolution | 360p / 720p / 1080p / 4k を使用します。2160p も受け付けます。 |
invalid_frame_images | 終了フレームのみが指定されています。開始フレームを追加します。 |
unsupported_image_count | 開始・終了フレームを含め 10 枚超。画像数を減らします。 |
unsupported_video_count | 入力動画が 1 本超。15 秒以内の動画 1 本にします。 |
HTTP 400 | 必須の prompt がありません。素材を指定する場合もテキスト指示を送信してください。 |
HTTP 401 | キーが無効です。Authorization を確認します。 |
HTTP 402 | 仮押さえ額に残高が不足しています。チャージするか解像度を下げます。 |
HTTP 429 | リクエスト過多です。待機時間を増やして再試行します。 |
status: failed | 上流エラーまたはコンテンツポリシーによる拒否。data.error.message を確認してリクエストを修正します。 |
よくある質問
画像や動画を指定しても prompt は必要ですか?
はい。画像からの動画生成、開始・終了フレーム補間、編集、延長、extend_from_task_id による動画の再利用を含め、すべてのモードで prompt が必須です。省略すると HTTP 400 が返されます。
Base64 の画像や動画を直接送信できますか?
できません。image_urls、first_frame_image、last_frame_image、image_with_roles[].url、video_urls は、公開アクセス可能な HTTP(S) の直リンクのみ対応します。data:image/...、data:video/...、Base64 文字列を直接送信しないでください。