Veo 3 の API を初めて触ったとき、最初に戸惑うのがその「非同期」な設計です。テキスト生成のように response.text を呼べばすぐ結果が返ってくる、というわけにはいかありません。動画生成には数十秒〜数分かかり、ポーリングと呼ばれる定期的な状態確認が必要になります。
この設計上の違いを理解していないまま実装すると、「なぜか動画が生成されない」「エラーが出て原因がわからない」という状態に陥りやすい。ここではVeo API を実際に使う中でよく遭遇するエラーと、その根本原因・具体的な解決策をまとめる。
Veo API が他と違う点 — まず仕組みを押さえる
エラーの前に、Veo API がどう動くかを簡潔に確認します。Veo API は「Long-Running Operation(LRO)」パターンを採用しています。リクエストを送った瞬間に動画は返ってこありません。代わりにオペレーションIDが返り、後からそのIDで完了状態を問い合わせる必要があります。
import google.genai as genai
import time
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
# 動画生成リクエスト(すぐには動画は返ってこない)
operation = client.models.generate_videos(
model="veo-3.0-generate-preview",
prompt="A serene mountain lake at golden hour, cinematic style",
config=genai.types.GenerateVideoConfig(
aspect_ratio="16:9",
number_of_videos=1,
),
)
print(f"Operation name: {operation.name}")
print(f"Done: {operation.done}") # → False(まだ処理中)この operation.done が True になるまで、定期的に状態を確認し続けるのが正しい実装です。
エラーと詰まりパターン① — ポーリングをしていない(最多)
「コードを実行したが動画ファイルが返ってこない」という相談の大半は、ポーリングを実装していないことが原因です。
間違い: operation をそのまま使おうとする
# ❌ これではダメ: 処理中のままなのにアクセスしようとしている
operation = client.models.generate_videos(...)
video_url = operation.result.generated_videos[0].video.uri # AttributeError になるoperation.result は None(処理完了前)なのでエラーになります。
正しい実装: ポーリングループを組む
import google.genai as genai
import time
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
operation = client.models.generate_videos(
model="veo-3.0-generate-preview",
prompt="A timelapse of city lights at night, aerial view",
config=genai.types.GenerateVideoConfig(
aspect_ratio="16:9",
number_of_videos=1,
duration_seconds=5,
),
)
# ポーリング: 完了するまで定期確認
max_wait = 300 # 最大5分
interval = 15 # 15秒ごとに確認
elapsed = 0
while not operation.done and elapsed < max_wait:
print(f"生成中... ({elapsed}秒経過)")
time.sleep(interval)
elapsed += interval
operation = client.operations.get(operation)
if not operation.done:
print("タイムアウト: 動画生成が完了しませんでした")
else:
# 生成完了
for video in operation.result.generated_videos:
print(f"動画URI: {video.video.uri}")ポーリング間隔は最低10〜15秒にすること。短すぎると不要なAPIコールが増え、クォータを無駄消費します。
エラーと詰まりパターン② — セーフティフィルターによる拒否
Veo API のセーフティフィルターは、テキスト生成よりも厳格に設定されています。プロンプトが拒否された場合、operation.error にエラー情報が格納されます。
症状
operation.error.code = 400
operation.error.message = "Video generation blocked by safety filters"
または operation.result.generated_videos が空リストになります。
拒否されやすいプロンプトのパターン
意外に引っかかりやすいのが、暴力・事故・自然災害の描写です。「爆発」「衝突」「洪水」といった単語をそのまま使うと弾かれることがあります。また、実在する人物の名前を含めたプロンプトも拒否されます。
# ❌ 拒否されやすい例
# "A car crash in slow motion"
# "Tsunami wave hitting buildings"
# ✅ 表現を変えて回避する例
# "A car speeding away dramatically, cinematic"
# "Powerful ocean waves crashing on rocky shores"エラーが返った場合の確認コード:
# エラー確認
if operation.done and operation.error:
print(f"エラーコード: {operation.error.code}")
print(f"メッセージ: {operation.error.message}")
elif operation.done and not operation.result.generated_videos:
print("生成結果が空: セーフティフィルターによる拒否の可能性")セーフティフィルターの詳しい対処法は Gemini API のセーフティフィルターによる応答ブロックの原因と回避策 も参考にしてほしい。
エラーと詰まりパターン③ — モデル名・パラメーター指定ミス
Veo API はモデル指定が重要です。2026年4月時点で利用可能なモデルは以下:
veo-3.0-generate-preview— Veo 3(フル機能版)veo-2.0-generate-001— Veo 2(安定版)veo-3.0-fast-generate-preview— Veo 3 Lite(コスト効率優先)
# よくある間違い
model="veo-3" # ❌ 正式名ではない
model="veo3" # ❌ ハイフンが必要
model="veo-3-preview" # ❌ バージョン番号の形式が違う
また duration_seconds は veo-3.0-generate-preview では5〜8秒の範囲が基本です。これを超えた値を指定するとエラーになります。aspect_ratio は "16:9" "9:16" "1:1" のみ有効で、それ以外は拒否されます。
# ✅ 正しいパラメーター指定例
config = genai.types.GenerateVideoConfig(
aspect_ratio="16:9", # "16:9" / "9:16" / "1:1" のみ有効
number_of_videos=1, # 1〜2(モデルによる)
duration_seconds=5, # Veo 3: 5〜8秒
)エラーと詰まりパターン④ — 動画ファイルの取得・ダウンロード失敗
生成が完了しても、動画URIからファイルを取得する際に詰まるケースがあります。
症状: URI にアクセスできない
Veo API が返す video.uri は期限付きのURLです。生成完了から一定時間が経過するとアクセスできなくなります。生成直後にダウンロードすることが重要です。
import requests
import os
# 動画のダウンロード
for i, video in enumerate(operation.result.generated_videos):
video_uri = video.video.uri
# 認証ヘッダーが必要(Bearerトークン)
headers = {"Authorization": f"Bearer {client._api_key}"}
response = requests.get(video_uri, headers=headers)
if response.status_code == 200:
filename = f"output_video_{i}.mp4"
with open(filename, "wb") as f:
f.write(response.content)
print(f"✅ 保存完了: {filename} ({len(response.content) / 1024:.1f} KB)")
else:
print(f"❌ ダウンロード失敗: {response.status_code}")また、Colab や Cloud Run などの一時的な環境で実行している場合、生成した動画はセッション終了と同時に消えてしまう。長期保存が必要なら Google Cloud Storage に即座にアップロードする設計にしておくこと。
エラーと詰まりパターン⑤ — クォータ超過(429)と課金の落とし穴
Veo API はテキスト/画像生成とは別のクォータ管理が適用されます。無料枠で使える動画生成数は非常に少ないため、開発段階からクォータに気を配る必要があります。
ERROR: 429 Resource exhausted
Quota exceeded for quota metric 'video_generation_requests'
詳細なクォータ確認は Gemini API のクォータ・429エラーのトラブルシューティング完全ガイド を参照してほしい。
Veo 3 はプロンプト1件あたりのコストがテキスト生成に比べて桁違いに高い。開発・テスト段階ではコスト効率の高い Veo 3 Lite API を活用したコスト効率の良い動画生成 を優先的に使うことをすすめる。
開発時のコスト抑制パターン
import os
# 開発環境フラグ
IS_DEV = os.getenv("ENV", "dev") == "dev"
def generate_video(prompt: str) -> str | None:
"""動画生成(開発時はLiteモデル、本番はフルモデル)"""
model = "veo-3.0-fast-generate-preview" if IS_DEV else "veo-3.0-generate-preview"
print(f"Using model: {model}")
operation = client.models.generate_videos(
model=model,
prompt=prompt,
config=genai.types.GenerateVideoConfig(
aspect_ratio="16:9",
number_of_videos=1,
duration_seconds=5, # 短めで開発
),
)
# ポーリング
max_wait = 180
interval = 15
elapsed = 0
while not operation.done and elapsed < max_wait:
time.sleep(interval)
elapsed += interval
operation = client.operations.get(operation)
if operation.done and operation.result.generated_videos:
return operation.result.generated_videos[0].video.uri
return Noneまず試すべきデバッグチェックリスト
Veo API でエラーが出たとき、まず以下を確認する:
- ポーリングを実装しているか —
operation.doneがTrueになるまで待っているか - モデル名は正しいか —
veo-3.0-generate-previewなど公式ドキュメントの名称と一致しているか - パラメーター範囲は正しいか —
duration_secondsとaspect_ratioの値を確認 - エラー内容を確認しているか —
operation.errorがNoneでないか確認 - 動画URIを即時ダウンロードしているか — URLは期限付きのため遅延は禁物
- クォータ残量を確認したか — Google Cloud Console のクォータページを確認
Veo API の詳しい実装については Veo 3 動画生成 API の完全ガイド を参考にしてほしい。正しくポーリングとエラーハンドリングを実装すれば、Veo API は強力なツールになります。今日のうちに動作するコードを1本完成させてみてほしい。