Kolbo.AIKolbo.AI Docs
Developer API

Audio Separation

Split a soundtrack into Dialogue, Music, Effects and a without-dialogue (M&E) track with Kolbo's own stem separation pipeline.

Split any soundtrack into separate audio layers — Dialogue, Music, Effects, and a without-dialogue (M&E) track. Built for dubbing and localisation, podcast cleanup, re-scoring, and handing an editor usable stems.

This is Kolbo's own pipeline, not a passthrough to a single vendor. Two things make it different from a generic "vocal remover":

  • It masks rather than resynthesises. The returned layers sum back to the original at −30 to −37 dB, so the audio you get back is the audio you put in, filtered — not a reconstruction of it.
  • A speech classifier decides what "dialogue" means. A vocal mask is not the same thing as speech: engines, impacts and centred ambience land in it at full volume. When a clip has no spoken words, that mask is folded back into Effects instead of being handed to you labelled as Dialogue.

These endpoints answer inline. There is no generation id to poll — the response body carries the finished layer URLs. A typical clip takes 20–90 seconds. Do not call /v1/generate/:id/status on the result.

All three endpoints accept an optional project_id body field that bills against and files the work into a specific project. See Projects.

Endpoints

POST /api/v1/audio/separate         # 5 credits  — the main split
POST /api/v1/audio/clean-dialogue   # 17 credits — remove voice leaking into the M&E track
POST /api/v1/audio/ambience         # 17 credits — pull room tone out of the Effects bed

Two ways to name the source

Every endpoint takes exactly one of:

FieldTypeDescription
audio_urlstringAny public audio or video URL — a Kolbo CDN asset, an upload_media result, or any direct link. Aliases video_url, media_url, file_url and url are accepted and behave identically.
generation_idstringThe id of a Kolbo video generation you already created.

Sending both returns 400. The two paths differ in one important way:

audio_urlgeneration_id
Result storageLayer URLs returned to you; nothing is stored against the sourceLayers are also saved onto the generation
Repeat callsNot cached — separates again and bills againCached; a repeat call returns the same layers for 0 credits
Source lengthUp to 15 minutesWhatever the generation is
Visible in the web appNoYes — the Shot Editor mixer reads the same layers

Prefer generation_id whenever the source is a Kolbo generation.

POST /v1/audio/separate

Splits the soundtrack. 5 credits.

Request

FieldTypeRequiredDescription
audio_urlstringNo*Public audio/video URL to separate
generation_idstringNo*Kolbo video generation id to separate instead
project_idstringNoProject to bill against and file into

*Exactly one of audio_url / generation_id.

curl -X POST https://api.kolbo.ai/api/v1/audio/separate \
  -H "X-API-Key: kolbo_live_..." \
  -H "Content-Type: application/json" \
  -d '{"audio_url": "https://media.kolbo.ai/uploads/interview.mp4"}'

Response

{
  "success": true,
  "source": "url",
  "layers": [
    { "type": "original", "label": "Original",          "url": "https://media.kolbo.ai/.../original-....wav" },
    { "type": "dialogue", "label": "Dialogue",          "url": "https://media.kolbo.ai/.../dialogue-....wav" },
    { "type": "music",    "label": "Music",             "url": "https://media.kolbo.ai/.../music-....wav" },
    { "type": "sfx",      "label": "Effects",           "url": "https://media.kolbo.ai/.../sfx-....wav" },
    { "type": "me",       "label": "Without dialogue",  "url": "https://media.kolbo.ai/.../me-....wav" }
  ],
  "has_dialogue": true,
  "has_music": true,
  "credits_used": 5
}

All layers are 48 kHz stereo WAV on the Kolbo CDN.

typeWhat it contains
originalThe untouched mix, for reference
dialogueSpeech only
musicScore / song bed
sfxEffects and Foley
meEverything except dialogue — the track you dub over

Layers are omitted when the material doesn't contain them. A talking-head clip with no score returns no music layer, and a clip with no spoken words returns no dialogue layer. This is deliberate: shipping an empty Music row plus an sfx track byte-identical to me would be two misleading lanes instead of one honest pair. Read has_dialogue / has_music and branch on the type values actually present rather than assuming a fixed five.

POST /v1/audio/clean-dialogue

Strips voices still faintly audible in an M&E track. 17 credits.

Kolbo's separation leaves roughly −33 to −40 dB of speech in the M&E on clean dialogue (inaudible) and about −19 dB on a dense crowd scene (faint). Use this only when that residue actually matters to you — it trades fidelity to do its job, reconstructing the bed at about −12 dB against the −30 dB of the masking split that produced it. It is an escalation, not a step in the normal flow.

FieldTypeRequiredDescription
audio_urlstringNo*The me layer URL returned by /v1/audio/separate
generation_idstringNo*Kolbo video whose stems were already separated — cleans its M&E layer in place
project_idstringNoProject to bill against

*Exactly one.

{
  "success": true,
  "source": "url",
  "layers": [{ "type": "me", "label": "Without dialogue", "url": "https://media.kolbo.ai/.../me-....wav" }],
  "passes": 2,
  "margin_db": -18.4,
  "already_clean": false,
  "credits_used": 17
}

passes is how many removal passes ran before the result stopped improving. already_clean: true means the analysis found nothing worth removing and url is the track you sent.

The analysis pass runs — and is billed — even when the track turns out to be already clean. Check already_clean before telling a user something was removed.

POST /v1/audio/ambience

Pulls room tone / atmosphere out of an Effects or Music bed, leaving hard effects behind. 17 credits.

FieldTypeRequiredDescription
audio_urlstringNo*The sfx (or music) layer URL returned by /v1/audio/separate
source_typestringNoWhich lane audio_url came from — "sfx" (default), "music" or "me". Labels the leftover correctly
generation_idstringNo*Kolbo video whose stems were already separated — picks the source lane automatically
project_idstringNoProject to bill against

*Exactly one of audio_url / generation_id.

{
  "success": true,
  "source": "url",
  "layers": [
    { "type": "sfx",      "label": "Effects",  "url": "https://media.kolbo.ai/.../sfx-....wav" },
    { "type": "ambience", "label": "Ambience", "url": "https://media.kolbo.ai/.../ambience-....wav" }
  ],
  "skipped": false,
  "levels": { "target": -24.1, "residual": -31.7 },
  "credits_used": 17
}

skipped: true means the bed had no separable ambience and layers is empty. As with clean-dialogue, the pass ran and is billed.

Errors

CodeStatusMeaning
NO_AUDIO400The file has no audio stream, or its audio is digital silence. Checked before anything is charged
SOURCE_TOO_LONG400The audio_url source is longer than 15 minutes. Trim it or split it into sections. Also checked before charging
MISSING_SOURCE400Neither audio_url nor generation_id was provided
INSUFFICIENT_CREDITS403Balance too low. Includes required and available
STEMS_IN_PROGRESS409(generation_id only) A separation on that generation is already running
RATE_LIMITED42910 requests/minute per account, shared with the in-app surface

Rate limits and timeouts

  • 10 requests/minute per account, shared with the Kolbo web app's own separation surface, so switching between them does not double your allowance.
  • The route holds its connection for the whole run and gives up at 10 minutes. Set your HTTP client's timeout above that; a shorter client timeout aborts your side while the server keeps working, and you lose the result.
  • Concurrent calls are independent — but each one spends credits, and the audio_url form has no cache. Two identical calls separate twice and bill twice.
  • Transcription — if you want the words as text, not the audio layers
  • Video Editinggenerate_audio adds an AI-generated audio layer; it is not the inverse of this endpoint
  • Media LibraryPOST /v1/media/upload to get a public URL for a local file first