Holiday music bed under a voice: soundtrack duck_db 0 to 20

Sume Timeline takes a soundtrack bed with gain_db, loop, fade_out_seconds up to 10 and duck_db 0 to 20 under a voice spine. Python plan call and errors.

3 min readSume
All posts

To lay a holiday music bed under a voiceover in Sume, add a soundtrack object to the Timeline body with url, gain_db, loop, fade_out_seconds and duck_db. The docs give duck_db a range of 0 to 20 and say it needs a real audio spine, meaning your voiceover, not audio.mode: "silence". Ducking lowers the bed while the voice plays. Timeline bills $0.10 per ceil output minute, with the bed included in the render.

Fields

Every limit below is from the Timeline page.

Timeline soundtrack fields, per the Sume docs read 2026-10-08
FieldLimit or meaning
soundtrack.urlThe music bed, a media.sume.com file in your workspace
soundtrack.gain_dbLevel of the bed
soundtrack.loopRepeat the bed to fill the length
soundtrack.fade_out_secondsUp to 10; must not exceed the output length
soundtrack.duck_db0 to 20; needs a voice spine
audio.gain_db-60 to 12; the voice level

Steps

Set VOICE_URL, BED_URL and CLIP_URL to imported files. The plan call is free and checks the body, including the ducking rules.

import json, os, urllib.request

body = {
    "audio": {"url": os.environ["VOICE_URL"], "duration_seconds": 24},
    "video": [{"source_url": os.environ["CLIP_URL"], "start": 0,
               "duration": 24}],
    "soundtrack": {"url": os.environ["BED_URL"], "gain_db": -6,
                   "duck_db": 8, "loop": True, "fade_out_seconds": 2},
}
req = urllib.request.Request(
    "https://api.sume.com/v1/timeline-1.0/plan",
    data=json.dumps(body).encode(),
    headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
             "Content-Type": "application/json"},
)
print(json.load(urllib.request.urlopen(req))["billable_minutes"])

The sample uses a quiet bed (-6 dB) and ducks it a further 8 dB under speech. Those two numbers are starting points I chose, not recommendations from the docs, so listen to a render and adjust. When the plan passes, send the same body to POST /v1/timeline-1.0/render with an Idempotency-Key.

Errors to expect

  • duck_requires_audio_spine: you set duck_db with silence.
  • soundtrack_fade_exceeds_output: the fade is longer than the voice length.
  • audio_url_and_parts_exclusive: you sent both url and parts for the voice.

Setting the levels

Start with the voice at 0 dB, the bed at a negative gain_db, and a modest duck_db. The sample uses -6 and 8. If the bed is still loud under the voice, make gain_db more negative or raise duck_db toward the upper end of its 0 to 20 range. If the bed disappears, lower duck_db.

Render a short test of ten seconds first. Timeline bills per ceil output minute, so a ten-second test costs $0.10, the same as a 60-second render. Test once, adjust once, and then render the full piece.

A fade_out_seconds of one to three seconds avoids a hard stop at the end of the bed. The value must not exceed the output length, or the job returns soundtrack_fade_exceeds_output.

Budget and detail

Keep the bed shorter than you think. With loop on, a 15-second sting can fill a 60-second spot, but repeats can be audible, so if the music has a clear start and end, choose a bed long enough to cover the piece. Check the first and last two seconds of the render, since that is where fades and loop joins show up, and listen on phone speakers as well as headphones.

What Sume does not do

Sume does not pick licensed music for you in this call, so the bed must be a file you have the right to use. It does not measure loudness against a platform target, and I found no loudness normalizer in the docs.

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume