---
title: Turn listing photos into a vertical real-estate reel
description: A vertical real-estate reel, or listing video, from your listing photos: slow pans, price and address on screen, music, and an upscaled 4K copy.
---
You get a vertical real-estate reel, also called a listing video or property tour reel, from the photos of a listing. Each room gets a slow pan or push, the price and the address sit on screen, and music plays under it. You get a 1080p MP4 for Reels and TikTok, and an upscaled 4K copy when the listing site or the seller asks for one.

Use invideo for this when you list homes every week: your agent builds the first reel, then makes each new listing on a copy of it, so you only swap the photos, the price and the address.

This is ordinary marketing work for a listing you represent. The agent makes the video. You post it and you publish the listing.

## Quickest path

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

```text
Make a 30 second vertical reel from the listing photos in ./42-elm.
Front of the house first, then kitchen, living room, bedrooms, yard.
Slow pans, the text "€685,000" and "42 Elm Street, Dublin", calm
music. Export 1080p, then make a 4K copy and tell me its price first.
```

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

## What you need

The agent puts on screen only what you give it, word for word.

- **The listing photos.** JPG or PNG, wide shots, in the order of the tour. Use enough photos to show each room once.
- **The text to show.** The price, the address, beds and baths, and your name or brokerage, exactly as they should read.
- **Your logo or headshot, if you use one.** A PNG.
- **The music mood.** Calm, upbeat or luxury.
- **The length.** 15, 30 or 60 seconds.
- **Whether you need an upscaled 4K copy.** Many listing sites take 1080p. Ask the site.

## Steps

The agent builds one reel, then copies it for each new listing.

### Build the first reel

The agent builds one reel on a branch and checks it before export.

<Steps>
<Step title="Make a vertical timeline and bring the photos in">
The agent makes a project with `new_project`, a 1080 by 1920 timeline with `new_timeline`, and a branch with `timeline_history`. It uploads the photos with `start_upload` and `add_media`. Expected result: a sequence URL per photo.
</Step>
<Step title="Place the photos and fill the frame">
The agent places each photo with `insert_media` in tour order, and fills the vertical frame with `fill_frame`. A wide photo then shows its middle. Expected result: no black bars, one photo after another.
</Step>
<Step title="Add the pans">
On each photo, the agent adds the `dynamic_zoom` effect with `add_effect`. Then, in a second `edit_timeline` call with the effect's id from `get_timeline`, it sets the start and end points with `set_effect_parameter` so the frame slides across the room. Expected result: each room moves slowly, from one side to the other.
</Step>
<Step title="Add the price, the address and the details">
The agent adds the price and the address with `add_text` on the first photo, and beds and baths on a later one. It types the words you gave, exactly. It styles them with `set_text_style`. Expected result: readable text in the middle of the frame, clear of the app buttons.
</Step>
<Step title="Make the music">
The agent runs `find_models` with the mood in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_music_v2_5_instrumental`. It calls `generate` with `dry_run: true`, a `prompt` and a `duration` that matches the reel, and tells you the price. Then it calls `generate` with `max_credits` set to that price and an `idempotency_key`. Expected result: a sequence URL, which the agent reads with `read` and places on `A2`.
</Step>
<Step title="Cut to the beat">
The agent reads the beats with `media` `audio.beats`, moves the cuts to them with `trim_clip`, and adds soft cuts with `add_transition`, such as `fade` or `slide`. Expected result: the photos change on the beat.
</Step>
<Step title="Check and export 1080p">
The agent runs `capture` at the price, the address and each room, and `check_timeline`. It checks the price and the address letter by letter against what you gave. Then it runs `export` with `format` video and `quality` 1080. Expected result: an export card with status `completed`.
</Step>
</Steps>

### Upscale to 4K and reuse the reel

The agent upscales the export, then reuses the reel for the next home.

<Steps>
<Step title="Upscale the export to 4K">
`export` makes 1080p. For 4K, the agent runs `media` `video.upscale` on the export card's URL, with `byteplus_vod_upscale` as the `model` and `target_resolution` 4k in `inputs`. The card is a sequence, so no re-upload is needed. It runs `dry_run` first and tells you the price. Then it runs the same call with `max_credits` set to that price and an `idempotency_key`. Upscales charge by each second of the source. Expected result: a 4K video as a new sequence.
</Step>
<Step title="Copy it for the next listing">
For the next listing, the agent copies the timeline with `duplicate_timeline` and names it after the address. It swaps each photo with `place_media` in `mode` replace, and changes the words with `set_text`. Expected result: a new reel with the same style, ready to check.
</Step>
<Step title="Check and export the new listing">
The agent runs `capture` on the copy at the price, the address and each room, and `check_timeline`. Then it runs `export` with the copy's `timeline_id`. Expected result: an export card with status `completed`.
</Step>
</Steps>

The same job from a terminal:

```bash
invideo project new --title "Listings"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "42 Elm" --width 1080 --height 1920
invideo asset upload <edit-url> ./42-elm/*.jpg
invideo gen models <project-url> --query "calm instrumental music bed"
invideo gen model <project-url> --model elevenlabs_music_v2_5_instrumental
invideo gen run <page-url> --model elevenlabs_music_v2_5_instrumental \
  --dry-run -i prompt="calm piano, warm, slow" -i duration=30
invideo gen run <page-url> --model elevenlabs_music_v2_5_instrumental \
  --max-credits <price> --idempotency-key 42-elm-music \
  -i prompt="calm piano, warm, slow" -i duration=30
invideo edit show <edit-url> --json
invideo edit change <edit-url> --timeline T1 --token <state_token> \
  --operations @reel-ops.json
invideo edit capture <edit-url> --at 1,5,10,20,29 --out ./frames
invideo edit export <edit-url> --format video --quality 1080 \
  --file-name 42-elm-street --json
invideo status <card-url> --wait
invideo notebook show <card-url> --out ./out
invideo media video.upscale <card-url> --model byteplus_vod_upscale \
  --inputs '{"target_resolution": "4k"}' --dry-run
invideo media video.upscale <card-url> --model byteplus_vod_upscale \
  --inputs '{"target_resolution": "4k"}' \
  --max-credits <price> --idempotency-key 42-elm-4k
```

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`. `<page-url>` is a notebook page from `invideo notebook show <project-url>`. `<state_token>` comes from `invideo edit show`. `<price>` is each dry run's `estimated_credits`. `<card-url>` is `.sequences[0]` of what the export returns. `invideo status` does not download. `invideo notebook show` saves the file as `export.mp4`, whatever `--file-name` says, so the agent renames it to `42-elm-street.mp4`. The ops file `reel-ops.json` is a bare list: the `operations` list of the MCP call below.

The key MCP call places a photo, fills the frame, adds the pan and the price. `<edit-url>` is the timeline URL from `new_timeline`, `<state_token>` comes from `get_timeline`, and `<sequence-url>` is the sequence URL `add_media` returns for the front photo. The new clip's id `c1` can be used later in the same call.

```json
{
  "url": "<edit-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "insert_media", "asset": "<sequence-url>",
      "track": "V1", "at_f": 0, "ripple": true },
    { "op": "fill_frame", "clip": "c1" },
    { "op": "add_effect", "clip": "c1", "effect": "dynamic_zoom" },
    { "op": "add_text", "track": "V2", "start_f": 15, "end_f": 105,
      "text": "€685,000\n42 Elm Street, Dublin",
      "style": { "font_size": 72, "align": "center", "color": "#ffffff",
                 "shadow": true } }
  ]
}
```

The 4K upscale is a `media` call on the export card, with `<card-url>` from the export result's `.sequences[0]`:

```json
{
  "url": "<card-url>",
  "op": "video.upscale",
  "model": "byteplus_vod_upscale",
  "inputs": { "target_resolution": "4k" },
  "dry_run": true
}
```

## 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 pans, the text, the beats, the copies per listing, the checks and the 1080p export.
- **Costs credits:** the generated music or paid stock music, and the 4K upscale. The upscale charges by each second of the video, so a shorter reel costs less.

The first reel takes under an hour. Each copy for a new listing takes a few minutes, plus the export. See [Credits and what they cost](/account/credits) for prices.

## If something goes wrong

Most problems are a room cut off by the vertical crop, or a typo in the price.

| 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. |
| You want stock music instead | Run `search_library` in `stock_music`, and add the pick with `add_media`. |
| You want a hand-made pan | Add a lane with `add_keyframe_lane` on `position_x`, and fill it with `add_keyframes`. |
| The best part of a wide room is cut off | Change the pan's start and end points, or move the photo with `set_position`. |
| `fill_frame` refused | The clip's zoom is animated. Remove the lane, fill the frame, then add the lane again. |
| The price or address is wrong | The agent types what you gave. Send the right text and it fixes it with `set_text`. |
| Text sits under the app's buttons | Move it with `set_position` toward the middle, and `capture` again. |
| The 4K copy looks soft | Upscaling cannot add real detail to a small photo. Start from full-size photos. |
| The download folder is empty | `invideo status` does not download. Run `invideo notebook show <card-url> --out ./out`. |
| `timeout` on the upscale | Do not start it again. `read` the sequence URL or call `status`. |
| Avoid: the agent writes its own description of the home | Instead: it shows only the words you gave, so the listing stays accurate. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Copy my 42 Elm reel for 7 Birch Lane. Photos in ./7-birch, price
€540,000, 3 beds 2 baths. Same music and style.
```

```text
Make a 15 second "Sold" reel from the front photo of 42 Elm with
a bold "SOLD" title and my headshot ./me.png at the end.
```

```text
Make an open house reel for Saturday 1 to 4pm from ./12-oak, with the
date and time on the last photo, and a 16:9 copy for YouTube.
```

## When to use something else

For a walk-through video, film it on a phone gimbal or hire a videographer, then bring the clips in. Photos with pans are not a real walk-through.

invideo does not make virtual staging or floor plans. Use a staging or floor plan tool, then bring the images in with `add_media`. Check your local rules on showing staged rooms.

## Related

- [Make monthly videos for a dentist, gym, restaurant or home service](/how-to/marketing/local-business-monthly-videos)
- [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master)
- [Make a stock-footage commercial for your business, in short and long cuts](/how-to/marketing/stock-footage-commercial)
- [Make a photo slideshow for any occasion: anniversary, graduation, retirement, baby's first year, family recap](/how-to/personal/occasion-slideshow)
- [Check your video before you say it is done](/how-to/check-your-video)