One probe, three verdicts: Reels, Shorts and TikTok ad limits

Read a clip's size, rate, length and bitrate once with Sume video inspect, then test it against Instagram, YouTube and TikTok's published limits.

1 min readSume
All posts

If one master video goes to three platforms, one probe is enough to test it against all three. Sume's video inspect returns width, height, frame rate, duration and file size. From those you can check Instagram's Reel limits, YouTube's Shorts shape and length, and TikTok's ad minimums and bitrate floor in about ten lines.

The limits are from three vendor pages, all read 2026-10-03: Instagram Reel size, YouTube Shorts upload and TikTok video ad specifications. The script tests only what those pages state, so it cannot promise a platform will accept a file.

The limits in one table

Each row is one rule the script tests.

Published limits the script tests; vendor help pages (read 2026-10-03)
PlatformRule tested
Instagram ReelRatio 1.91:1 to 9:16, at least 30 FPS, at least 720 pixels
YouTube ShortUp to 3 minutes, square or vertical
TikTok ad (non-Spark)9:16 from 540x960, 16:9 from 960x540 or 1:1 from 640x640; up to 10 minutes; 500 MB or less; at least 516 kbps

The script

Per the Sume docs, the probe takes frames: false and returns size_bytes alongside the video fields. Bitrate here is the average over the whole file, audio included, so it is a rough check against the 516 kbps floor, and a frame rate of 29.97 reads as under 30.

import json, os, time, urllib.request as u
def api(m, path, body=None, key=None):
    h = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
         "Content-Type": "application/json"}
    if key: h["Idempotency-Key"] = key
    data = json.dumps(body).encode() if body else None
    with u.urlopen(u.Request("https://api.sume.com" + path, data, h, method=m)) as r:
        d = json.load(r)
    return d.get("data", d)
def probe(url):
    d = api("POST", "/v1/video-inspect", {"video_url": url, "frames": False}, "p12")
    for _ in range(30):
        if d.get("probe"): return d["probe"]
        time.sleep(2); d = api("GET", "/v1/video-inspect/" + d["id"])
p = probe("https://media.sume.com/artifacts/artf_demo/ad.mp4")
w, h, s = p["width"], p["height"], p["duration_seconds"]
kbps = p["size_bytes"] * 8 / s / 1000
mins = {(9, 16): (540, 960), (16, 9): (960, 540), (1, 1): (640, 640)}
tt = any(abs(w / h - a / b) < 0.01 and w >= mw and h >= mh
         for (a, b), (mw, mh) in mins.items())
print("Reel", 9 / 16 <= w / h <= 1.91 and p["fps"] >= 30 and min(w, h) >= 720)
print("Short", s <= 180 and w <= h)
print("TikTok ad", tt and kbps >= 516 and p["size_bytes"] <= 500e6 and s <= 600)

Reading the output

A 1080x1920 file at 30 fps, 45 seconds and 12 MB averages about 2,133 kbps and passes all three. The same file at 24 fps fails the Reel line only, and the fix is a 30 fps re-encode. A 1080x1920 clip over 180 seconds still suits TikTok ads, up to 600 seconds, but fails the Short line.

Extending it

Each platform check is one line, so adding a fourth platform means one more print. Keep the limits in a dictionary at the top and put the date you read the vendor page next to them, because these pages change and a stale number in a script is worse than none.

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume