---
title: Make an App Store preview video at Apple's sizes
description: An App Store preview, or app preview video, cut from your screen recording at Apple's device sizes, with text overlays and a pre-flight check.
---
You get an App Store preview, also called an app preview video or App Store trailer, cut from your own screen recordings. It is sized for each iPhone and iPad display Apple asks for, uses text to explain each step because previews start muted, and passes a pre-flight check before you upload it.

Use invideo for this when you need the same preview at several device sizes: your agent makes one timeline per size from one cut, checks each against Apple's spec, and you change a line of text in all of them after.

This is ordinary marketing work for your own app. The agent makes the files. You upload them in App Store Connect, and Apple reviews them. The agent never uploads or submits them.

## Quickest path

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

```text
Make an App Store preview from my screen recording ./capture.mov.
Cut it to 25 seconds: onboarding, the main feature, the result. Add a
short text line for each part, no prices, music I can use. Make the
iPhone 886x1920 and the iPad 1200x1600 sizes, and check each file
against Apple's spec before you say it is done.
```

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

## What you need

Apple's rules decide most of this list. Read them on Apple's <a href="https://developer.apple.com/help/app-store-connect/reference/app-preview-specifications" target="_blank">App preview specifications</a> page and the <a href="https://developer.apple.com/app-store/app-previews/" target="_blank">App previews</a> guidelines. They change, so the agent checks them before each job.

- **Screen recordings from the device.** Record on the iPhone or iPad, or in the Simulator, at the device's own resolution. Footage must come from the app itself.
- **The device sizes you ship.** Apple lists one pixel size per display family, portrait and landscape.
- **The text for each step.** Short lines that say what the person sees. No prices.
- **A disclosure, if it applies.** If a feature needs a purchase, a subscription or a sign-in, say so on screen or on the end frame.
- **Music you have the rights to.** Stock music from invideo, or your own licensed track.

These are Apple's sizes for the common display families:

| Display | Portrait | Landscape |
| --- | --- | --- |
| iPhone with Dynamic Island or Face ID | 886 x 1920 | 1920 x 886 |
| iPhone with Home Button, large | 1080 x 1920 | 1920 x 1080 |
| iPad, 13 and 11 inch | 1200 x 1600 | 1600 x 1200 |

Apple asks for a preview between 15 and 30 seconds long, at 30 frames a second or less, as H.264 in MP4, M4V or MOV, with stereo AAC sound.

## Steps

The agent cuts once on the main size, then copies the cut for each other size.

<Steps>
<Step title="Make a timeline at the first device size">
The agent makes a timeline with `new_timeline` and sets its size and rate with `set_timeline_settings`, for example 886 by 1920 at 30 fps. It creates a branch with `timeline_history`. Expected result: an empty timeline at Apple's size.
</Step>
<Step title="Bring in the screen recording">
The agent uploads the recording with `start_upload` and `add_media`. It runs `media` `metadata` for its size and frame rate, and `video.frames` to see the screens. Expected result: a sequence URL, and a note of where each part of the app appears.
</Step>
<Step title="Cut the preview">
The agent places the parts you want with `place_media`, in story order, and trims them with `trim_clip`. It keeps the app's screen at its own size with `fill_frame`, and does not zoom far into the UI. Expected result: a cut between 15 and 30 seconds, with only app footage on screen.
</Step>
<Step title="Add text, music and the disclosure">
The agent adds one short line per step with `add_text`, large enough to read on a phone. It adds stock music with `search_library` in `stock_music` and `add_media`. It adds a disclosure line on the end frame when a feature needs a purchase or a sign-in. Expected result: text that explains the preview with the sound off.
</Step>
<Step title="Make the other device sizes">
The agent copies the timeline with `duplicate_timeline`, one copy per size, and sets each copy's size with `set_timeline_settings`. It checks each clip's framing with `fill_frame` or `fit_frame`, and moves text with `set_position`. Expected result: one timeline per size, each with the same cut.
</Step>
<Step title="Run the pre-flight check">
The agent runs `check_timeline` and `capture` on each timeline at every text line and at the end frame. It looks for text cut at the edge, any price, any date, and anything outside the app. Expected result: frames with no problems.
</Step>
<Step title="Export and check the files">
The agent runs `export` with `format` video, `quality` 1080, `fps` 30 and `audio_format` aac, then runs `media` `metadata` on each export card's URL. It checks the width, the height, the length and the frame rate against Apple's spec. The card is a sequence, so no re-upload is needed. Expected result: one export card per size, with its numbers read back.
</Step>
</Steps>

The same job from a terminal:

```bash
invideo project new --title "App Store preview"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo edit new <project-url> --name "iPhone 886x1920" \
  --width 886 --height 1920 --fps 30
invideo asset upload <edit-url> ./capture.mov
invideo media metadata <sequence-url>
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name preview-v1 --token <state_token>
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 --token <state_token> \
  --operations @cut.json
invideo edit check <branch-url>
invideo edit capture <branch-url> --at 1,6,12,18,24 --out ./frames
invideo edit export <branch-url> --format video --quality 1080 --fps 30 \
  --audio-format aac --json
invideo status <card-url> --wait
invideo media metadata <card-url>
invideo notebook show <card-url> --out ./iphone
mv ./iphone/export.mp4 ./iphone/preview_iphone.mp4
```

Where the values come from:

- `<project-url>` comes from `invideo project new`. `<edit-url>` comes 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 recording.
- `<state_token>` comes from `invideo edit show <edit-url>`, and on the branch from `invideo edit show <branch-url>`; the main token is stale there. `<branch-url>` is the `.branch_url` that `invideo branch new` returns.
- `<card-url>` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./iphone/export.mp4`.
- The file `./cut.json` holds a bare list of operations, the same list the MCP path sends in `operations`.
- In the MCP call below, `<edit-url>` is the timeline's URL from `new_timeline`, and `<state_token>` comes from `get_timeline`.

The key MCP call makes the iPad copy from the iPhone cut and sets its size.

```json
{
  "url": "<edit-url>",
  "timeline_id": "T1",
  "expected_state_token": "<state_token>",
  "operations": [
    { "op": "duplicate_timeline", "timeline": "T1",
      "name": "iPad 1200x1600" }
  ]
}
```

In the next call, on the new timeline's id from the result, the agent sends `{ "op": "set_timeline_settings", "timeline": "T2", "width": 1200, "height": 1600, "fps": 30 }`.

## 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:** the upload, the cut, the copies per size, the text, the checks and every export.
- **Costs credits:** stock music, and a voiceover if you add one.

A preview at two or three sizes takes under an hour, most of it on choosing the parts of the recording. See [Credits and what they cost](/account/credits) for prices.

## What invideo cannot check

invideo checks the file: its size, length, frame rate and what is in the frames. It cannot tell you whether Apple will accept the preview. Apple's App Review decides that, and it reads the content as well as the file. If Apple rejects the preview, App Store Connect says why, and the agent fixes that on the timeline.

## If something goes wrong

Most rejections come from what is in the frames, not from the file.

| Symptom | Fix |
| --- | --- |
| Apple rejects hands, a phone or a person in the shot | Use only footage captured from the app. Remove the clip with `delete_clip`. |
| Apple rejects a price on screen | Remove the text with `delete_clip`, or change it with `set_text`. Prices vary by region. |
| The file's width or height does not match the spec | Read it with `media` `metadata`. Fix the timeline size with `set_timeline_settings` and export again. |
| A portrait file is smaller than Apple's size | `quality` sets the file's height, and 1080 is its largest value. Scale the file to the exact size with `media` `video.upscale` on the export card, then check it with `metadata`. Or scale it outside invideo with ffmpeg or HandBrake. |
| The file is too long or too short | Trim with `trim_clip`, or export a range with `start` and `end`. |
| Text is hard to read on a phone | Make it larger with `set_text_style`, and `capture` again. |
| `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. |
| CLI exit 3 on the branch | The token is from main. Run `invideo edit show <branch-url>` and use its `state_token`. |
| The saved file is called `./iphone/export.mp4` | `notebook show` always saves `./iphone/export.mp4`. Rename it per size. |
| CLI exit 2 | The request cannot be done as asked. Read the error and the help for that command. |
| Avoid: zooming deep into the UI | Instead: show the screen at its own size, and explain with text. |

## Prompts to try

Each prompt is a real variation of the job.

```text
Make a landscape App Store preview for my iPad game from ./play.mov.
Show more gameplay than menus, 1600x1200, epic music, no prices.
```

```text
My preview was rejected for showing a date. Find the date in the text,
remove it, and export the three sizes again.
```

```text
Make my iPhone preview in German and Japanese. Same cut, translated
text lines, one branch per language.
```

## When to use something else

invideo exports MP4, and `quality` sets its height. Apple's portrait sizes are taller than the largest `quality` value, so the portrait files always need a scale step after export: `media` `video.upscale`, or ffmpeg or HandBrake for an exact pixel size. For ProRes 422, finish the file in a desktop editor such as Final Cut Pro.

invideo does not record your screen. Use the iPhone's screen recording, Xcode's Simulator recording, or QuickTime Player with the device plugged in.

## Related

- [Make a launch video from your product URL and screenshots](/how-to/marketing/launch-video)
- [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master)
- [Check your video before you say it is done](/how-to/check-your-video)
- [Licensing and commercial use](/account/commercial-use)
- [MCP tools](/reference/mcp-tools)