Agent-JAE/default-skills/venice-video-quote/scripts/get_video_quote.py

193 lines
6 KiB
Python

"""# Venice.ai Video Quote Instrument
Get cost estimate for video generation before creating.
Validates parameters against model capabilities from the video models endpoint.
Usage: get_video_quote(model, duration, aspect_ratio="16:9", resolution="720p", audio=False)
"""
import os
import requests
from typing import Optional
from pydantic import BaseModel, Field
# API Configuration
VENICE_QUOTE_URL = "https://api.venice.ai/api/v1/video/quote"
VENICE_MODELS_URL = "https://api.venice.ai/api/v1/models"
VENICE_API_KEY = os.getenv("VENICE_API_KEY")
# Pydantic Models
class VideoQuoteRequest(BaseModel):
model: str
duration: str
aspect_ratio: str = "16:9"
resolution: str = "720p"
audio: bool = False
class VideoQuoteResponse(BaseModel):
quote: float
model: Optional[str] = None
config: Optional[dict] = None
class ModelCapabilities(BaseModel):
"""Extracted capabilities for a video model."""
model_id: str
name: str
model_type: str
durations: list[str]
aspect_ratios: list[str]
resolutions: list[str]
supports_audio: bool
def get_video_model_capabilities(model_id: str) -> Optional[ModelCapabilities]:
"""Fetch capabilities for a specific video model."""
headers = {
"Authorization": f"Bearer {VENICE_API_KEY}",
"Content-Type": "application/json"
}
response = requests.get(
VENICE_MODELS_URL,
headers=headers,
params={"type": "video"},
timeout=30
)
response.raise_for_status()
data = response.json()
for model in data.get("data", []):
if model["id"] == model_id:
spec = model.get("model_spec", {})
constraints = spec.get("constraints", {})
return ModelCapabilities(
model_id=model["id"],
name=spec.get("name", model["id"]),
model_type=constraints.get("model_type", "unknown"),
durations=constraints.get("durations", []),
aspect_ratios=constraints.get("aspect_ratios", []),
resolutions=constraints.get("resolutions", []),
supports_audio=constraints.get("supported_audio", {}).get("configurable", False)
)
return None
def validate_quote_params(caps: ModelCapabilities, duration: str, aspect_ratio: str, resolution: str, audio: bool) -> list[str]:
"""Validate quote parameters against model capabilities."""
errors = []
if duration not in caps.durations:
errors.append(f"Invalid duration '{duration}'. Valid: {caps.durations}")
if aspect_ratio not in caps.aspect_ratios:
errors.append(f"Invalid aspect_ratio '{aspect_ratio}'. Valid: {caps.aspect_ratios}")
if resolution not in caps.resolutions:
errors.append(f"Invalid resolution '{resolution}'. Valid: {caps.resolutions}")
if audio and not caps.supports_audio:
errors.append(f"Model '{caps.model_id}' does not support audio")
return errors
def get_video_quote(
model: str,
duration: str,
aspect_ratio: str = "16:9",
resolution: str = "720p",
audio: bool = False,
validate: bool = True
) -> VideoQuoteResponse:
"""Get price quote for video generation with optional validation."""
headers = {
"Authorization": f"Bearer {VENICE_API_KEY}",
"Content-Type": "application/json"
}
# Validate against model capabilities
if validate:
caps = get_video_model_capabilities(model)
if caps is None:
raise ValueError(f"Model '{model}' not found. Use list_video_models() to see available models.")
errors = validate_quote_params(caps, duration, aspect_ratio, resolution, audio)
if errors:
error_msg = f"Invalid parameters for model '{model}': " + "; ".join(errors)
raise ValueError(error_msg)
request = VideoQuoteRequest(
model=model,
duration=duration,
aspect_ratio=aspect_ratio,
resolution=resolution,
audio=audio
)
response = requests.post(
VENICE_QUOTE_URL,
headers=headers,
json=request.dict(),
timeout=30
)
response.raise_for_status()
result = VideoQuoteResponse(**response.json())
result.model = model
result.config = request.dict()
return result
def show_model_options(model_id: str) -> None:
"""Print valid options for a video model."""
caps = get_video_model_capabilities(model_id)
if caps is None:
print(f"Model '{model_id}' not found")
return
print(f"Model: {caps.name} ({caps.model_id})")
print(f"Type: {caps.model_type}")
print(f"Durations: {', '.join(caps.durations)}")
print(f"Aspect Ratios: {', '.join(caps.aspect_ratios)}")
print(f"Resolutions: {', '.join(caps.resolutions)}")
print(f"Audio: {'Yes' if caps.supports_audio else 'No'}")
if __name__ == "__main__":
print("=" * 70)
print("Venice.ai Video Quote - With Model Validation")
print("=" * 70)
# Show options for models
print("\n>>> Model: wan-2.5-preview-text-to-video")
show_model_options("wan-2.5-preview-text-to-video")
print("\n>>> Model: ltx-2-fast-text-to-video")
show_model_options("ltx-2-fast-text-to-video")
# Valid quote
print("\n" + "-" * 70)
print("Testing VALID quote request:")
try:
quote = get_video_quote(
model="wan-2.5-preview-text-to-video",
duration="10s",
aspect_ratio="16:9",
resolution="720p",
audio=False
)
print(f" ✅ Quote: ${quote.quote:.2f}")
except ValueError as e:
print(f"{e}")
# Invalid quote (wrong resolution for LTX)
print("\nTesting INVALID quote request (720p on LTX model):")
try:
quote = get_video_quote(
model="ltx-2-fast-text-to-video",
duration="10s",
aspect_ratio="16:9",
resolution="720p",
audio=True
)
print(f" Quote: ${quote.quote:.2f}")
except ValueError as e:
print(f" ✅ Caught validation error: {e}")