Animating a still with runway/gen-4.5: image prep, motion prompts and checks
Updated 2026-10-02
The Gen-4.5 guide shows the basic image-to-video request. This page goes into the part that decides whether the result is usable: how you prepare the still, what the prompt should and should not say, and the checks that catch problems before they multiply across a batch. It assumes runway/gen-4.5 as the model id and the documented start_image_url field. Host-specific behaviour (which inputs a host accepts, supported tiers) varies, so check the model page for the host you use.
The request
curl https://videorouter.sh/api/v1/videos \
-H "Authorization: Bearer llmr_sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "runway/gen-4.5",
"prompt": "slow push-in, the woman turns her head toward the window, curtains move in a light breeze",
"start_image_url": "https://example.com/frame.jpg",
"duration_secs": 5
}'
start_image_url accepts a public https:// URL or an inline data:image/...;base64,... URI. The job is asynchronous: poll GET /videos/{id} until completed or failed. Polling is free, billing is once at creation from the requested duration, and a job that fails upstream is not billed. If you send start_image_url to a model or host that does not support it, the request fails with a 400 rather than being ignored. Only the start frame is supported; end_image_url is documented as rejected with a 400.
Prepare the image
The model animates what it is given, so most of the quality control happens before the request.
- Match the aspect ratio. If you pass a 4:5 photo and ask for 16:9, something has to give. Crop the still to your target ratio yourself so you decide what stays in frame. Supported ratios in the docs are 16:9, 9:16, 1:1, 4:3, 3:4 and 21:9, but a given model supports only some, and unsupported combinations are ignored rather than rejected.
- Use a clean, sharp source. Compression artefacts and noise in the still tend to become visible motion. Export at moderate size with minimal JPEG compression.
- Leave room for the motion you want. If the camera should push in or the subject should walk right, a frame with the subject jammed against that edge leaves nowhere to go.
- Keep the subject unambiguous. A frame with several competing subjects gives the model several things to animate.
from PIL import Image
img = Image.open("photo.jpg").convert("RGB")
w, h = img.size
target = 16 / 9
if w / h > target: # too wide: crop sides
nw = int(h * target); x = (w - nw) // 2
img = img.crop((x, 0, x + nw, h))
else: # too tall: crop top/bottom
nh = int(w / target); y = (h - nh) // 2
img = img.crop((0, y, w, y + nh))
img = img.resize((1920, 1080), Image.LANCZOS)
img.save("frame.jpg", quality=92)
Center cropping is only a default. For a portrait you may want to crop around the face instead.
Write the prompt for motion, not content
The image already says what is in the scene. Re-describing it wastes words and can pull the model away from the frame you chose. Spend the prompt on three things:
- Camera: "slow push-in", "static tripod shot", "handheld, slight sway", "orbit left around the subject".
- Subject action: one verb phrase, "turns her head toward the window", not a sequence of five.
- Environment motion: "curtains move in a light breeze", "rain falls", "steam rises".
| Weak | Stronger |
|---|---|
| A beautiful woman in a bright room, cinematic, 4k | Slow push-in, she turns her head toward the window, curtains move gently |
| Make the car drive, lots of action | Static camera, the car pulls away from the kerb and exits frame left |
| Amazing product video | Slow orbit around the bottle, soft light shifts across the glass |
Keep the clip short while you iterate. Short durations cost less, and motion that goes wrong tends to go wrong early.
Hosting the image
Expired signed URLs are a common cause of failed image-to-video jobs: the host fetches the image after you submit, possibly after queueing, so a link that lasts a few minutes may be gone when it is needed. Use a URL that stays valid for the job's lifetime, or send a base64 data URI. Test the link from outside your network with curl -I before submitting.
Verification steps
- One job first. Submit a single request with a short
duration_secsand inspect the result. - Check dimensions.
ffprobe -v error -show_entries stream=width,height,duration -of csv=p=0 out.mp4. If the size is not what you asked for, the resolution or ratio was ignored. - Check the first frame. Extract it with
ffmpeg -i out.mp4 -frames:v 1 first.pngand compare with your still. A large difference means the model deviated from the source. - Check the duration billed against the duration delivered. Durations snap to supported values, so read the job back instead of assuming.
- Only then scale. Reuse the prompt template, change the image, and keep the job ids so you can trace any bad output.
When it fails or looks wrong
| Symptom | Likely cause | What to try |
|---|---|---|
| 400 on create | Host or model does not accept the field you sent | Check the model page for the host's accepted inputs; remove unsupported fields |
Job failed | Unreachable or rejected image | Verify the URL; read the job's error |
| Subject barely moves | Prompt describes the scene, not an action | Add one explicit action and one camera move |
| Frame drifts from the still | Over-long or conflicting prompt | Shorten it; keep a single action |
Because Gen-4.5 has few hosts, keep a second model ready in your own code for anything customer-facing; the same request shape works across the catalog, so swapping is a change to the model string. See the model pages for hosts, the pricing page for the live comparison, and sign up to run your first job.
Frequently asked questions
How do I send an image to runway/gen-4.5?
Add start_image_url to the POST /videos request, either a public https URL or a base64 data URI, along with a motion-focused prompt.
Can I set the last frame as well?
No. end_image_url is documented as accepted by no model yet and is rejected with a 400, so only the start frame can be controlled.
What should the prompt contain for image-to-video?
Camera movement, one subject action and any environmental motion. The image already supplies the content, so avoid re-describing it.
Why did my image-to-video job fail?
Common causes are an unreachable or expired image URL and sending a field the chosen host does not support. Read the job's error and check the model page for the host.
Keep reading
- Editing Video with Runway Aleph 2 over API — Request Format and Limits
- Runway Gen-4.5 API Guide: Text & Image-to-Video Examples
- Runway vs Kling vs Veo API: How to Choose Between Them
- Video-to-Video Editing API Options: Aleph 2 and Alternatives
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 →