Crop a 21:9 video to 9:16, 4:5, 1:1 and 16:9: fraction table

From a 21:9 source, a full-height crop is 0.2411 wide for 9:16, 0.3429 for 4:5, 0.4286 for 1:1, 0.7619 for 16:9. $0.02 per crop; the check is free.

5 min readSume
All posts

For a source that is exactly 21:9, a full-height centered crop to 9:16 uses width 0.2411 and x 0.3795. The same source gives width 0.3429 for 4:5, 0.4286 for 1:1 and 0.7619 for 16:9. Each crop is one Sume video filter job at $0.02, and the unbilled /v1/video-filter/check endpoint validates the program first.

The arithmetic

Crop fractions are relative to the source frame. With height 1, the width fraction is the target ratio divided by the source ratio. The 21:9 source ratio is 21 / 9 = 2.3333. The centered offset is x = (1 - width) / 2.

Full-height centered crops of a 21:9 source (read 2026-10-08)
TargetWidth fractionCalculationCentered x
9:160.24110.5625 / 2.33330.3795
4:50.34290.8 / 2.33330.3286
1:10.42861 / 2.33330.2857
16:90.76191.7778 / 2.33330.1190

Limits from the docs

The crop op takes x and y in 0 to 1, and width and height in 0.05 to 1. The sums x + width and y + height must not go above 1. The compiler rounds to even values for yuv420p. An op carries only the keys op, x, y, width, height; an extra key is refused with unsupported_filter_op_field, and a rectangle outside the frame gives video_filter_crop_out_of_bounds. The source can be 300 seconds at most.

Price is $0.02 per encode job and four crops cost $0.08. The check call creates no job and reserves nothing. The live price is in GET /v1/catalog.

Why not crop and then scale in one step

A crop gives you the right shape, not the right size. A 2520 x 1080 source cropped to 9:16 leaves about 608 x 1080 pixels, which is below the 1080 x 1920 default of a Timeline render. Placing it in a Timeline slot with a fit mode scales it up, so the crop job is the shape step and the render is the size step. Keep the pieces separate: the video filter is $0.02 and does one job, and the Timeline render bills by output minute.

If the output is a social ad, check the platform floor too. TikTok lists 540 x 960 as the minimum for non-Spark 9:16 ads, and a 608 x 1080 crop clears that without scaling, though it is soft at full screen.

A second pass for a different crop

Crops do not chain for free. Each one reads the source again, so four crops of the same wide file are four jobs and $0.08. If you need a vertical cut and a square cut, send both from the original, not the square from the vertical. The vertical has already thrown away 76% of the width and cannot give it back.

Look at the framing before you commit

A centered 9:16 crop of a 21:9 frame keeps 24.11% of the width. That is a narrow window. Anything that is not in the middle is gone, so a two-person shot loses one person. Move x to follow the subject, and keep x + width at 1 or less. For a subject at the left third, x of 0.15 with a width of 0.2411 ends at 0.3911, which is valid.

Run the free check, then run the job. The code builds all four request bodies from the source ratio, so you can change the source ratio and see new numbers.

import json

SRC = 21 / 9
TARGETS = {"9:16": 9 / 16, "4:5": 4 / 5, "1:1": 1.0, "16:9": 16 / 9}

for name, ratio in TARGETS.items():
    width = round(ratio / SRC, 4)
    x = round((1 - width) / 2, 4)
    op = {"op": "crop", "x": x, "y": 0, "width": width, "height": 1}
    assert width >= 0.05 and x + width <= 1.0001
    body = {"video_url": "https://media.sume.com/artifacts/artf_demo/wide.mp4",
            "ops": [op]}
    print(name, json.dumps(body["ops"][0]))

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume