Shorts Sync to beat: how it works, and a manual version in Python

Sync to beat needs at least two photos or videos and cuts them to music. The help-page steps, and a Python script that sets Sume Timeline cut times.

4 min readSume
All posts

Sync to beat is a Shorts feature that lays your clips over music so the cuts land on the beat. YouTube's help page says to select at least two media assets, photos or videos, from your device gallery; tap Next to see a preview synced to music from YouTube; then either accept it or pick other audio from the carousel, or tap Skip to trim and add audio by hand.

You don't set the tempo yourself in that flow. If you want cuts at times you choose, you can compute them from a tempo and write them into a Sume Timeline.

What are the exact steps?

On the record screen, tap Add at the bottom left to open your device's gallery. Select at least two assets. Tap Next. YouTube previews your media automatically synced to music. If you like the pre-selected arrangement, tap Next again. If you prefer a different song, pick one from the carousel at the bottom. If you don't want the feature, tap Skip for the regular preview, where you can trim clips and add audio manually.

The page doesn't say how long each clip is held, which tempo is used, or whether it works on a clip longer than the beat; it describes the feature at that level only.

How would I do this myself?

The arithmetic is simple. One beat lasts 60 divided by the BPM, in seconds. Cut every N beats and each slot starts at a multiple of that length. Sume's Music Router doc shows a prompt can state a tempo, for example 84 BPM, so you can ask for a track at a tempo and cut to it; the music is then yours to place as the Timeline's audio spine.

Whether the generated track holds the BPM exactly is not something the doc promises, so listen to the result before you trust the grid.

Cut length for a given tempo, computed as 60 / BPM x beats per cut. Timeline limits from the Timeline 1.0 doc, read 2026-10-03.
BPMBeats per cutSeconds per clip
9021.33
12021.00
12042.00
14041.71

Python that builds the Timeline body

Timeline requires video[0].start to be 0, later starts to increase, and each duration to be at least 0.2 seconds. This script prints a request body for six clips at 120 BPM with a cut every two beats, so each clip is one second. Replace the URLs with your imported media.sume.com files.

import json

bpm = 120
beats_per_cut = 2
clips = [f"https://media.sume.com/artifacts/artf_demo/clip{i}.mp4" for i in range(1, 7)]

seconds = round(60 / bpm * beats_per_cut, 3)
video = [
    {"source_url": url, "start": round(i * seconds, 3), "duration": seconds}
    for i, url in enumerate(clips)
]
body = {
    "audio": {
        "url": "https://media.sume.com/artifacts/artf_demo/track.mp3",
        "duration_seconds": round(len(clips) * seconds, 3),
    },
    "video": video,
}
print(json.dumps(body, indent=2))

How do I send it?

POST the body to /v1/timeline-1.0/render with an Idempotency-Key, or to /v1/timeline-1.0/plan first for an unbilled preflight. The default output is 1080 by 1920, and the rate is $0.10 per ceil output minute, so a six-second render is $0.10. If you omit output.fps, the render keeps the rate your sources already run at. A 25 or 30 fps source mixed with a 24 fps one can resample, which shows as judder.

Which should I use?

Use Sync to beat for a quick camera-roll montage inside the app, where the music comes from YouTube's library. Use a Timeline when you want exact cut times, your own generated track, or a repeatable batch. In both cases, check the result by ear.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume