Files
Aether/tests/test_veo.py
T

208 lines
5.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
Veo Video Generation Test Script
This script demonstrates video generation using Google's Veo API.
It sends a request to generate a video, polls for completion, and downloads the result.
Usage:
export GEMINI_API_KEY="your-api-key"
python test_veo.py
"""
from __future__ import annotations
import os
import sys
import time
import requests
# Gemini API Base URL
BASE_URL = "http://localhost:8084/v1beta"
# Default polling interval in seconds
POLL_INTERVAL = 10
os.environ["GEMINI_API_KEY"] = "sk-PCr5oXZNKb9HcyzYqTIMvr8zXsIBK3WS"
def generate_video(api_key: str, prompt: str, model: str = "veo-3.1-fast-generate-preview") -> str:
"""
Send a request to generate a video and return the operation name.
Args:
api_key: Gemini API key
prompt: Text prompt for video generation
model: Model name to use (default: veo-3.1-generate-preview)
Returns:
Operation name for polling status
"""
url = f"{BASE_URL}/models/{model}:predictLongRunning"
headers = {
"x-goog-api-key": api_key,
"Content-Type": "application/json",
}
payload = {
"instances": [
{
"prompt": prompt,
}
]
}
print(f"Sending video generation request to {model}...")
response = requests.post(url, headers=headers, json=payload, timeout=60)
response.raise_for_status()
data = response.json()
operation_name = data.get("name")
if not operation_name:
raise ValueError(f"No operation name in response: {data}")
print(f"Operation started: {operation_name}")
return operation_name
def poll_operation(api_key: str, operation_name: str, poll_interval: int = POLL_INTERVAL) -> dict:
"""
Poll the operation status until the video is ready.
Args:
api_key: Gemini API key
operation_name: Operation name from generate_video
poll_interval: Seconds between polls (default: 10)
Returns:
Final response dict containing the video URI
"""
url = f"{BASE_URL}/{operation_name}"
headers = {
"x-goog-api-key": api_key,
}
print(f"Polling operation status (every {poll_interval}s)...")
while True:
response = requests.get(url, headers=headers, timeout=60)
response.raise_for_status()
data = response.json()
is_done = data.get("done", False)
if is_done:
print("Operation completed!")
# Check for errors
if "error" in data:
error = data["error"]
raise RuntimeError(f"Operation failed: {error.get('message', error)}")
return data
# Show progress if available
metadata = data.get("metadata", {})
if metadata:
progress = metadata.get("progress", "unknown")
print(f" Progress: {progress}%")
time.sleep(poll_interval)
def download_video(api_key: str, video_uri: str, output_path: str = "dialogue_example.mp4") -> str:
"""
Download the generated video.
Args:
api_key: Gemini API key
video_uri: URI of the generated video
output_path: Path to save the video (default: dialogue_example.mp4)
Returns:
Path to the downloaded video
"""
headers = {
"x-goog-api-key": api_key,
}
print(f"Downloading video from: {video_uri}")
response = requests.get(video_uri, headers=headers, allow_redirects=True, timeout=300, stream=True)
response.raise_for_status()
with open(output_path, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
file_size = os.path.getsize(output_path)
print(f"Video saved to: {output_path} ({file_size / 1024 / 1024:.2f} MB)")
return output_path
def extract_video_uri(response: dict) -> str:
"""
Extract the video URI from the operation response.
Args:
response: Final operation response dict
Returns:
Video download URI
"""
try:
video_response = response["response"]["generateVideoResponse"]
samples = video_response["generatedSamples"]
video_uri = samples[0]["video"]["uri"]
return video_uri
except (KeyError, IndexError) as e:
raise ValueError(f"Could not extract video URI from response: {response}") from e
def main() -> None:
"""Main entry point."""
# Get API key from environment
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
print("Error: GEMINI_API_KEY environment variable not set", file=sys.stderr)
print("Usage: export GEMINI_API_KEY='your-api-key' && python test_veo.py", file=sys.stderr)
sys.exit(1)
# Default prompt (same as the bash script)
prompt = (
"A close up of two people staring at a cryptic drawing on a wall, "
"torchlight flickering. A man murmurs, \"This must be it. That's the secret code.\" "
"The woman looks at him and whispering excitedly, \"What did you find?\""
)
# Allow custom prompt via command line argument
if len(sys.argv) > 1:
prompt = " ".join(sys.argv[1:])
print(f"Using custom prompt: {prompt}")
try:
# Step 1: Start video generation
operation_name = generate_video(api_key, prompt)
# Step 2: Poll until complete
final_response = poll_operation(api_key, operation_name)
# Step 3: Extract video URI and download
video_uri = extract_video_uri(final_response)
download_video(api_key, video_uri)
print("\nVideo generation complete!")
except requests.exceptions.HTTPError as e:
print(f"HTTP Error: {e}", file=sys.stderr)
if e.response is not None:
print(f"Response: {e.response.text}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()