MCP tool for video reframing and OTIO timeline reframe annotation generation. Annotates a reframe directive (target resolution / fit mode / anchor) to timeline-level metadata for clipwright-render to apply.
Project description
clipwright-reframe
MCP tool that annotates a reframe directive (target resolution / fit mode / anchor) to an OTIO timeline for aspect-ratio conversion and delivery-format preparation.
Overview
clipwright-reframe writes a reframe directive to
metadata["clipwright"]["reframe"] in an OTIO timeline file. The directive is
materialised by clipwright-render as an FFmpeg filter chain in a single render
pass (design M3: separation of annotation and realisation).
Fit modes:
| Mode | Behaviour |
|---|---|
crop |
Scale to cover the target rectangle, then crop to size. Content at the edges may be lost; controlled by anchor. |
pad |
Scale to fit inside the target rectangle (letterbox / pillarbox), then pad the remaining area with pad_color (default "black"). |
blur_pad |
Scale the foreground to fit; overlay it over a blurred, cover-scaled version of the same frame as background. Popular for 16:9 → 9:16 vertical conversions (Shorts / Reels). |
Prerequisites
- Python 3.11 or later
clipwrightcore package (shared types, envelope, OTIO utils)- No FFmpeg dependency at annotation time (FFmpeg is only required by
clipwright-renderat realisation time)
MCP Tool: clipwright_reframe
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
media |
string |
required | Input video file path (must contain a video stream) |
output |
string |
required | Output OTIO timeline path (.otio) |
options.target_w |
integer |
required | Target output width in pixels (even integer, 2–7680) |
options.target_h |
integer |
required | Target output height in pixels (even integer, 2–7680) |
options.mode |
string |
"pad" |
Fit mode: crop, pad, or blur_pad |
options.anchor |
string |
"center" |
Crop/pad alignment anchor. One of: top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right |
options.pad_color |
string |
"black" |
Background fill color for pad mode. Accepts CSS color names or #RRGGBB hex strings. |
timeline |
string | null |
null |
Existing OTIO timeline path to append the directive to (accumulate pattern). When omitted a new timeline is created. |
Return value
{
"ok": true,
"summary": "Reframe directive written for video.mp4. target=1080x1920 mode=blur_pad anchor=center.",
"data": {
"target_w": 1080,
"target_h": 1920,
"mode": "blur_pad",
"anchor": "center",
"pad_color": "black"
},
"artifacts": [{"role": "timeline", "path": "out.otio", "format": "otio"}],
"warnings": []
}
Error codes
| Code | Cause |
|---|---|
INVALID_INPUT |
target_w / target_h is odd, out of range, or mode / anchor is unrecognised |
FILE_NOT_FOUND |
media or timeline path does not exist |
INVALID_INPUT |
output and timeline point to the same file (use distinct paths) |
Two-Phase Workflow
clipwright_reframe(media, output, options) # Phase 1 — annotate
│
▼ OTIO timeline with metadata["clipwright"]["reframe"]
clipwright_render(timeline, output_media) # Phase 2 — realise
│
▼ output video in target resolution/aspect ratio
clipwright-reframe can be combined with other directive tools in any order before
the final render:
clipwright_detect_color → clipwright_reduce_noise → clipwright_reframe → clipwright_render
MCP Client Registration
Register clipwright-reframe as a standalone MCP server in your client configuration
(.mcp.json / claude_desktop_config.json). No FFmpeg environment variables are
required for the annotation step.
{
"mcpServers": {
"clipwright-reframe": {
"command": "clipwright-reframe"
}
}
}
clipwright-render (which materialises the directive) still requires
CLIPWRIGHT_FFMPEG.
Usage Examples
16:9 landscape → 9:16 vertical (blur-pad background)
# Via MCP call_tool
result = await session.call_tool("clipwright_reframe", {
"media": "source.mp4",
"output": "reframed.otio",
"options": {
"target_w": 1080,
"target_h": 1920,
"mode": "blur_pad",
"anchor": "center"
}
})
# Then render
render_result = await session.call_tool("clipwright_render", {
"timeline": "reframed.otio",
"output": "vertical.mp4"
})
Crop to 1:1 square (top-aligned)
result = await session.call_tool("clipwright_reframe", {
"media": "source.mp4",
"output": "square.otio",
"options": {
"target_w": 1080,
"target_h": 1080,
"mode": "crop",
"anchor": "top"
}
})
Pad to 4:3 with white bars (accumulate on existing timeline)
result = await session.call_tool("clipwright_reframe", {
"media": "source.mp4",
"timeline": "edited.otio", # existing timeline from other tools
"output": "edited_reframed.otio",
"options": {
"target_w": 1440,
"target_h": 1080,
"mode": "pad",
"anchor": "center",
"pad_color": "white"
}
})
Installation
Within a uv workspace:
uv run --package clipwright-reframe clipwright-reframe
Or install from PyPI:
pip install clipwright-reframe
clipwright-reframe
License
MIT — See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clipwright_reframe-0.1.0.tar.gz.
File metadata
- Download URL: clipwright_reframe-0.1.0.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0971ef827f2a9183838fc8fd1ab74e66a61737cb4baa634734b56a13ef2aede1
|
|
| MD5 |
0acc282a97474224a55515a26acb424f
|
|
| BLAKE2b-256 |
66f82b464368eb7c46d792a2b96865991e08399a9e8dcd7acf863b0bb2135dd4
|
Provenance
The following attestation bundles were made for clipwright_reframe-0.1.0.tar.gz:
Publisher:
publish.yml on satoh-y-0323/clipwright
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clipwright_reframe-0.1.0.tar.gz -
Subject digest:
0971ef827f2a9183838fc8fd1ab74e66a61737cb4baa634734b56a13ef2aede1 - Sigstore transparency entry: 1888565594
- Sigstore integration time:
-
Permalink:
satoh-y-0323/clipwright@e5d0cdd41ef7e6eb456feb9492c81eb1e7ccd0e8 -
Branch / Tag:
refs/tags/v0.12.0 - Owner: https://github.com/satoh-y-0323
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e5d0cdd41ef7e6eb456feb9492c81eb1e7ccd0e8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file clipwright_reframe-0.1.0-py3-none-any.whl.
File metadata
- Download URL: clipwright_reframe-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
439fc21e9d20ced28a2591dfb7e27d8b75a3bf873e7459f81327768f904ce0ea
|
|
| MD5 |
6ba72b6dd9b182cc9ffa3c785509b02a
|
|
| BLAKE2b-256 |
9f4f8604d070ff9ecf521e4097422b98390cc4f78d3513cf1d8f380c4b7329ca
|
Provenance
The following attestation bundles were made for clipwright_reframe-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on satoh-y-0323/clipwright
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clipwright_reframe-0.1.0-py3-none-any.whl -
Subject digest:
439fc21e9d20ced28a2591dfb7e27d8b75a3bf873e7459f81327768f904ce0ea - Sigstore transparency entry: 1888565633
- Sigstore integration time:
-
Permalink:
satoh-y-0323/clipwright@e5d0cdd41ef7e6eb456feb9492c81eb1e7ccd0e8 -
Branch / Tag:
refs/tags/v0.12.0 - Owner: https://github.com/satoh-y-0323
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e5d0cdd41ef7e6eb456feb9492c81eb1e7ccd0e8 -
Trigger Event:
push
-
Statement type: