Media tools

Add background music to a video with an API: loop, fade, and duck

Add a soundtrack to a Sume Timeline 1.0 render to mix Sume-hosted music under a voice spine: set its level, loop it, fade it out, and duck it under speech.

5 min readSume
All posts

To add background music to a video with the Sume API, send a Timeline 1.0 render (POST /v1/timeline-1.0/render) with a soundtrack object: the Sume-hosted music url, plus optional gain_db, loop, fade_out_seconds, and duck_db. Sume mixes that bed under the audio spine and returns one MP4.

The facts below come from the Timeline 1.0 docs and the Timeline field descriptions in the Sume API reference, read on 2026-09-26. Anything described as current behavior is read from Sume's code. For the rest of the render document, see How to assemble a long-form video.

Where do the voice and the music come from?

Every URL in a render must already be your workspace's media.sume.com artifact or asset, such as the output of an earlier Sume job. A music URL on another host is refused with unsupported_media_source.

  • The voice spine: audio.url plus audio.duration_seconds (1–1800), which sets the output length. The API reference names an audio detach wav or a TTS master as spine-grade files.
  • The music: for example a track from the Music Router, read from the result artifact whose type is audio. Sume mirrors generated outputs to Sume-owned media URLs.

How do I mix a music bed under a voiceover?

Add soundtrack next to audio and video in the render body. The output audio is the spine plus the bed: in the current compiler a slot's own sound is never mixed in. If a clip already carries the narration, extract it with audio detach, whose default wav is the format audio.url expects, and pass that file as the spine.

curl -X POST https://api.sume.com/v1/timeline-1.0/render \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: timeline-music-001" \
  -d '{
    "audio": {
      "url": "https://media.sume.com/artifacts/artf_demo/voice.wav",
      "duration_seconds": 24
    },
    "soundtrack": {
      "url": "https://media.sume.com/artifacts/artf_demo/music.mp3",
      "loop": true,
      "fade_out_seconds": 3,
      "duck_db": 8
    },
    "video": [
      { "source_url": "https://media.sume.com/artifacts/artf_demo/clip.mp4", "start": 0, "duration": 24 }
    ]
  }'

What do gain_db, loop, fade_out_seconds, and duck_db do?

Only url is required. The voice keeps its own level: audio.gain_db (−60 to 12, default 0) is applied to the spine.

Soundtrack fields from Timeline 1.0 and the Sume API reference, read 2026-09-26.
FieldRangeOmittedEffect
urlSume-hosted HTTPSRequiredThe music file.
gain_db−60 to 12 dB−16 dBThe bed's level; the API reference calls −16 a bed level under a spine.
looptrue / falseNo loopRepeats the bed until the spine ends. Without it, a shorter bed stops partway and the render warns soundtrack_shorter_than_spine.
fade_out_seconds0–10 s0 (the bed stops dead)Fades the bed out over the last seconds of the spine.
duck_db0–20 dB0 (a static bed at gain_db)Target attenuation of the bed while the spine is speaking.

How does ducking work?

duck_db is a sidechain duck that follows the spine's envelope, so the bed dips while someone speaks. The API reference calls the value a target depth against a spine at speech level, not a constant gain, and in the current code a quieter voiceover ducks less.

In the current code the duck is keyed on the spine with a −40 dBFS threshold, a 20 ms attack, and a 300 ms release. The code's notes say that threshold is low enough for a TTS voiceover's near-silent gaps to let the bed back up, and high enough that room tone on a recorded voice does not hold the duck open.

duck_db needs a real spine. With audio.mode: "silence" there is nothing to key off, and the request is refused with duck_requires_audio_spine.

Can I make a video with music and no voice?

Yes. Set audio.mode: "silence" with audio.duration_seconds and no url, parts, gain_db, or source_in, then add a soundtrack. The bed becomes the whole audio track, so the API reference says to set soundtrack.gain_db to 0 unless you want it quiet; omitted, it still renders at −16 dB. Leave out duck_db. A photo montage built this way is covered in the image slideshow API.

What does it cost, and what can go wrong?

The render's public rate is $0.10 per output minute on API pricing, and the reserve is ceil(audio.duration_seconds / 60) minutes. The docs say to confirm the rate live in GET /v1/catalog.

  • unsupported_media_source: the music URL is not on the Sume media host.
  • soundtrack_fade_exceeds_output: the bed's fade is longer than the output.
  • duck_requires_audio_spine: duck_db on a silent spine.
  • soundtrack_shorter_than_spine is a warning, not a failure. Only the render can report it: the unbilled plan preflight never downloads media, so it cannot know the bed's length.

Sources

Related posts

Written by Sume