Home › Guides › Veo 3.1 image-to-video

Animating a still with the Veo 3.1 API

Updated 2026-10-02

Image-to-video is the mode where you already have the first frame (a product shot, a character render, a storyboard panel) and want the model to supply motion. With the Veo 3.1 family the request is the standard video call plus one field. The catch is that image input is a per-host capability, so this guide spends as much time on checking that as on the happy path.

The request

Pass start_image_url, either a public https:// URL or an inline data:image/...;base64,... URI. The rest of the body is the same as text-to-video:

import requests

API = "https://videorouter.sh/api/v1"
HEADERS = {"Authorization": "Bearer llmr_sk_live_...", "Content-Type": "application/json"}

job = requests.post(
    f"{API}/videos",
    headers=HEADERS,
    json={
        "model": "google/veo-3.1-fast/replicate",
        "prompt": "slow push-in on the mug, steam rising, soft morning light",
        "start_image_url": "https://example.com/mug.jpg",
        "duration_secs": 8,
        "aspect_ratio": "16:9",
        "resolution": "720p",
    },
).json()
print(job["id"], job["status"])

Then poll GET /videos/{id} exactly as you would for text-to-video. The job goes queued, in_progress, completed or failed, polling is free, and the URL is in data[0].url.

If your image is local, upload it first with POST /v1/uploads (multipart, up to 50 MB). It returns a presigned URL that expires after 30 minutes, which is enough to pass straight into the next call but not somewhere to store the file.

Check host support before you build on it

Whether a Veo variant accepts an image depends on the host serving it. In the gateway's wiring, image input is available on a subset of hosts for the Veo family. At the time of writing that includes Replicate for Veo 3.1 and Fast and SandBase across the three variants, and one host's Lite listing exists only as an image-to-video endpoint. Direct Google and some other hosts are wired for text-to-video only. That list moves as hosts are added, so do not hard-code it from an article.

Practical consequences:

Remember that the model/host suffix is a soft preference. If you need the request to fail rather than fall back to a host with different behaviour, use "provider": {"only": ["replicate"], "allow_fallbacks": false}.

Writing the prompt for a still

The image already fixes subject, composition and lighting, so the prompt should describe change, not the scene. A workable structure:

  1. Camera move (slow push-in, locked-off, gentle orbit).
  2. Subject motion (what moves, how fast, in which direction).
  3. Environmental motion (steam, hair, foliage, reflections).
  4. Constraint (what must stay unchanged, such as the logo or the face).

Re-describing everything in the frame invites the model to reinvent it. Keep the prompt short and verb-heavy, and vary one element per test so you can tell what caused a change.

Aspect ratio, resolution and duration

Lite, then Fast, then full

Image-to-video has a convenient property: the first frame is fixed, so a cheap draft tells you most of what you need about motion. A sensible loop:

  1. Run the motion prompt on google/veo-3.1-lite at a low resolution. You are checking whether the movement makes sense, not judging final fidelity.
  2. Promote the prompts you like to google/veo-3.1-fast and review at delivery resolution.
  3. Render only the approved shots on google/veo-3.1.

Two cautions. A cheaper tier is a preview of intent, not a pixel-exact preview of the final, so do not promise a client that the draft is what they will get. And because image support varies by host and variant, confirm each tier you plan to use accepts your image before relying on the ladder. The cost-strategy guide covers how to cap spend across the ladder.

Failure handling

Start with the quickstart if you have not made a first call yet, and grab a key at videorouter.sh/signup.

Frequently asked questions

How do I send an image to Veo 3.1?

Add start_image_url to the /videos request, as a public https URL or an inline base64 data URI. Image input is a per-host capability, so pin a host you have tested.

Do all Veo hosts support image-to-video?

No. Support is wired on a subset of hosts and variants, and models that do not take an image reject start_image_url with a 400. Check the model page and test one cheap call first.

What aspect ratio should I use?

Match your source image. Supported values are 16:9, 9:16, 1:1, 4:3, 3:4 and 21:9, but unsupported combinations are silently ignored, so verify the returned file.

Can I draft on Lite and finish on the full model?

Yes. All three variants share one request shape, so promoting a prompt is a change to the model string, provided the host you use accepts image input on each variant.

Keep reading

Using Veo is one part of the job.

VideoRouter puts it next to dozens of other video and image models behind one API key, so you can compare providers, prices and fail over automatically. Compare providers on VideoRouter →