TikTok ad cuts in 9:16, 1:1 and 16:9 from one master clip

TikTok ads allow 9:16, 1:1 and 16:9 with set minimums. Cut all three from one master with Sume Timeline, picking cover or blur so little is lost.

1 min readSume
All posts

TikTok's in-feed ad specification lists three aspect ratios for non-Spark ads, each with a minimum size: 9:16 at least 540x960, 16:9 at least 960x540, and 1:1 at least 640x640. One 9:16 master can produce all three in Sume's Timeline, but the fit mode decides how much of the picture survives, and it differs by ratio.

The sizes are from TikTok Ads Help: video ad specifications (read 2026-10-03). The page also lists the formats .mp4, .mov, .mpeg, .3gp and .avi, a length of up to 10 minutes, a file size of 500 MB or less and a bitrate of at least 516 kbps. Sume's Timeline output is MP4.

What each cut keeps

From a 1080x1920 master, cover fills the frame and crops the overflow. For a 1080x1080 square it keeps 1080 of 1920 rows, 56.25 percent of the height. For a 1920x1080 wide frame it would scale to 1920 wide and keep only 1080 of about 3413 rows, 31.6 percent. So use cover for 1:1 if the subject sits mid-frame, and blur for 16:9, which keeps the full vertical frame fitted over a blurred fill.

Cuts from a 1080x1920 master against TikTok's minimums (read 2026-10-03)
RatioOutputTikTok minimumfitPicture kept
9:161080x1920540x960cover100%
1:11080x1080640x640cover56.25% of the height
16:91920x1080960x540blur100%, shown smaller

Plan all three, then render

Timeline 1.0 bills $0.10 per started output minute, so three 20-second cuts cost $0.30. The unbilled plan call confirms that before you commit. This loop runs the plan for each cut.

import json, os, time, urllib.request as u

def call(method, 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 is not None else None
    req = u.Request("https://api.sume.com" + path, data, h, method=method)
    with u.urlopen(req) as r:
        out = json.load(r)
    return out.get("data", out)

SRC = "https://media.sume.com/artifacts/artf_demo/master.mp4"
CUTS = {"9x16": (1080, 1920, "cover"), "1x1": (1080, 1080, "cover"),
        "16x9": (1920, 1080, "blur")}
for name, (w, h, fit) in CUTS.items():
    body = {"audio": {"mode": "silence", "duration_seconds": 20},
            "video": [{"source_url": SRC, "start": 0, "duration": 20, "fit": fit}],
            "output": {"width": w, "height": h}}
    plan = call("POST", "/v1/timeline-1.0/plan", body)
    print(name, plan["billable_minutes"], plan["estimated_cost_usd_micros"])

Spark Ads differ

The same page lists separate rules for Spark Ads: mp4 or mov and no duration restriction. This post covers only the non-Spark specification, so check the page for the Spark row before you reuse these cuts there.

Check the outputs

After rendering, read each file back with video inspect and compare its width and height with TikTok's minimums. 1080x1920, 1080x1080 and 1920x1080 clear them with room, so the main risk is a master that was exported too small to begin with. Resolution you do not have cannot be added later by an encoder.

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume