---
name: video-reframe
description: Smart reframe a video to another aspect ratio - 16:9 to 9:16 for Reels / TikTok / Shorts, or 4:5, 1:1 - with a crop window that follows the action instead of a fixed centre crop. Removes black bars, detects hard cuts, scores motion and detail per shot, smooths the path (smooth pans or one static framing per shot), previews the crop window on source frames, and accepts manual keyframes when the subject is wrong. Use when the user wants a landscape Kenerate clip or ad turned vertical, auto-reframed, re-cropped for social, or "make this fit TikTok".
compatibility: Python 3.9+ with Pillow and ffmpeg.
metadata:
  author: kenerate
  version: "1.1"
  kenerate-tools: "generate_video expand_image upload_media wait_for_generation"
---

# Video reframe (subject-following crop)

`scripts/reframe.py` analyses the clip locally and renders one ffmpeg crop with a moving window. Free. Rules:
[references/KENERATE.md](references/KENERATE.md) (models and voices: [references/MODELS.md](references/MODELS.md), or the free `pick_model` / `pick_voice` tools).

## When to use / not to use
- Use: "make this vertical", "reframe for Reels", "crop to 4:5 but keep the person in frame".
- Not when the subject must stay fully visible in a wide composition (two people at opposite edges): offer
  `ad-resizer` with a blurred fill, or regenerate the shot vertically (`generate_video(aspect_ratio="9:16")`, model
  from `pick_model`) - ask before spending.

## 1. Preview the path (free)
```
python <skill-dir>/scripts/reframe.py --input "<clip url>" --aspect 9:16 --preview-only
```
Show `*_path_preview.jpg`: six source frames with the crop window drawn in yellow. If the window misses the subject,
fix it: `--style static` (one framing per shot, no pans), `--smooth 0.9` (calmer), or manual keyframes taken from
`*_path.json` (`--keyframes "0:0.3,2.5:0.7"`, positions 0 = left / top .. 1 = right / bottom). `--mode center` and
`--mode fixed --focus 0.35` are simple fallbacks.

## 2. Render
Same command without `--preview-only` (`--res 1080` default, `--out` to name it). Audio is copied as is.

## Progress and output
Steps: fetch + probe (black bars) → analyse (percent through the clip) → preview → render (percent) → done.
`RESULT_JSON` has `output`, `preview`, `path_json`, the detected `cuts` and the keyframe count.

## If something fails
Tracking follows motion and detail, so a static speaker next to a busy background can lose: use keyframes. Fast
handheld footage: raise `--smooth`. Very short clips (< 1 s) just centre.

## Limits
One window per frame (no split-screen). No face detection model: the heuristic is motion + edges + a centre bias.
