---
title: Turn a product photo into a video without redrawing the product
description: A product video, or image-to-video ad, from your product photos, where the label, shape and color stay exactly as in your photo.
---
You get a short product video, also called an image-to-video ad or product animation, from your product photos. The camera moves, the background lives, and the product looks exactly like the one you sell. The label, the shape and the color come from your photo, not from a model's guess.

Use invideo for this when the product must stay exact: your agent keeps your real photo on the timeline for every shot where the label shows, moves it with free effects and keyframes, and uses a model only where a redraw does no harm.

This is ordinary product marketing work, and the agent does it. You choose where the video runs and you publish it.

## Quickest path

Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt.

```text
Make a 12 second vertical product video from ./bottle.jpg and
./bottle-side.jpg. Cut the bottle out, put it on a soft studio
background, a slow push in, then a lifestyle shot made with a model.
The label must never change. Tell me the price before you generate.
```

In a chat app, you drag the photos into the project in invideo. In a terminal, you name the files and the agent uploads them.

## What you need

The photo is the product. A better photo gives a better video.

- **Product photos.** Sharp, well lit, at a high resolution. A front shot and one or two angles.
- **A clean background, if you have one.** A plain backdrop makes the cutout clean.
- **The shots you want.** A push in, a turn, a lifestyle scene, the product in a hand.
- **The shape.** 9:16 for Reels and TikTok, 1:1 or 4:5 for feeds, 16:9 for a store page.
- **The words.** The product name, one claim and the call to action.

## Steps

The agent sorts each shot into two kinds: exact shots that use your photo, and mood shots that may use a model.

<Steps>
<Step title="Bring the photos in">
The agent makes a project with `new_project`, a timeline with `new_timeline`, and a branch with `timeline_history`. It uploads each photo with `start_upload` and `add_media`. Expected result: a sequence URL per photo.
</Step>
<Step title="Cut the product out">
The agent runs `media` `image.removeBackground` on the front photo, with `dry_run` first, then `max_credits` set to the price and an `idempotency_key`. The default model is `bria_bg_remove`. `birefnet_bg_remove` is the other choice. Expected result: a cutout of the product as a new sequence. The agent looks at it with `read`, which returns the image, and checks the edges.
</Step>
<Step title="Build the exact shots on the timeline">
The agent places a background on `V1` and the cutout above it with `insert_media`. It adds the `dynamic_zoom` effect with `add_effect` for a slow push. For a turn or a slide, it uses `set_keyframes` on `rotation`, or a lane from `add_keyframe_lane` on `position_x` or `zoom_x` and `zoom_y`, filled with `add_keyframes`. This is free, and every pixel of the product is your photo. Expected result: the product moves, and the label is sharp.
</Step>
<Step title="Make the mood shots with a model">
The agent runs `find_models` with the shot in words, picks a model, and reads its inputs with `get_model`. For a lifestyle scene, a good pick is `seedance_2_5.r2v` with your photos in `reference_images`. For a move from one photo, good picks are `kling_v4.kling_v4_frames` or `wan_27_alibaba.wan_27_i2v` with the photo as the first frame, or `camera_moves.image` for a set camera move. Your agent can search for others with `find_models`. It calls `generate` with `dry_run: true` and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. It sees a thread URL and, when the shot lands, a sequence URL. It reads that URL with `read` and never calls `generate` again to check. Expected result: a new video sequence per shot. A model redraws the product, so these shots keep the product small, moving or out of focus.
</Step>
<Step title="Check the product by eye">
The agent runs `capture` on every generated shot where the product shows, and compares each frame with your photo: the label text, the logo, the color, the cap, the shape. It replaces any shot where the product changed with an exact shot from your photo. Expected result: a product that matches your photo in every frame.
</Step>
<Step title="Add text and music">
The agent adds the product name and claim with `add_text`, and music with `search_library` in `stock_music` and `add_media`. Expected result: words on screen and music under the video.
</Step>
<Step title="Check and export">
The agent runs `capture` at each shot and each text, and `check_timeline`. Then it runs `export` with `format` video. Expected result: an export card with status `completed`.
</Step>
</Steps>

The same job from a terminal:

```bash
invideo project new --title "Bottle product video"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "Bottle 9x16" --width 1080 --height 1920
invideo asset upload <edit-url> ./bottle.jpg ./bottle-side.jpg
invideo media image.removeBackground <sequence-url> --dry-run
invideo media image.removeBackground <sequence-url> \
  --max-credits <price> --idempotency-key bottle-cutout
invideo gen models <project-url> --query "product lifestyle shot from photos"
invideo gen model <project-url> --model seedance_2_5.r2v
invideo gen run <page-url> --model seedance_2_5.r2v --dry-run \
  --input r2v-inputs.json
invideo gen run <page-url> --model seedance_2_5.r2v \
  --max-credits <price> --idempotency-key bottle-life-1 \
  --input r2v-inputs.json
invideo status <thread-url> --wait
invideo edit show <edit-url> --json
invideo edit change <edit-url> --timeline T1 --token <state_token> \
  --operations @ops.json
invideo edit capture <edit-url> --at 1,4,7,10 --out ./frames
invideo edit export <edit-url> --format video --quality 1080 --json
invideo status <card-url> --wait
invideo notebook show <card-url> --out ./out
```

Where the values come from: `<project-url>` from `invideo project new`, and `<edit-url>` from `invideo edit new`. `<name>` is the name you choose in `invideo agent register`. `<sequence-url>` is the `url` that `invideo asset upload` returns for the front photo. `<page-url>` is a notebook page from `invideo notebook show <project-url>`. `<price>` is each dry run's `estimated_credits`. `<thread-url>` is the `url` the paid `gen run` returns. `<state_token>` comes from `invideo edit show`. `<card-url>` is `.sequences[0]` of what the export returns. `invideo status` does not download; `invideo notebook show` saves the file as `export.mp4`.

The file `r2v-inputs.json` holds the model's inputs alone, as `get_model` lists them, with no `inputs` wrapper. The dry run and the paid run pass the same file, so the run that spends is the run that was priced.

```json
{
  "prompt": "The bottle on a sunny kitchen counter, slow push in",
  "reference_images": ["<sequence-url>", "<side-sequence-url>"],
  "aspect_ratio": "9:16",
  "duration": 6
}
```

`<side-sequence-url>` is the upload URL of the side photo.

The key MCP call cuts the product out. It is a dry run, so it returns the price and starts nothing.

```json
{
  "url": "<sequence-url>",
  "op": "image.removeBackground",
  "model": "bria_bg_remove",
  "dry_run": true
}
```

The agent then sends the same call with `dry_run` false, `max_credits` at the price, and an `idempotency_key`.

## Cost and time

Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything.

- **Free:** uploads, the exact shots with effects and keyframes, text, the checks and the export.
- **Costs credits:** the background removal, each model shot, and stock music. Most video models charge by the second, so short mood shots cost less.

A short product video takes under an hour, most of it on the model shots and the check. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems are a model that redrew the label, or a rough cutout edge.

| Symptom | Fix |
| --- | --- |
| `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. |
| Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status <url> --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. |
| The label text is wrong in a model shot | Use an exact shot from your photo for that moment. Models redraw text. |
| The color shifted in a model shot | Compare with `capture`. Replace the shot, or keep the product small in it. |
| The cutout has a halo | Try `birefnet_bg_remove`, or start from a photo on a plain backdrop. |
| `fill_frame` refused on the cutout | Its zoom is animated. Set the size with `set_zoom` before the lane. |
| `set_keyframes` refused for zoom | It takes `opacity` and `rotation` only. Use `add_keyframe_lane` and `add_keyframes`. |
| The download folder is empty | `invideo status` does not download. Run `invideo notebook show <card-url> --out ./out`. |
| `inputs is not an input of this model` | `r2v-inputs.json` has an `inputs` wrapper. Keep only the model's inputs in the file. |
| CLI exit 5 | A credit limit. Use more exact shots, which are free. |
| Avoid: the agent says the product "should look the same" | Instead: it captures frames and compares them with your photo. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make a 6 second 1:1 loop of my sneaker ./shoe.png turning slowly on a
pastel background. No model, only my photo.
```

```text
Make three 8 second lifestyle shots of my candle from these photos,
kitchen, bedroom and patio, then check the label in every frame.
```

```text
Make a 15 second Amazon-style video from my 5 product photos: a push
on each, a feature line on each, white background, no music.
```

## When to use something else

invideo does not turn a photo into a 3D model you can spin freely. For a true 360 view, shoot the product on a turntable, or use a 3D tool, and bring the clip in.

For the product photos themselves, a studio shoot gives the cleanest result. If you need new photos made from your product, an image model can help, but check the label the same way.

## Related

- [Make a UGC ad from product photos with an AI actor](/how-to/marketing/ugc-ad-with-ai-actor)
- [Make an Amazon listing or Sponsored Brands video ready for moderation](/how-to/marketing/amazon-listing-video)
- [Make a Shopify and TikTok Shop product video that follows the no-stills rule](/how-to/marketing/shopify-and-tiktok-shop-video)
- [Animate a photo, or make a pet memorial from one picture](/how-to/personal/animate-a-photo)
- [Check your video before you say it is done](/how-to/check-your-video)