One Sume probe, eight platform limits: a Python preflight

Check one video inspect probe against Truth Social, Odysee, ArtStation, Linktree, Spotlight, Reels, TikTok API and Shorts limits in under 30 lines of Python.

4 min readSume
All posts

Probe the clip once and compare the numbers with a table of rules. Sume video inspect returns a probe with duration_seconds, width, height, rotation, fps, size_bytes, video_codec, has_audio and audio_codec for any clip in your workspace, and you can run it with frames set to false so that no stills are produced. Eight platform rule sets, each taken from that platform's own help or developer page that we read on 2026-10-05, fit in a small Python dictionary.

The point of doing it this way is that the probe is the only expensive step. Everything after it is plain arithmetic on a handful of numbers, so you can run the same check on a folder of clips, in a CI job, or in an agent step that decides whether to trim before it publishes. Because each rule is a line of data with a source, a reviewer can read the table and see where every number came from without reading the code.

The rules and where they come from

Each rule below comes from a page we read. Where a platform gave a limit in minutes or in megabytes, the table converts it to the units the code uses. A blank means the page gave no such limit, and the check skips it.

Two cautions on the table. The Instagram and TikTok rows come from developer reference pages that describe what the API accepts, which can differ from what a person can do in the phone app. And the Shorts row is a help page statement about the format, not an upload validator, so treat vertical and up to 3 minutes as the target and not a guarantee of how the platform classifies the video.

Limits used by the preflight (read 2026-10-05)
PlatformDurationSizeOther
Truth SocialUp to 15 minutes450 MB
Odysee16 GBUnder 8 Mbps recommended
ArtStation clip, freeUp to 1 minute25 MB
Linktree backgroundNo time limit50 MB
Snapchat Spotlight5 seconds or longerPost button rule
Instagram Reels API3 seconds to 15 minutes300 MB23 to 60 fps
TikTok APIUp to 10 minutes4 GB23 to 60 fps
YouTube ShortsUp to 3 minutesVertical, up to 1080p

The preflight

The rules are data and the check is one function. That makes it easy to add a ninth platform by adding a line, and easy to audit, since each line maps to a page. The function reads the probe, applies the rotation, and returns a list of problems per platform. An empty list means the clip passes on the numbers that the check covers.

RULES = {
    "truth_social": {"max_s": 900, "max_mb": 450},
    "odysee": {"max_mb": 16000, "max_mbps": 8},
    "artstation_free": {"max_s": 60, "max_mb": 25},
    "linktree_bg": {"max_mb": 50}, "spotlight": {"min_s": 5},
    "reels_api": {"min_s": 3, "max_s": 900, "max_mb": 300, "fps": (23, 60)},
    "tiktok_api": {"max_s": 600, "max_mb": 4000, "fps": (23, 60)},
    "shorts": {"max_s": 180, "vertical": True},
}

def preflight(p):
    s, mb = p["duration_seconds"], (p.get("size_bytes") or 0) / 1e6
    w, h = p["width"], p["height"]
    if p.get("rotation") in (90, 270, -90, -270):
        w, h = h, w
    out = {}
    for name, r in RULES.items():
        bad = []
        if s > r.get("max_s", 1e9): bad.append("too long")
        if s < r.get("min_s", 0): bad.append("too short")
        if mb > r.get("max_mb", 1e12): bad.append("too big")
        if mb * 8 / s > r.get("max_mbps", 1e9): bad.append("bitrate")
        if "fps" in r and not r["fps"][0] <= p["fps"] <= r["fps"][1]: bad.append("fps")
        if r.get("vertical") and h <= w: bad.append("not vertical")
        out[name] = bad
    return out

probe = {"duration_seconds": 42.0, "size_bytes": 31_000_000,
         "width": 1080, "height": 1920, "rotation": 0, "fps": 30}
print({k: v for k, v in preflight(probe).items() if v})

Reading the output

Run the sample and the output is a dictionary of only the failing platforms. For the sample, a 42-second, 31 MB, 1080 by 1920 clip at 30 fps, the free ArtStation rule fails on size, since 31 MB is over 25 MB, and Odysee's 8 Mbps recommendation passes, since 31 MB over 42 seconds is about 5.9 Mbps. The rest pass.

Check that arithmetic yourself, since it is the point of the exercise: 31 times 8 is 248 megabits, and 248 divided by 42 is 5.9 Mbps. So the sample's only failure is ArtStation free by size.

What it leaves out

The preflight does not cover codecs, container details or audio. Odysee's page asks for H264 and AAC, and the Instagram page lists codec and container rules, all of which are in the probe as video_codec, audio_codec and container, but this short version leaves them out to stay under 30 lines. Add them as further keys if you need them.

The preflight also treats size_bytes of null as zero, which lets a clip with no size pass the size rules. In production, treat a null as a failure instead. And all the megabyte figures use 1 MB as 1,000,000 bytes, which is a decision, since the pages do not define the unit.

The usual follow-up is to act on the result. If the failing list is only about length, cut with video trim. If it is about frame rate or size, conform the clip with the same trim job and probe again. The loop ends when the dictionary of failures is empty, and you keep the probe output from the final pass with the file as a record.

Where Sume fits

Sume does the media work, and each platform decides what it accepts. Trim can shorten a clip, conform its width, height and fps with exact precision, or drop audio, and the preflight tells you whether to do that. A trim is $0.02 per job at the public rate.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume