20 TopView ads per ad group: 20 hook swaps from one body for $2.00
TikTok's TopView page allows at most 20 ads per ad group. Build 20 hook variants over one body with Timeline 1.0: 20 one-minute reservations, $2.00.

Twenty hook swaps over one shared body fill a TopView ad group exactly. TikTok's TopView page sets the maximum at 20 ads per ad group (read 2026-10-07). In Sume, each 15-second Timeline render reserves one output minute at $0.10, so 20 variants cost $2.00 of assembly, before you pay for the hook and body clips themselves.
The discipline is to change one thing per variant, so a result tells you which hook did the work.
Constraints from the TopView page
From TikTok's TopView page. The review step and the freeze after preloading mean variants must exist before submission.
| Constraint | Value |
|---|---|
| Ads per ad group | maximum 20 |
| Duration | 5-60 s (9-15 s recommended) |
| Pre-approval | from your sales representative before submission |
| Assets after preloading begins | cannot be modified |
Build 20 bodies in a loop
Each variant is a 5-second hook followed by a shared 10-second body, over a 15-second voice spine. The script builds the 20 bodies and totals the reserved minutes: ceil(audio.duration_seconds / 60) per render. Send each body to POST /v1/timeline-1.0/plan first, which is unbilled, then to render with a unique idempotency key.
import json
import math
body_url = "https://media.sume.com/artifacts/artf_demo/body.mp4"
vo_url = "https://media.sume.com/artifacts/artf_demo/vo.wav"
bodies = []
for n in range(1, 21):
hook = "https://media.sume.com/artifacts/artf_demo/hook-%02d.mp4" % n
bodies.append({
"audio": {"url": vo_url, "duration_seconds": 15},
"video": [
{"source_url": hook, "start": 0, "duration": 5},
{"source_url": body_url, "start": 5, "duration": 10},
],
})
minutes = sum(math.ceil(b["audio"]["duration_seconds"] / 60) for b in bodies)
print(len(bodies), "variants,", minutes, "minutes, $%.2f" % (minutes * 0.10))
print(json.dumps(bodies[0]["video"][0]))Limits of the shared voice
One spine over 20 hooks means the hook's own audio is replaced, so a hook that depends on speech needs its own spine. For that, give the variant its own audio.url; the cost rule is unchanged.
Each render still needs a probe: duration within 5-60 s, 1080x1920 against TikTok's 540x960 px minimum, and a bitrate of at least 2,500 kbps (both listed for non-Spark ads, read 2026-10-07).
What it does not do
Sume does not run the ad group, tell you which hook won, or lift the 20-ad cap. Twenty is a ceiling set by TikTok; you may wish to spend fewer, bigger bets. Collect the files per Jobs and results.
How to read the results
Twenty variants are only useful if each differs by one variable. Name the files by hook, keep body, voice, and music constant, and write the hypothesis next to each key in the job record before the ad runs.
If you cannot afford twenty hook clips, five hooks across four voice reads is also twenty, with a different lesson. Either way the assembly cost stays at $0.10 per render, and the creative work is the real budget.
Sources
Related posts
More in Use cases
- 30, 15 and 6-second cutdowns from one master with video trim
Make three cutdowns from one master clip with video trim: $0.02 each, $0.06 in all. Use exact precision, conform to 1080x1920, and keep or drop the audio.
- A 30-second Business Profile video in one Wan 3.0 job: $3.75 at 720p
Wan 3.0 on Sume makes up to 30 seconds in one job: $3.75 at 720p, Google Business Profile's minimum, with no seam. Three Omni clips plus Timeline cost $3.85.
- 5-minute AI presenter video on Sume: $55.20 avatar plus $0.50 render
A 5-minute presenter video made of five 60-second Standard avatar jobs (no product) costs $55.20, plus $0.50 to render the Timeline: $55.70 in total.
- A 50-page deck to AI video: five ten-slide Wan 3.0 batches on Sume
Alibaba caps document input at 50 pages. Sume wan-3.0 takes 10 reference images per job, so a 50-slide deck becomes five jobs. Cost at 6 s or 30 s per batch.
Written by Sume