How to Generate High-Volume Video With the Veo 3.1 Lite API
If you've ever needed twenty versions of the same 6-second product clip for an A/B test and balked at what that would cost on a full-quality video model, Veo 3.1 Lite is the tier Google built for exactly that. It's the cheapest model in the Veo 3.1 family on Vertex AI, and it's meant for the kind of high-volume, throwaway generation that ad creative, storyboard previews and variant testing actually need.
This walks through calling the Veo 3.1 Lite API directly, generating a batch of variants in a script, and knowing where the Fast and standard tiers still beat it.
Turn on the Vertex AI API and authenticate
You need a Google Cloud project with billing enabled and the Vertex AI API turned on. Authenticate with application default credentials so your scripts can get a token without embedding a key.
gcloud auth application-default login
gcloud config set project <your-project-id>
gcloud services enable aiplatform.googleapis.com
Veo generation runs through us-central1 today, so keep your project, bucket and requests in that region unless you've confirmed another region works for your account.
Call the Veo 3.1 Lite API for your first batch
Veo models don't run on the normal predict endpoint. Video generation is asynchronous, so you kick it off with predictLongRunning and poll for the result. The model ID for this tier is veo-3.1-lite-generate-001.
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://us-central1-aiplatform.googleapis.com/v1/projects/<your-project-id>/locations/us-central1/publishers/google/models/veo-3.1-lite-generate-001:predictLongRunning" \
-d '{
"instances": [
{ "prompt": "A red kettlebell spinning on a white studio backdrop, product ad style, soft studio lighting" }
],
"parameters": {
"aspectRatio": "9:16",
"durationSeconds": 6,
"sampleCount": 4,
"resolution": "1080p",
"generateAudio": false,
"personGeneration": "allow_adult",
"storageUri": "gs://<your-bucket>/veo-variants/"
}
}'
sampleCount gives you multiple takes from one call, which is the cheapest way to get variants: one prompt, several outputs. storageUri writes the finished MP4s straight to a bucket instead of returning them inline. The response is an operation name, not a video.
Poll predictLongRunning until your videos land
Feed that operation name to fetchPredictOperation until done comes back true.
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://us-central1-aiplatform.googleapis.com/v1/projects/<your-project-id>/locations/us-central1/publishers/google/models/veo-3.1-lite-generate-001:fetchPredictOperation" \
-d '{ "operationName": "projects/<your-project-id>/locations/us-central1/publishers/google/models/veo-3.1-lite-generate-001/operations/<operation-id>" }'
If you'd rather see clips before you script anything, Vertex AI Media Studio runs the same model through a console UI, which is a faster way to iterate on a prompt before you commit it to a batch job.
Script it for high-volume video generation
For real volume, loop the call across a list of prompt and aspect ratio variants, fire them all, then poll the whole set.
import time
import requests
import google.auth
import google.auth.transport.requests
PROJECT_ID = "<your-project-id>"
LOCATION = "us-central1"
MODEL_ID = "veo-3.1-lite-generate-001"
BASE_URL = (
f"https://{LOCATION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}"
f"/locations/{LOCATION}/publishers/google/models/{MODEL_ID}"
)
creds, _ = google.auth.default()
creds.refresh(google.auth.transport.requests.Request())
headers = {"Authorization": f"Bearer {creds.token}", "Content-Type": "application/json"}
variants = [
{"prompt": "Kettlebell ad, energetic gym lighting", "aspectRatio": "9:16"},
{"prompt": "Kettlebell ad, calm studio lighting", "aspectRatio": "16:9"},
]
operations = []
for v in variants:
body = {
"instances": [{"prompt": v["prompt"]}],
"parameters": {
"aspectRatio": v["aspectRatio"],
"durationSeconds": 6,
"sampleCount": 2,
"resolution": "1080p",
"generateAudio": False,
"storageUri": "gs://<your-bucket>/veo-variants/",
},
}
resp = requests.post(f"{BASE_URL}:predictLongRunning", headers=headers, json=body)
operations.append(resp.json()["name"])
while operations:
for op_name in list(operations):
resp = requests.post(f"{BASE_URL}:fetchPredictOperation", headers=headers, json={"operationName": op_name})
result = resp.json()
if result.get("done"):
print(op_name, "->", result["response"])
operations.remove(op_name)
time.sleep(10)
The service account running this needs Storage Object Admin on the output bucket, or the writes to storageUri will fail silently on the operation's error field.
Veo 3.1 Fast vs Lite: picking the right tier
Lite and Fast are closer than you'd think on capability: both cap out at 1080p, both support native audio through generateAudio, and both hand you clips in 4, 6 or 8 second lengths at 16:9 or 9:16. The difference is what Lite drops to get cheaper: no video extension, and no reference-image conditioning. If your pipeline needs to extend a clip past its first cut or steer generation from a reference frame, that's a Fast or full Veo 3.1 job, not a Lite one. If you just need a lot of short, disposable variants fast, Lite is the tier this was built for. Full Veo 3.1 is the only tier that reaches 4K, and it's the one to reserve for the final cut once a variant wins.
The real cost math
Google's own positioning for Lite is that it costs less than half of what Fast charges per second, which is the whole point of the tier: you're meant to generate ten times the variants for the same budget, not run your existing volume for less. Rates move, so check the current Vertex AI Veo pricing before you size a budget, and multiply by durationSeconds * sampleCount * number of prompts, since that's what actually shows up on the bill.
Gotchas
- The new Veo upscaling pass to 1080p and 4K is still private preview. You can't call it from the API yet, so don't design a pipeline around upscaling Lite output until Google opens it up.
- Lite has no extend and no reference-image support. Confirm your creative brief doesn't secretly need either before you build around it.
- Responsible AI filtering can quietly return fewer clips than the
sampleCountyou asked for. Check each operation's response for filtered results instead of assuming every request produced a full set. storageUrifailures show up in the operation response, not as an HTTP error. Check it explicitly in your polling loop.
Once this loop is running, generating fifty ad variants overnight costs about the same as generating five did on Fast, which is the entire reason to reach for Lite before you reach for anything more expensive.