Gemini Video Generation
Gemini Video Generation (Veo)
LiteLLM은 Google의 Veo 비디오 생성 모델을 통합 API 인터페이스로 지원해요.
출처: 문서
본문
개요 (Overview)
| 속성 | 설명 |
|---|---|
| 설명 | Google의 Veo AI 비디오 생성 모델 |
| LiteLLM 라우트 | gemini/ |
| 지원 모델 | Veo 3.0 / 3.1 preview 및 프로덕션 ID (아래 표 참고), Veo 3.1 Lite 포함 |
| 비용 추적 | ✅ 시간 기반 가격; 카탈로그에 나열된 곳에서는 선택적 해상도별 등급 (예: 720p vs 1080p) |
| 로깅 지원 | ✅ 전체 요청/응답 로깅 |
| Proxy 지원 | ✅ 가상 키 포함 전체 proxy 통합 |
| 지출 관리 | ✅ 예산 추적 및 rate limiting |
| 공급자 문서 | Google Veo Documentation |
빠른 시작 (Quick Start)
필수 API 키
import os
os.environ["GEMINI_API_KEY"] = "your-google-api-key"
# OR
os.environ["GOOGLE_API_KEY"] = "your-google-api-key"
기본 사용법
from litellm import video_generation, video_status, video_content
import os
import time
os.environ["GEMINI_API_KEY"] = "your-google-api-key"
# Step 1: Generate video
response = video_generation(
model="gemini/veo-3.0-generate-preview",
prompt="A cat playing with a ball of yarn in a sunny garden"
)
print(f"Video ID: {response.id}")
print(f"Initial Status: {response.status}") # "processing"
# Step 2: Poll for completion
while True:
status_response = video_status(
video_id=response.id
)
print(f"Current Status: {status_response.status}")
if status_response.status == "completed":
break
elif status_response.status == "failed":
print("Video generation failed")
break
time.sleep(10) # Wait 10 seconds before checking again
# Step 3: Download video content
video_bytes = video_content(
video_id=response.id
)
# Save to file
with open("generated_video.mp4", "wb") as f:
f.write(video_bytes)
print("Video downloaded successfully!")
지원 모델 (Supported Models)
| 모델 이름 | 설명 | 최대 길이 | 상태 |
|---|---|---|---|
| veo-3.0-generate-preview | Veo 3.0 비디오 생성 | 8초 | Preview |
| veo-3.1-generate-preview | Veo 3.1 비디오 생성 | 8초 | Preview |
| veo-3.1-lite-generate-preview | Veo 3.1 Lite (비용 효율적; Gemini 가격) | Google 문서대로 | Preview |
| veo-3.1-fast-generate-preview / …-001 | 더 빠른 / prod 변형 | Google 문서대로 | Preview / GA |
| veo-3.1-generate-001 | Veo 3.1 프로덕션 | Google 문서대로 | GA |
gemini/ 접두사가 있는 전체 LiteLLM 모델 id를 사용하세요 (예: gemini/veo-3.1-lite-generate-preview).
비디오 생성 파라미터
LiteLLM은 자동으로 OpenAI 스타일 파라미터를 Veo의 형식으로 매핑해요:
| OpenAI 파라미터 | Veo 파라미터 | 설명 | 예시 |
|---|---|---|---|
| prompt | prompt | 비디오의 텍스트 설명 | "A cat playing" |
| size | aspectRatio 및 해당 시 resolution | 표준 width/height는 landscape/portrait 및 API에 대해 720p 또는 1080p에 매핑 | 아래 참고 |
| seconds | durationSeconds | 길이(초) | "8" → 8 |
| input_reference | image | 애니메이션할 참조 이미지 | File 객체 또는 경로 |
| model | model | 사용할 모델 | "gemini/veo-3.0-generate-preview" |
size와 출력 해상도
표준 size 문자열을 전달하면 LiteLLM이 둘 다 설정해요:
- 종횡비 (16:9 또는 9:16): 이전과 동일
- height가 preset에서 명확하면 출력 해상도 (720p 또는 1080p): 추가 필드 없이 올바른 Veo 등급 요청
| size | 종횡비 | Veo로 보내는 해상도 |
|---|---|---|
| 1280x720, 720x1280 | 16:9 / 9:16 | 720p |
| 1920x1080, 1080x1920 | 16:9 / 9:16 | 1080p |
다른 size 값은 여전히 종횡비로 매핑(알 수 없으면 16:9 기본)되고, 해상도는 직접 설정하지 않으면 Google 기본값에 맡겨져요. 위 preset과 맞지 않는 명시적 값이 필요하면 extra_body로 Veo의 resolution을 전달할 수도 있어요. 직접 resolution을 설정하면 size에서 추론된 값보다 우선해요.
size → 종횡비 (참고)
"1280x720","1920x1080"→"16:9"(landscape)"720x1280","1080x1920"→"9:16"(portrait)
지원 Veo 파라미터
Veo API 기준:
prompt(필수): 선택적 오디오 큐가 포함된 텍스트 설명aspectRatio:"16:9"(기본) 또는"9:16"resolution:"720p"(기본) 또는"1080p"(Veo 3.1 전용, 16:9 종횡비만)durationSeconds: 비디오 길이 (대부분 모델에서 최대 8초)image: 애니메이션용 참조 이미지negativePrompt: 비디오에서 제외할 것 (Veo 3.1)referenceImages: 스타일 및 콘텐츠 참조 (Veo 3.1 전용)
완전한 워크플로 예시
import litellm
import time
def generate_and_download_veo_video(
prompt: str,
output_file: str = "video.mp4",
size: str = "1280x720",
seconds: str = "8"
):
"""
Complete workflow for Veo video generation.
Args:
prompt: Text description of the video
output_file: Where to save the video
size: Video dimensions (e.g., "1280x720" for 16:9)
seconds: Duration in seconds
Returns:
bool: True if successful
"""
print(f"🎬 Generating video: {prompt}")
# Step 1: Initiate generation
response = litellm.video_generation(
model="gemini/veo-3.0-generate-preview",
prompt=prompt,
size=size, # Maps to aspectRatio
seconds=seconds # Maps to durationSeconds
)
video_id = response.id
print(f"✓ Video generation started (ID: {video_id})")
# Step 2: Wait for completion
max_wait_time = 600 # 10 minutes
start_time = time.time()
while time.time() - start_time < max_wait_time:
status_response = litellm.video_status(video_id=video_id)
if status_response.status == "completed":
print("✓ Video generation completed!")
break
elif status_response.status == "failed":
print("✗ Video generation failed")
return False
print(f"⏳ Status: {status_response.status}")
time.sleep(10)
else:
print("✗ Timeout waiting for video generation")
return False
# Step 3: Download video
print("⬇️ Downloading video...")
video_bytes = litellm.video_content(video_id=video_id)
with open(output_file, "wb") as f:
f.write(video_bytes)
print(f"✓ Video saved to {output_file}")
return True
# Use it
generate_and_download_veo_video(
prompt="A serene lake at sunset with mountains in the background",
output_file="sunset_lake.mp4"
)
비동기 사용법 (Async Usage)
from litellm import avideo_generation, avideo_status, avideo_content
import asyncio
async def async_video_workflow():
# Generate video
response = await avideo_generation(
model="gemini/veo-3.0-generate-preview",
prompt="A cat playing with a ball of yarn"
)
# Poll for completion
while True:
status = await avideo_status(video_id=response.id)
if status.status == "completed":
break
await asyncio.sleep(10)
# Download content
video_bytes = await avideo_content(video_id=response.id)
with open("video.mp4", "wb") as f:
f.write(video_bytes)
# Run it
asyncio.run(async_video_workflow())
LiteLLM Proxy 사용법
config.yaml에 Veo 모델 추가:
model_list:
- model_name: veo-3
litellm_params:
model: gemini/veo-3.0-generate-preview
api_key: os.environ/GEMINI_API_KEY
Proxy 시작:
litellm --config config.yaml
# Server running on http://0.0.0.0:4000
요청:
curl:
# Step 1: Generate video
curl --location 'http://0.0.0.0:4000/v1/videos' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ***" \
--data '{
"model": "veo-3",
"prompt": "A cat playing with a ball of yarn in a sunny garden"
}'
# Response: {"id": "gemini::operations/generate_12345::...", "status": "processing", ...}
# Step 2: Check status
curl --location 'http://localhost:4000/v1/videos/{video_id}' \
--header 'x-litellm-api-key: sk-<yo...y>'
# Step 3: Download video (when status is "completed")
curl --location 'http://localhost:4000/v1/videos/{video_id}/content' \
--header 'x-litellm-api-key: sk-<yo...ey>' \
--output video.mp4
Python SDK:
import litellm
litellm.api_base = "http://0.0.0.0:4000"
litellm.api_key = "sk-<your-litellm-api-key>"
# Generate video
response = litellm.video_generation(
model="veo-3",
prompt="A cat playing with a ball of yarn in a sunny garden"
)
# Check status
import time
while True:
status = litellm.video_status(video_id=response.id)
if status.status == "completed":
break
time.sleep(10)
# Download video
video_bytes = litellm.video_content(video_id=response.id)
with open("video.mp4", "wb") as f:
f.write(video_bytes)
비용 추적과 지출 (Cost tracking and spend)
LiteLLM은 다음에서 비디오 지출을 추정해요:
- 생성된 클립이 청구되는 길이(초), 그리고
- LiteLLM 모델 카탈로그에서 해당 모델의 초당 가격 (가능한 곳에서 Google Gemini API 비디오 가격과 정렬)
일부 모델은 720p vs 1080p에 다른 초당 요율을 부과해요. 위의 표준 size preset을 쓰거나 resolution을 직접 설정하면 LiteLLM이 일치하는 등급을 사용하므로 proxy 지출, 로그, 예산이 요청한 해상도와 일치해요.
response = litellm.video_generation(
model="gemini/veo-3.0-generate-preview",
prompt="A beautiful sunset"
)
# Cost is calculated based on video duration
# Veo pricing: ~$0.10 per second (estimated)
# Default video duration: ~5 seconds
# Estimated cost: ~$0.50
OpenAI Video API와의 차이점
| 기능 | OpenAI (Sora) | Gemini (Veo) |
|---|---|---|
| 참조 이미지 | ✅ 지원 | ❌ 미지원 |
| 크기/차원 | ✅ 지원 | ✅ size → aspect ratio + preset 시 720p/1080p로 지원 |
| 길이 (초) | ✅ 지원 | ✅ 지원 (durationSeconds로 매핑; Google 문서대로 한도) |
| 비디오 리믹스/편집 | ✅ 지원 | ❌ 미지원 |
| 비디오 목록 | ✅ 지원 | ❌ 미지원 |
| 프롬프트 기반 생성 | ✅ 지원 | ✅ 지원 |
| 비동기 작업 | ✅ 지원 | ✅ 지원 |
에러 처리 (Error Handling)
from litellm import video_generation, video_status, video_content
from litellm.exceptions import APIError, Timeout
try:
response = video_generation(
model="gemini/veo-3.0-generate-preview",
prompt="A beautiful landscape"
)
# Poll with timeout
max_attempts = 60 # 10 minutes (60 * 10s)
for attempt in range(max_attempts):
status = video_status(video_id=response.id)
if status.status == "completed":
video_bytes = video_content(video_id=response.id)
with open("video.mp4", "wb") as f:
f.write(video_bytes)
break
elif status.status == "failed":
raise APIError("Video generation failed")
time.sleep(10)
else:
raise Timeout("Video generation timed out")
except APIError as e:
print(f"API Error: {e}")
except Timeout as e:
print(f"Timeout: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
모범 사례 (Best Practices)
- 항상 완료를 폴링하세요: Veo 비디오 생성은 비동기이며 몇 분이 걸릴 수 있어요
- 합리적인 타임아웃 설정: 비디오 생성에 최소 5-10분 허용
- 실패를 우아하게 처리: failed 상태를 확인하고 재시도 로직 구현
- 설명적인 프롬프트 사용: 더 자세한 프롬프트가 일반적으로 더 나은 결과 생성
- 비디오 ID 저장: 앱이 재시작되어도 폴링을 재개하도록 operation ID/video ID 저장
문제 해결 (Troubleshooting)
비디오 생성 타임아웃:
# Increase polling timeout
max_wait_time = 900 # 15 minutes instead of 10
다운로드 시 비디오를 찾을 수 없음:
# Make sure video is completed before downloading
status = video_status(video_id=video_id)
if status.status != "completed":
print("Video not ready yet!")
API 키 에러:
# Verify your API key is set
import os
print(os.environ.get("GEMINI_API_KEY"))
# Or pass it explicitly
response = video_generation(
model="gemini/veo-3.0-generate-preview",
prompt="...",
api_key="your-api-key-here"
)