AI Video Generation Duration API — Set Length for Veo 3.1, Grok & Omni Flash
You're building a social media automation tool that needs 5-second clips for short-form posts and 15-second clips for mid-roll ads — from the same API. Or you're running a product demo generator where clip length should match a script's word count. Getting duration control right from the start saves you from re-architecting your job submission layer once you're in production.
This guide covers how to set video generation duration via the GenRelay API, the per-model duration parameters, duration limits for each model, and how duration interacts with per-second billing to directly determine your generation cost.
How Does Duration Affect AI Video Generation Cost?
Duration's cost impact depends on the billing model the video API uses. As of September 2026, GenRelay's video models use two billing approaches:
Per-second billing — Veo 3.1 Lite and Grok Imagine models charge per second of output video. Generating a longer clip costs proportionally more:
| Model | 720p ($/s) | 1080p ($/s) |
|---|---|---|
| Veo 3.1 Lite (t2v / i2v / ref2v) | $0.060 | $0.120 |
| Grok Imagine 1.5 (i2v) | $0.022 | — |
| Grok Imagine 1.0 (t2v) | $0.010 | — |
Per-generation billing — Gemini Omni Flash charges a flat fee per completed video regardless of duration:
| Resolution | Cost per generation |
|---|---|
| 720p | $0.10 |
| 1080p | $0.15 |
Omni Flash's flat-rate model means a 4-second and a 12-second clip at 720p cost the same $0.10. This makes it economical when you regularly need longer clips but less predictable when clips are short.
Example cost comparison — 8-second clip at 720p:
| Model | Billing | Cost for 8 s |
|---|---|---|
| Veo 3.1 Lite | Per second | 8 × $0.060 = $0.480 |
| Grok 1.0 | Per second | 8 × $0.010 = $0.080 |
| Grok 1.5 | Per second | 8 × $0.022 = $0.176 |
| Omni Flash | Per generation | flat $0.100 |
For clips under roughly 10 seconds at 720p, Grok 1.0 is cheapest on a per-second basis. Omni Flash becomes cost-competitive around 4–10 seconds depending on the model you're comparing against.
How Do I Set Duration in the GenRelay Video API?
Submit a duration parameter (in seconds) alongside your model, prompt, and resolution in the job creation request. Video generation is asynchronous — you receive a job ID immediately and poll for the completed video URL.
Here's a complete Python example with async polling:
import requests
import time
API_KEY = "your-genrelay-api-key"
BASE_URL = "https://genrelay.ai/v1"
def generate_video(
prompt: str,
model: str = "veo-3-lite",
resolution: str = "720p",
duration: int = 5,
poll_interval: int = 8,
timeout: int = 300,
) -> str:
"""Submit a video generation job and return the video URL."""
# Step 1: Submit the job
resp = requests.post(
f"{BASE_URL}/videos/generations",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": model,
"prompt": prompt,
"resolution": resolution,
"duration": duration,
},
)
resp.raise_for_status()
job_id = resp.json()["id"]
print(f"Job submitted: {job_id} | {model} | {duration}s @ {resolution}")
# Step 2: Poll until complete or timeout
deadline = time.time() + timeout
while time.time() < deadline:
time.sleep(poll_interval)
status_resp = requests.get(
f"{BASE_URL}/videos/generations/{job_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
)
status_resp.raise_for_status()
result = status_resp.json()
if result["status"] == "succeeded":
return result["output"]["url"]
elif result["status"] == "failed":
raise RuntimeError(f"Generation failed: {result.get('error')}")
raise TimeoutError(f"Job {job_id} did not complete within {timeout}s")
# Usage — generate a 5-second Grok 1.0 clip (cheapest for short clips)
url = generate_video(
prompt="A developer types code in a dark office; monitor glow reflects on glasses",
model="grok-imagine-1.0",
resolution="720p",
duration=5,
)
print(f"Video ready: {url}")
For Omni Flash, duration is still submitted the same way — but since billing is per generation, the duration value affects clip length without affecting cost:
# Omni Flash — $0.10/generation at 720p regardless of duration
url = generate_video(
prompt="Product on rotating white pedestal with soft studio lighting",
model="omni-flash",
resolution="720p",
duration=8, # 8s costs the same as 4s on Omni Flash
)
What Duration Ranges Does Each Model Support?
Each model supports a specific range of duration values. Requesting a value outside the supported range returns a 400 invalid_request error.
| Model | Min duration | Max duration | Supported values |
|---|---|---|---|
| Veo 3.1 Lite (t2v / i2v / ref2v) | 5 s | 8 s | 5, 6, 7, 8 |
| Grok Imagine 1.0 (t2v) | 5 s | 10 s | 5–10 (integer steps) |
| Grok Imagine 1.5 (i2v) | 5 s | 8 s | 5, 6, 7, 8 |
| Gemini Omni Flash | 4 s | 12 s | 4–12 (integer steps) |
If your use case requires clips longer than 8 seconds, Omni Flash and Grok 1.0 cover up to 10–12 seconds. For clips beyond that, the typical pattern is to generate sequential clips and concatenate in post-processing.
How Do I Choose Duration Based on Cost and Use Case?
Match duration to the billing model and use case rather than always requesting the maximum:
Short-form social (5 s):
- Grok 1.0 at 720p: 5 × $0.010 = $0.050/clip — lowest cost for 5-second social clips.
- Omni Flash at 720p: $0.100/clip flat — 2× more expensive for 5s.
Mid-length marketing (8 s at 720p):
- Omni Flash: $0.100 flat.
- Grok 1.0: 8 × $0.010 = $0.080 — slightly cheaper if you need controllable motion prompts.
- Veo 3.1 Lite: 8 × $0.060 = $0.480 — significantly higher cost; justified when visual quality is the primary requirement.
Longer explainer content (10–12 s):
- Grok 1.0 (up to 10s): 10 × $0.010 = $0.100.
- Omni Flash (up to 12s): $0.100 flat — cost parity at 10s, then cheaper for 11s+.
A production job dispatcher that selects model and duration based on content type:
def dispatch_video_job(
prompt: str,
use_case: str, # "social_short" | "marketing_mid" | "explainer_long"
api_key: str,
) -> str:
configs = {
"social_short": {
"model": "grok-imagine-1.0",
"resolution": "720p",
"duration": 5,
},
"marketing_mid": {
"model": "omni-flash",
"resolution": "1080p",
"duration": 8,
},
"explainer_long": {
"model": "omni-flash",
"resolution": "720p",
"duration": 12,
},
}
config = configs.get(use_case)
if not config:
raise ValueError(f"Unknown use case: {use_case}")
resp = requests.post(
"https://genrelay.ai/v1/videos/generations",
headers={"Authorization": f"Bearer {api_key}"},
json={"prompt": prompt, **config},
)
resp.raise_for_status()
return resp.json()["id"]
How Does Duration Interact with Resolution on Cost?
For per-second models, resolution multiplies the per-second rate. At 1080p, Veo 3.1 Lite costs exactly 2× the 720p rate:
| Clip | 720p cost | 1080p cost |
|---|---|---|
| Veo 3.1 Lite — 5 s | 5 × $0.060 = $0.300 | 5 × $0.120 = $0.600 |
| Veo 3.1 Lite — 8 s | 8 × $0.060 = $0.480 | 8 × $0.120 = $0.960 |
| Grok 1.5 — 5 s | 5 × $0.022 = $0.110 | N/A |
| Grok 1.5 — 8 s | 8 × $0.022 = $0.176 | N/A |
For Omni Flash, resolution shifts the flat rate: 720p is $0.10/generation, 1080p is $0.15/generation. Duration doesn't change either number.
When budgeting at scale — say 1,000 clips/day — the resolution × duration product is your primary cost lever:
# Cost estimation utility
def estimate_monthly_cost(
clips_per_day: int,
model: str,
resolution: str,
duration: int,
) -> float:
per_second_rates = {
("veo-3-lite", "720p"): 0.060,
("veo-3-lite", "1080p"): 0.120,
("grok-imagine-1.0", "720p"): 0.010,
("grok-imagine-1.5", "720p"): 0.022,
}
flat_rates = {
("omni-flash", "720p"): 0.10,
("omni-flash", "1080p"): 0.15,
}
key = (model, resolution)
if key in per_second_rates:
cost_per_clip = per_second_rates[key] * duration
elif key in flat_rates:
cost_per_clip = flat_rates[key]
else:
raise ValueError(f"Unknown model/resolution: {key}")
return cost_per_clip * clips_per_day * 30
# Example: 1,000 clips/day × 5s × Grok 1.0 × 720p
monthly = estimate_monthly_cost(1000, "grok-imagine-1.0", "720p", 5)
print(f"Estimated monthly cost: ${monthly:,.2f}") # → $1,500.00
For a deeper look at cost math across workload sizes, see how much does AI video generation cost via API. For async polling patterns and per-model poll intervals, see async video generation API — how to poll for results.
FAQ
Does Omni Flash support a duration parameter?
Yes. Omni Flash accepts duration values from 4 to 12 seconds. Unlike per-second models, the duration you request does not affect the cost — Omni Flash charges a flat rate per generation regardless of clip length.
What happens if I request a duration outside a model's supported range?
The API returns a 400 invalid_request error with a message indicating the valid range. No credits are consumed. Validate the duration against the model's range in your application layer before submitting jobs.
Can I generate clips longer than 12 seconds?
Not in a single API call with current models. The common approach for longer content is to generate sequential clips with overlapping or matched prompts and concatenate them in post-processing using ffmpeg or a cloud media pipeline.
Does duration affect generation latency, not just cost?
Yes. Longer clips take more time to generate. A 5-second Veo 3.1 Lite clip typically completes in 60–120 seconds of wall-clock time; an 8-second clip at 1080p may take 180–240 seconds. Adjust your polling timeout and poll interval accordingly — see the async video API polling guide for per-model recommendations.
Are there duration restrictions for image-to-video jobs?
Grok Imagine 1.5 (i2v) supports durations of 5–8 seconds, matching Veo 3.1 Lite's range. Veo 3.1 i2v also accepts 5–8 seconds. Submit the duration parameter alongside your image_url in the job payload; the format is identical to text-to-video requests.