# Auto Reframe: Horizontal to Vertical Video (Face Tracking) (`jumblemog/auto-reframe`) Actor

Turn horizontal videos into vertical 9:16 videos for YouTube Shorts, TikTok and Reels. Face tracking keeps the speaker in frame with smooth camera moves and clean cuts. Also 4:5, 1:1 and vertical to 16:9, or fit the whole picture over a blurred background.

- **URL**: https://apify.com/jumblemog/auto-reframe.md
- **Developed by:** [Jumble Mog](https://apify.com/jumblemog) (community)
- **Categories:** Videos, AI, For creators
- **Security:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Auto Reframe: Horizontal to Vertical Video (Face Tracking)

**Turn horizontal videos into vertical 9:16 videos for YouTube Shorts, TikTok and Instagram Reels**, with a virtual camera that follows the speaker's face. Give it an interview, podcast, webinar, vlog or any landscape video, and get back an MP4 at 1080 × 1920 where the person stays in the picture: the camera holds still while they talk, pans smoothly when they move, and re-frames on the exact frame of every cut. It also makes 4:5 and square videos, and turns vertical phone videos into horizontal 16:9 ones. No editing app, no watermark, pay per minute.

![Three moments of a 16:9 video with the 9:16 crop drawn in yellow, and the vertical video that came out](https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/auto-reframe-demo.jpg?signature=1cIBlxjljZH1y3sOJWrab)

Watch the [16:9 demo clip](https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/auto-reframe-demo-original.mp4?signature=45yGwMNeFVZZDd8rI4od) and [the vertical video made from it](https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/auto-reframe-demo-vertical.mp4?signature=13jL2BtfHdpkNEvJcsb8S). *The demo clip is made from 1940s color photos by the Farm Security Administration and Office of War Information (Library of Congress, no known restrictions), moved across a 16:9 frame.*

### What it does

- **Face tracking**: finds faces about eight times a second and follows the main one, the face that is biggest and on screen longest. When two or more people fit in the frame together, it keeps the whole group in.
- **Moves like a camera operator**: holds still while the speaker moves a little, re-centers with a smooth, eased pan when they move away, and never jitters. Pick smooth, fast, or static (one fixed position per shot).
- **Knows where the cuts are**: every cut between shots is detected, and the crop jumps to the new position on the exact frame of the cut, so a new shot never starts with a pan from the old one.
- **Any shape**: 9:16 for Shorts, TikTok and Reels, 4:5 for Instagram and Facebook feeds, 1:1 square, and 16:9 to turn vertical videos into horizontal ones.
- **Fit mode**: the whole picture over a blurred copy of itself, for slides, screen recordings and wide shots where nothing should be cut off.
- **Ready to post**: MP4 (H.264 and AAC) at 1080p or 720p, with the sound kept in sync. Phone videos recorded sideways are turned upright.
- **Crop data for developers**: optionally get the shots and the crop position of every frame as JSON, to use in your own editor or pipeline.
- **Takes files from anywhere**: direct links, Google Drive and Dropbox share links, or uploads. Videos up to 2 GB and 2 hours.
- **Pay per minute of video**. Files that fail cost nothing.

### Who it's for

- **Podcasters and YouTubers** turning long-form episodes into Shorts, Reels and TikToks.
- **Social media managers and agencies** making vertical clips from interviews, webinars and event videos.
- **Automation builders** with clip pipelines in n8n, Make or Zapier: cut the clips, reframe them here, add captions, publish.
- **App developers and AI agents** that need reframing as one API step in a video workflow.
- **Anyone with vertical phone videos** who needs a horizontal version for YouTube, a website or a presentation.

### How to use it

1. Paste links to your videos, or upload them.
2. Pick the shape (9:16 by default) and the layout.
3. Click **Start**. Each video appears in the **Output** tab with a download link.

You can also run it through the [Apify API](https://docs.apify.com/api/v2), on a schedule, or from Make, n8n, Zapier and other integrations.

### How-to examples

Each example below is a complete input, checked with a run of the Actor on a short test clip.

#### How to turn a horizontal video into a vertical 9:16 video for Shorts, TikTok and Reels

```json
{"videoUrls": ["https://example.com/podcast/episode-12-clip.mp4"], "aspectRatio": "9:16"}
```

Result: an MP4 at 1080 x 1920 in `videoUrl`, with the crop following the speaker's face. `shots` and `shotsWithFaces` say how many cuts it found and how many had a face to follow. A 5-second 1280 x 720 test clip took 1.9 seconds.

#### How to make a square video without cropping anything out

```json
{"videoUrls": ["https://example.com/webinar/slide-demo.mp4"], "aspectRatio": "1:1", "layout": "fit", "resolution": "720p"}
```

Result: a 720 x 720 MP4 with the whole picture over a blurred copy of itself. This suits screen recordings and slides, where a crop would cut off text.

#### How to turn a vertical phone video into a horizontal 16:9 video

```json
{"videoUrls": ["https://drive.google.com/file/d/YOUR_FILE_ID/view?usp=sharing"], "aspectRatio": "16:9", "layout": "fit"}
```

Result: a 1920 x 1080 MP4 for YouTube, a website or a presentation, with the phone video in the middle over a blurred background.

#### How to let an AI agent make vertical clips

Add this Actor to the [Apify MCP server](https://mcp.apify.com) with `https://mcp.apify.com/?tools=jumblemog/auto-reframe`. The agent sends the clip links in `videoUrls` and gives the user `videoUrl`. In a clip pipeline it goes after the step that cuts the clips and before the one that adds captions.

### FAQ

**Does it follow the speaker?** Yes, with `"layout": "track"` (the default). The crop holds still while the person talks, pans smoothly when they move, and re-frames on every cut. It doesn't know who is talking, so in a wide shot of two people it follows the most prominent face.

**Is there a watermark?** No.

**Can I give it a YouTube or TikTok link?** No. Those platforms' terms don't allow downloading, so use your own copy of the video, from a direct link, Google Drive, Dropbox or an upload.

**Does it add captions?** No. It keeps the sound as it is. Add captions in your editor or with another step.

**Does it work with Zapier, Make or n8n?** Yes. Call the Actor with its Apify app or an HTTP request, and pass `videoUrl` to the next step.

### Input

| Field | What it does |
| --- | --- |
| `videoUrls` | Links to video files, or Google Drive and Dropbox share links. |
| `files` | Videos uploaded from your computer or picked from an Apify key-value store. |
| `aspectRatio` | `9:16` (default), `4:5`, `1:1` or `16:9`. |
| `layout` | `track` (default): crop and follow faces. `center`: fixed crop in the middle. `fit`: the whole picture over a blurred background. |
| `cameraMotion` | `smooth` (default), `fast` or `static` (one position per shot). |
| `resolution` | `1080p` (default) or `720p`. |
| `saveCropData` | `true` also saves the shots and crop positions as JSON (default `false`). |
| `maxFiles` | Stop after this many videos (default 100). |

Example:

```json
{
  "videoUrls": [
    "https://example.com/podcast/episode-12-clip.mp4",
    "https://drive.google.com/file/d/YOUR_FILE_ID/view?usp=sharing"
  ],
  "aspectRatio": "9:16",
  "cameraMotion": "smooth"
}
```

### Output

Each video becomes one dataset item, and the reframed video is saved in the run's key-value store:

```json
{
  "url": "https://example.com/podcast/episode-12-clip.mp4",
  "status": "ok",
  "error": null,
  "videoUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/001-episode-12-clip-9x16.mp4?signature=...",
  "fileName": "001-episode-12-clip-9x16.mp4",
  "sourceFileUrl": "https://example.com/podcast/episode-12-clip.mp4",
  "durationSeconds": 74.5,
  "width": 1080,
  "height": 1920,
  "aspectRatio": "9:16",
  "layout": "track",
  "shots": 9,
  "shotsWithFaces": 9,
  "cropDataUrl": null,
  "minutesBilled": 2,
  "processingSeconds": 81.3
}
```

A video that couldn't be downloaded or read gets `status: "failed"` and an `error` that says why, and isn't billed. Download your videos within your plan's data retention period, or copy them to your own storage, because run storage expires.

### Pricing

You pay per **started minute of video**, at the price shown on this page. A 2½-minute video is 3 minutes; a 20-second clip is 1 minute. Files that fail are never charged. If you set a maximum cost per run, the Actor stops before a video that wouldn't fit.

### Speed

Processing takes a little longer than the video itself. Measured on Apify with a 2½-minute 1080p video: about 3 minutes at the default 8 GB of memory, and about 5 minutes at 4 GB. Each run also needs a few seconds to start and to download the video.

### Tips and limits

- **It follows faces.** Videos without people, such as products, animals or sports, get a centered crop; the fit layout often works better for those.
- **It doesn't know who is talking.** In a wide shot of two people sitting far apart, it follows the most prominent face. Multi-camera podcasts with close-ups of each speaker work best.
- On-screen text and graphics at the sides of the picture are cropped away. Use the fit layout for slides and screen recordings.
- The output is always 1080p (or 720p), so small videos are scaled up.
- Links to YouTube, TikTok, Instagram, Facebook and X aren't supported, because those platforms' terms don't allow downloading. Use your own copy of the video.
- Faces are only located to place the crop. Nobody is identified, and no face data is kept.

### For AI agents and developers

This Actor works with the [Apify MCP server](https://mcp.apify.com), so AI agents can call it as a tool: pass `videoUrls` and read `videoUrl` from each dataset item. Every item has the same documented fields, and `status` tells you whether a video succeeded. For a direct API call:

```bash
curl -X POST "https://api.apify.com/v2/acts/jumblemog~auto-reframe/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"videoUrls": ["https://example.com/clip.mp4"], "aspectRatio": "9:16"}'
```

The synchronous endpoint waits up to 5 minutes, which suits short clips. For long videos or batches, start a run with `/runs` and read the dataset when it finishes.

### Privacy

Videos are downloaded into the run, processed there and saved only to your own Apify storage. Nothing is sent to an outside service.

### Credits

- Face detection: [YuNet](https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet) from the OpenCV model zoo (MIT license).
- Video decoding, cropping and encoding: [FFmpeg](https://ffmpeg.org) with x264.

# Actor input Schema

## `videoUrls` (type: `array`):

Direct links to video files (MP4, MOV, MKV, WebM, AVI and more), or Google Drive and Dropbox share links. YouTube, TikTok, Instagram, Facebook and X links aren't supported because their terms don't allow downloading.

## `files` (type: `array`):

Upload videos from your computer, or pick videos you already stored in an Apify key-value store.

## `aspectRatio` (type: `string`):

9:16 for YouTube Shorts, TikTok and Reels. 4:5 for Instagram and Facebook feeds. 1:1 square. 16:9 turns vertical videos into horizontal ones.

## `layout` (type: `string`):

track: crop the video and follow the main face (or keep a group in frame). center: a fixed crop in the middle. fit: show the whole picture over a blurred background, with nothing cut off.

## `cameraMotion` (type: `string`):

How the crop follows faces. smooth holds still and pans gently, like a camera operator. fast follows quick movement closely. static picks one position per shot and never pans.

## `resolution` (type: `string`):

1080p gives 1080 x 1920 for 9:16. 720p gives 720 x 1280, with smaller files.

## `saveCropData` (type: `boolean`):

Also save the shots and the crop position of every frame where it moves, in source pixels, to use in your own editor or pipeline.

## `maxFiles` (type: `integer`):

Stop after this many videos, so the cost of a run stays predictable.

## Actor input object example

```json
{
  "videoUrls": [
    "https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/auto-reframe-demo-original.mp4?signature=45yGwMNeFVZZDd8rI4od"
  ],
  "aspectRatio": "9:16",
  "layout": "track",
  "cameraMotion": "smooth",
  "resolution": "1080p",
  "saveCropData": false,
  "maxFiles": 100
}
```

# Actor output Schema

## `results` (type: `string`):

One item per video: download link, size, shots and faces found.

## `files` (type: `string`):

The reframed videos (and crop data, if requested) saved in the run's key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videoUrls": [
        "https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/auto-reframe-demo-original.mp4?signature=45yGwMNeFVZZDd8rI4od"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jumblemog/auto-reframe").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "videoUrls": ["https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/auto-reframe-demo-original.mp4?signature=45yGwMNeFVZZDd8rI4od"] }

# Run the Actor and wait for it to finish
run = client.actor("jumblemog/auto-reframe").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/auto-reframe-demo-original.mp4?signature=45yGwMNeFVZZDd8rI4od"
  ]
}' |
apify call jumblemog/auto-reframe --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jumblemog/auto-reframe"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0p5yn5CjXBWDjIfbR/builds/DLR63Uj1DHNNT31DA/openapi.json
