Agent-JAE/default-skills/venice-list-video-models/scripts/list_video_models.py
jae a96a254473 fix: venice-list-video-models --help handling, venice-video-quote test params
- Added early --help handler in list_video_models.py before API call
- Fixed venice-video-quote self-test: audio=False for wan-2.5 model
- VENICE_API_KEY added to ~/.bashrc for runtime
2026-03-23 21:12:39 +01:00

313 lines
10 KiB
Python

"""List Venice.ai Video Models
This instrument fetches and displays all available video generation models from Venice.ai API
with comprehensive specifications for each model including:
- Supported durations
- Valid resolutions
- Aspect ratios (if configurable)
- Audio capabilities (generation, input, configurable)
- Video input support
- Beta/offline status
This information is CRITICAL for video generation - each model has different valid
parameter combinations that must be respected.
Usage:
python list_video_models.py # List all models
python list_video_models.py --detailed # Show full specs for each model
python list_video_models.py --model <id> # Show specs for specific model
python list_video_models.py --json # Output as JSON
"""
import os
import sys
import json
import requests
from typing import Optional
from dataclasses import dataclass, field, asdict
@dataclass
class VideoModelSpec:
"""Complete specification for a video generation model."""
id: str
name: str
model_type: str # text-to-video, image-to-video, video
# Generation constraints
durations: list = field(default_factory=list)
resolutions: list = field(default_factory=list)
aspect_ratios: list = field(default_factory=list)
# Audio capabilities
audio: bool = False
audio_configurable: bool = False
audio_input: bool = False
# Input requirements
video_input: bool = False
requires_image: bool = False
# Status
beta: bool = False
offline: bool = False
privacy: str = "anonymized"
VENICE_API_URL = "https://api.venice.ai/api/v1/models"
VENICE_API_KEY = os.getenv("VENICE_API_KEY")
def fetch_video_models():
"""Fetch all video models from Venice.ai API."""
if not VENICE_API_KEY:
raise ValueError("VENICE_API_KEY environment variable not set")
headers = {
"Authorization": f"Bearer {VENICE_API_KEY}",
"Content-Type": "application/json"
}
response = requests.get(VENICE_API_URL, headers=headers, params={"type": "video"}, timeout=30)
response.raise_for_status()
data = response.json()
models = []
for item in data.get("data", []):
spec = item.get("model_spec", {})
constraints = spec.get("constraints", {})
model_type = constraints.get("model_type", "unknown")
models.append(VideoModelSpec(
id=item.get("id", ""),
name=spec.get("name", item.get("id", "Unknown")),
model_type=model_type,
durations=constraints.get("durations", []),
resolutions=constraints.get("resolutions", []),
aspect_ratios=constraints.get("aspect_ratios", []),
audio=constraints.get("audio", False),
audio_configurable=constraints.get("audio_configurable", False),
audio_input=constraints.get("audio_input", False),
video_input=constraints.get("video_input", False),
requires_image=(model_type == "image-to-video"),
beta=spec.get("beta", False),
offline=spec.get("offline", False),
privacy=spec.get("privacy", "anonymized")
))
return models
def format_summary_table(models):
"""Format models as summary table grouped by type."""
lines = []
by_type = {}
for m in models:
by_type.setdefault(m.model_type, []).append(m)
for mtype in ["text-to-video", "image-to-video", "video"]:
if mtype not in by_type:
continue
type_models = by_type[mtype]
lines.append("")
lines.append("=" * 115)
lines.append(f" {mtype.upper()} MODELS ({len(type_models)})")
lines.append("=" * 115)
lines.append("")
lines.append(f" {'Model ID':<40} {'Durations':<25} {'Res':<12} {'Audio':<12} {'Audio In'}")
lines.append(f" {'-'*40} {'-'*25} {'-'*12} {'-'*12} {'-'*10}")
for m in sorted(type_models, key=lambda x: x.name):
durations = ", ".join(m.durations) if m.durations else "N/A"
resolutions = ", ".join(m.resolutions) if m.resolutions else "default"
audio = "Yes" if m.audio else "No"
if m.audio_configurable:
audio += " (cfg)"
audio_in = "Yes" if m.audio_input else "No"
status = ""
if m.beta:
status = " [BETA]"
if m.offline:
status = " [OFFLINE]"
lines.append(f" {m.id:<40} {durations:<25} {resolutions:<12} {audio:<12} {audio_in}{status}")
return "\n".join(lines)
def format_detailed_spec(model):
"""Format detailed specs for a single model."""
lines = []
lines.append("")
lines.append("=" * 75)
lines.append(f" {model.name}")
lines.append(f" ID: {model.id}")
lines.append("=" * 75)
lines.append("")
lines.append(f" Type: {model.model_type}")
status = []
if model.beta:
status.append("BETA")
if model.offline:
status.append("OFFLINE")
if status:
lines.append(f" Status: {', '.join(status)}")
lines.append("")
lines.append(" GENERATION PARAMETERS:")
lines.append(" " + "-" * 40)
if model.durations:
lines.append(f" duration: {' | '.join(model.durations)}")
else:
lines.append(f" duration: (not configurable)")
if model.resolutions:
lines.append(f" resolution: {' | '.join(model.resolutions)}")
else:
lines.append(f" resolution: (model default)")
if model.aspect_ratios:
lines.append(f" aspect_ratio: {' | '.join(model.aspect_ratios)}")
else:
lines.append(f" aspect_ratio: (NOT SUPPORTED - do not include in request)")
lines.append("")
lines.append(" AUDIO CAPABILITIES:")
lines.append(" " + "-" * 40)
lines.append(f" audio: {'Yes - generates audio' if model.audio else 'No'}")
lines.append(f" audio_configurable: {'Yes - can toggle on/off' if model.audio_configurable else 'No'}")
lines.append(f" audio_input: {'Yes - accepts audio' if model.audio_input else 'No'}")
lines.append("")
lines.append(" INPUT REQUIREMENTS:")
lines.append(" " + "-" * 40)
if model.model_type == "text-to-video":
lines.append(f" prompt: Required (text description)")
lines.append(f" image_url: Not used")
elif model.model_type == "image-to-video":
lines.append(f" prompt: Required (text description)")
lines.append(f" image_url: REQUIRED (base64 data URL or HTTP URL)")
elif model.model_type == "video":
lines.append(f" prompt: Required (text description)")
lines.append(f" video_url: {'Required' if model.video_input else 'Optional'}")
return "\n".join(lines)
def format_generation_example(model):
"""Generate example API call for this model."""
example = {
"model": model.id,
"prompt": "Your detailed prompt here"
}
if model.durations:
example["duration"] = model.durations[0]
if model.resolutions:
example["resolution"] = model.resolutions[0]
if model.aspect_ratios:
example["aspect_ratio"] = model.aspect_ratios[0]
if model.audio_configurable:
example["audio"] = True
if model.model_type == "image-to-video":
example["image_url"] = "data:image/jpeg;base64,... OR https://..."
return json.dumps(example, indent=2)
def output_json(models):
"""Output all models as JSON."""
return json.dumps([asdict(m) for m in models], indent=2)
def main():
args = sys.argv[1:]
# Handle --help before making any API calls
if "--help" in args or "-h" in args:
print("""List Venice.ai Video Models
Usage:
python list_video_models.py # List all models
python list_video_models.py --detailed # Show full specs for each model
python list_video_models.py --model <id> # Show specs for specific model
python list_video_models.py --json # Output as JSON
Options:
--help, -h Show this help message
--detailed Show full specifications for all models
--model <id> Show specs for a specific model (supports partial match)
--json Output all models as JSON
Environment:
VENICE_API_KEY Required. Your Venice.ai API key.""")
return
print("Fetching Venice.ai video models...")
print()
try:
models = fetch_video_models()
if "--json" in args:
print(output_json(models))
return
if "--model" in args:
idx = args.index("--model")
if idx + 1 < len(args):
model_id = args[idx + 1]
matching = [m for m in models if m.id == model_id or model_id in m.id]
if matching:
for m in matching:
print(format_detailed_spec(m))
print("\n EXAMPLE API REQUEST:")
print(" " + "-" * 40)
for line in format_generation_example(m).split("\n"):
print(f" {line}")
else:
print(f"No model found matching: {model_id}")
return
if "--detailed" in args:
for m in models:
print(format_detailed_spec(m))
return
print(f"Total video models available: {len(models)}")
print(format_summary_table(models))
print()
print("=" * 100)
print(" USAGE")
print("=" * 100)
print("""
--model <id> Show detailed specs for a specific model
--detailed Show specs for all models
--json Output as JSON
CRITICAL FOR VIDEO GENERATION:
* Each model has specific valid durations - use ONLY listed values
* aspect_ratio: ONLY include if model lists them (otherwise causes 400 errors)
* audio: check audio_configurable before including
* image-to-video models REQUIRE image_url parameter
""")
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()