> ## Documentation Index
> Fetch the complete documentation index at: https://docs.camb.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Audio separation

> Split mixed audio into foreground and background stems using the Python or TypeScript SDK

## Overview

Separate a mixed recording into two stems: **foreground** (vocals, speech, or lead elements) and **background** (accompaniment, ambience, or supporting sounds). This is useful for remixing, isolation, accessibility, and cleaning up recordings.

The pipeline is asynchronous: you upload an audio file, poll until processing finishes, then download URLs for both stems.

### Prerequisites

<Steps>
  <Step title="Create an account">
    Sign up at [CAMB.AI Studio](https://studio.camb.ai) if you haven't already.
  </Step>

  <Step title="Get your API key">
    Go to **Settings → API Keys** in Studio and copy your key. See [Authentication](/getting-started/authentication) for details.
  </Step>

  <Step title="Install the SDK">
    <CodeGroup>
      ```bash Python theme={null}
      pip install camb-sdk
      ```

      ```bash TypeScript theme={null}
      npm install @camb-ai/sdk
      ```
    </CodeGroup>

    Skip this step if you're using the [direct API](/tutorials/direct-api).
  </Step>

  <Step title="Set your API key to use in your code">
    ```bash theme={null}
    export CAMB_API_KEY="your_api_key_here"
    ```
  </Step>
</Steps>

***

## Code

<CodeGroup>
  ```python Python theme={null}
  import os
  import time
  from camb.client import CambAI

  client = CambAI(api_key=os.getenv("CAMB_API_KEY"))

  def separate_audio():
      # Replace with your mixed audio file (WAV, MP3, FLAC, or AAC)
      audio_path = "mix.wav"

      # Step 1: Submit the separation job (multipart upload)
      response = client.audio_separation.create_audio_separation(
          media_file=open(audio_path, "rb"),
          project_name="my-separation-job",
      )

      task_id = response.task_id
      print(f"Audio separation task created: {task_id}")

      # Step 2: Poll until complete
      max_attempts = 60
      attempt = 0
      while attempt < max_attempts:
          status = client.audio_separation.get_audio_separation_status(task_id=task_id)
          print(f"Status: {status.status}")

          if status.status == "SUCCESS":
              # Step 3: Retrieve download URLs for both stems
              result = client.audio_separation.get_audio_separation_run_info(status.run_id)
              print(f"Foreground URL: {result.foreground_audio_url}")
              print(f"Background URL: {result.background_audio_url}")
              break
          elif status.status == "ERROR":
              print(f"Separation failed: {status.exception_reason}")
              break

          time.sleep(5)
          attempt += 1

  separate_audio()
  ```

  ```javascript TypeScript theme={null}
  import { CambClient } from '@camb-ai/sdk';
  import * as fs from 'fs';

  const client = new CambClient({
      apiKey: process.env.CAMB_API_KEY
  });

  async function separateAudio() {
      const audioPath = 'mix.wav'; // Replace with your mixed audio file

      if (!fs.existsSync(audioPath)) {
          console.error('Audio file not found:', audioPath);
          return;
      }

      // Step 1: Submit the separation job (multipart upload)
      const response = await client.audioSeparation.createAudioSeparation({
          media_file: fs.createReadStream(audioPath),
          project_name: 'my-separation-job'
      });

      const taskId = response.task_id;
      console.log(`Audio separation task created: ${taskId}`);

      if (!taskId) {
          console.error('No task ID returned.');
          return;
      }

      // Step 2: Poll until complete
      const maxAttempts = 60;
      let attempt = 0;

      while (attempt < maxAttempts) {
          const status = await client.audioSeparation.getAudioSeparationStatus({
              task_id: taskId
          });

          console.log(`Status: ${status.status}`);

          if (status.status === 'SUCCESS') {
              // Step 3: Retrieve download URLs for both stems
              const result = await client.audioSeparation.getAudioSeparationRunInfo({
                  run_id: status.run_id
              });

              console.log(`Foreground URL: ${result.foreground_audio_url}`);
              console.log(`Background URL: ${result.background_audio_url}`);
              break;
          } else if (status.status === 'ERROR') {
              console.error(`Separation failed: ${status.exception_reason}`);
              break;
          }

          await new Promise(resolve => setTimeout(resolve, 5000));
          attempt++;
      }

      if (attempt >= maxAttempts) {
          console.error('Timeout waiting for separation to complete.');
      }
  }

  separateAudio();
  ```
</CodeGroup>

***

## Parameters

### Required

| Parameter    | Type        | Description                                               |
| ------------ | ----------- | --------------------------------------------------------- |
| `media_file` | file stream | Mixed audio to separate (uploaded as multipart form data) |

### Optional

| Parameter             | Type    | Description                         |
| --------------------- | ------- | ----------------------------------- |
| `project_name`        | string  | Label for the job in your dashboard |
| `project_description` | string  | Notes for the job                   |
| `folder_id`           | integer | Folder to organize the run under    |
| `run_id`              | integer | Optional run identifier for tracing |
| `traceparent`         | string  | Distributed tracing header value    |

***

## Tips

* **Formats:** FLAC, MP3, WAV, and AAC are supported; lossless or high-quality sources generally separate better than heavily compressed files.
* **Length:** Roughly 10 seconds to 10 minutes often works well; very long files may take more processing time.
* **Polling:** Cap your loop (for example 60 attempts × 5 seconds) and treat timeout as a separate failure path from `ERROR`.
* **Mix balance:** Foreground and background should both be audible in the original mix for cleaner stems.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Create Audio Separation" icon="book" href="/api-reference/endpoint/create-audio-separation">
    Multipart upload and task creation API reference.
  </Card>

  <Card title="Get Separation Status" icon="clock" href="/api-reference/endpoint/get-audio-separation-status">
    Poll task status with `task_id`.
  </Card>

  <Card title="Get Separation Result" icon="audio-waveform" href="/api-reference/endpoint/get-audio-separation-run-info">
    Retrieve `foreground_audio_url` and `background_audio_url`.
  </Card>

  <Card title="Dubbing" icon="video" href="/tutorials/dubbing-with-sdk">
    Translate video audio with the SDK.
  </Card>
</CardGroup>
