Cloudinary ar_9:16,c_fill,g_auto vs Sume per-shot crop fractions

Cloudinary reframes video with ar_9:16,c_fill,g_auto. On Sume you pick crop x per shot (left, centre, right), with a runnable Python script.

6 min readSume
All posts

Cloudinary turns a 16:9 video into 9:16 with one transformation string, ar_9:16,c_fill,g_auto, and automatic gravity keeps the main subject in view as it moves. Sume has no automatic gravity, so the equivalent is a crop fraction you choose per shot: a left, centre or right 9:16 slice of the frame, applied with video filter.

Cloudinary's string comes from its video manipulation and delivery guide, Sume's rules from the video filter doc, both read on 2026-10-03.

What does the Cloudinary string do?

ar_9:16 sets the aspect ratio, c_fill crops and scales to fill the dimensions while keeping the ratio, and g_auto is smart auto-gravity that keeps main subjects in focus throughout the cropped video. Its guide shows the combination ar_9:16,c_fill,g_auto,w_[width].

It is a delivery-time transformation on a URL, so the crop is computed by Cloudinary and you cannot see or set the exact rectangle.

What are the exact crop fractions for 9:16 on Sume?

Video filter's crop op takes fractions of the source frame. A 16:9 frame is 16 wide by 9 high, and a 9:16 window of the full height is 9/16 of the height wide, which is (9/16) / (16/9) = 0.31640625 of the source width. The left edge x can be anywhere from 0 to 1 minus that width.

That gives three useful anchors: left at x 0, centre at x 0.341796875, and right at x 0.68359375. height is 1 and y is 0. The compiler even-rounds the rectangle, so expect a pixel of drift, not an error.

9:16 crop from 16:9 as video filter fractions (read 2026-10-03)
Anchorxywidthheight
Left000.316406251
Centre0.34179687500.316406251
Right0.6835937500.316406251

How do you script a crop per shot?

The script below builds one request body per shot from a list of speaker positions, ready to send to POST /v1/video-filter/check first (free) and then to POST /v1/video-filter. It only prints the bodies, so it runs without an API key.

import json

W = (9 / 16) / (16 / 9)  # 0.31640625 of source width
SHOTS = [
    ("artf_a/shot1.mp4", 0.10),  # speaker at left
    ("artf_a/shot2.mp4", 0.50),  # centred
    ("artf_a/shot3.mp4", 0.90),  # speaker at right
]

def body(path, centre):
    x = min(max(centre - W / 2, 0), 1 - W)
    return {
        "video_url": f"https://media.sume.com/artifacts/{path}",
        "ops": [{"op": "crop", "x": round(x, 6), "y": 0,
                 "width": round(W, 6), "height": 1}],
    }

for path, centre in SHOTS:
    print(json.dumps(body(path, centre)))

What can go wrong with a fixed crop?

A fixed crop drops everything outside its window, so a speaker who leans out of frame gets cut. Look at stills from the filtered clip with video frames at the start, middle and end of each shot, and shorten the shot if the speaker moves out of the window.

Off-bounds fractions are refused with video_filter_crop_out_of_bounds, so the script clamps x to the range 0 to 1 - width. A side under 0.05 is also refused. Because the check endpoint returns diagnostics instead of a 400, it is the fastest place to find these before you submit.

What is the full workflow, and what does it cost?

Cut each shot with video trim, run the free check on each crop, submit the filter jobs, then place the filtered MP4s in video[] of a Timeline 1.0 render. Trim and filter are each $0.02 per job and the check is free; confirm live prices in GET /v1/catalog. Timeline renders are $0.10 per output minute, rounded up.

Filter inputs must be 300 seconds or shorter, and all URLs must be this workspace's media.sume.com artifacts. Choosing centre per shot is manual, which is the price of a crop you can predict. If you want tracking, Cloudinary's g_auto does that and Sume does not.

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume