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

# Stem Separation

> Extract individual audio components from mixed recordings using AI-powered audio source separation.

## Overview

AudioPod AI's Stem Separation API uses state-of-the-art AI models to separate mixed audio recordings into individual components (stems). Extract vocals, drums, bass, guitar, piano, and more from any song.

### Key Features

* **Granular Separation**: Single, two, four, six, eight(producer), twelve(studio), sixteen(mastering)
* **File Upload & URL Support**: Process local files or YouTube/SoundCloud URLs
* **Quality Scores**: Get AI-assessed quality metrics for each stem
* **Presigned Downloads**: Direct S3 URLs for fast stem downloads

## Installation

<Tabs>
  <Tab title="Python">
    ```bash theme={null}
    pip install audiopod
    ```
  </Tab>

  <Tab title="Node.js">
    ```bash theme={null}
    npm install audiopod
    ```
  </Tab>
</Tabs>

## Authentication

Get your API key from the [API Keys Dashboard](https://www.audiopod.ai/dashboard/account/api-keys).

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")
    # Or set AUDIOPOD_API_KEY environment variable
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });
    // Or set AUDIOPOD_API_KEY environment variable
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    export AUDIOPOD_API_KEY="ap_your_api_key"
    # Use -H "X-API-Key: $AUDIOPOD_API_KEY" in requests
    ```
  </Tab>
</Tabs>

## Separation Modes

| Mode        | Stems | Output                      | Use Case                         |
| ----------- | ----- | --------------------------- | -------------------------------- |
| `single`    | 1     | Specified stem only         | Vocal isolation, drum extraction |
| `two`       | 2     | vocals + instrumental       | Karaoke tracks                   |
| `four`      | 4     | vocals, drums, bass, other  | Standard remixing                |
| `six`       | 6     | + guitar, piano             | Full instrument separation       |
| `producer`  | 8     | + kick, snare, hihat        | Beat production                  |
| `studio`    | 12    | + cymbals, sub\_bass, synth | Professional mixing              |
| `mastering` | 16    | Maximum detail              | Forensic analysis                |

***

## Quick Start

### Six-Stem Separation

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    # Extract and wait for completion
    result = client.stems.separate(
        url="https://youtube.com/watch?v=VIDEO_ID",
        mode="six"
    )

    # Download stems
    print("Stems ready:")
    for stem, url in result["download_urls"].items():
        print(f"  {stem}: {url[:60]}...")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    // Extract and wait for completion
    const result = await client.stems.separate({
      url: 'https://youtube.com/watch?v=VIDEO_ID',
      mode: 'six'
    });

    // Download stems
    console.log('Stems ready:');
    for (const [stem, url] of Object.entries(result.download_urls)) {
      console.log(`  ${stem}: ${url.substring(0, 60)}...`);
    }
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Submit job
    curl -X POST "https://api.audiopod.ai/api/v1/stem-extraction/api/extract" \
      -H "X-API-Key: $AUDIOPOD_API_KEY" \
      -F "url=https://youtube.com/watch?v=VIDEO_ID" \
      -F "mode=six"

    # Check status (replace JOB_ID)
    curl -X GET "https://api.audiopod.ai/api/v1/stem-extraction/status/JOB_ID" \
      -H "X-API-Key: $AUDIOPOD_API_KEY"
    ```
  </Tab>
</Tabs>

***

## Examples by Mode

### Four-Stem Separation (Standard)

Extract vocals, drums, bass, and other.

<Tabs>
  <Tab title="Python (URL)">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    result = client.stems.separate(
        url="https://youtube.com/watch?v=VIDEO_ID",
        mode="four"
    )

    print(f"Vocals: {result['download_urls']['vocals']}")
    print(f"Drums: {result['download_urls']['drums']}")
    print(f"Bass: {result['download_urls']['bass']}")
    print(f"Other: {result['download_urls']['other']}")
    ```
  </Tab>

  <Tab title="Python (File)">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    result = client.stems.separate(
        file="/path/to/song.mp3",
        mode="four"
    )

    for stem, url in result["download_urls"].items():
        print(f"{stem}: {url}")
    ```
  </Tab>

  <Tab title="Node.js (URL)">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    const result = await client.stems.separate({
      url: 'https://youtube.com/watch?v=VIDEO_ID',
      mode: 'four'
    });

    console.log(`Vocals: ${result.download_urls.vocals}`);
    console.log(`Drums: ${result.download_urls.drums}`);
    console.log(`Bass: ${result.download_urls.bass}`);
    console.log(`Other: ${result.download_urls.other}`);
    ```
  </Tab>

  <Tab title="Node.js (File)">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    const result = await client.stems.separate({
      file: '/path/to/song.mp3',
      mode: 'four'
    });

    for (const [stem, url] of Object.entries(result.download_urls)) {
      console.log(`${stem}: ${url}`);
    }
    ```
  </Tab>

  <Tab title="cURL (URL)">
    ```bash theme={null}
    curl -X POST "https://api.audiopod.ai/api/v1/stem-extraction/api/extract" \
      -H "X-API-Key: $AUDIOPOD_API_KEY" \
      -F "url=https://youtube.com/watch?v=VIDEO_ID" \
      -F "mode=four"
    ```
  </Tab>

  <Tab title="cURL (File)">
    ```bash theme={null}
    curl -X POST "https://api.audiopod.ai/api/v1/stem-extraction/api/extract" \
      -H "X-API-Key: $AUDIOPOD_API_KEY" \
      -F "file=@/path/to/song.mp3" \
      -F "mode=four"
    ```
  </Tab>
</Tabs>

***

### Single Stem Extraction (Vocals Only)

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    # Extract only vocals
    result = client.stems.separate(
        url="https://youtube.com/watch?v=VIDEO_ID",
        mode="single",
        stem="vocals"  # Options: vocals, drums, bass, guitar, piano, other
    )

    print(f"Vocals: {result['download_urls']['vocals']}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    // Extract only vocals
    const result = await client.stems.separate({
      url: 'https://youtube.com/watch?v=VIDEO_ID',
      mode: 'single',
      stem: 'vocals' // Options: vocals, drums, bass, guitar, piano, other
    });

    console.log(`Vocals: ${result.download_urls.vocals}`);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST "https://api.audiopod.ai/api/v1/stem-extraction/api/extract" \
      -H "X-API-Key: $AUDIOPOD_API_KEY" \
      -F "url=https://youtube.com/watch?v=VIDEO_ID" \
      -F "mode=single" \
      -F "stem=vocals"
    ```
  </Tab>
</Tabs>

***

### Two-Stem Separation (Karaoke)

Separate vocals from instrumental.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    result = client.stems.separate(
        url="https://youtube.com/watch?v=VIDEO_ID",
        mode="two"
    )

    # Returns: vocals + no_vocals (instrumental)
    print(f"Vocals: {result['download_urls']['vocals']}")
    print(f"Instrumental: {result['download_urls']['no_vocals']}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    const result = await client.stems.separate({
      url: 'https://youtube.com/watch?v=VIDEO_ID',
      mode: 'two'
    });

    // Returns: vocals + no_vocals (instrumental)
    console.log(`Vocals: ${result.download_urls.vocals}`);
    console.log(`Instrumental: ${result.download_urls.no_vocals}`);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST "https://api.audiopod.ai/api/v1/stem-extraction/api/extract" \
      -H "X-API-Key: $AUDIOPOD_API_KEY" \
      -F "url=https://youtube.com/watch?v=VIDEO_ID" \
      -F "mode=two"
    ```
  </Tab>
</Tabs>

***

### Producer Mode (8 Stems with Drum Kit)

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    result = client.stems.separate(
        url="https://youtube.com/watch?v=VIDEO_ID",
        mode="producer"
    )

    # Returns: vocals, kick, snare, hihat, bass, guitar, piano, other
    for stem, url in result["download_urls"].items():
        print(f"{stem}: {url[:60]}...")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    const result = await client.stems.separate({
      url: 'https://youtube.com/watch?v=VIDEO_ID',
      mode: 'producer'
    });

    // Returns: vocals, kick, snare, hihat, bass, guitar, piano, other
    for (const [stem, url] of Object.entries(result.download_urls)) {
      console.log(`${stem}: ${url.substring(0, 60)}...`);
    }
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST "https://api.audiopod.ai/api/v1/stem-extraction/api/extract" \
      -H "X-API-Key: $AUDIOPOD_API_KEY" \
      -F "url=https://youtube.com/watch?v=VIDEO_ID" \
      -F "mode=producer"
    ```
  </Tab>
</Tabs>

***

## Advanced Usage

### Async Job Handling

For more control, use `extract()` and `wait_for_completion()` separately:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    # Submit job (returns immediately)
    job = client.stems.extract(
        url="https://youtube.com/watch?v=VIDEO_ID",
        mode="six"
    )
    print(f"Job submitted: {job['id']}")

    # Do other work...

    # Wait for completion when ready
    result = client.stems.wait_for_completion(job["id"], timeout=600)

    if result["status"] == "COMPLETED":
        print("Download URLs:")
        for stem, url in result["download_urls"].items():
            print(f"  {stem}: {url}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    // Submit job (returns immediately)
    const job = await client.stems.extract({
      url: 'https://youtube.com/watch?v=VIDEO_ID',
      mode: 'six'
    });
    console.log(`Job submitted: ${job.id}`);

    // Do other work...

    // Wait for completion when ready
    const result = await client.stems.waitForCompletion(job.id, 600000);

    if (result.status === 'COMPLETED') {
      console.log('Download URLs:');
      for (const [stem, url] of Object.entries(result.download_urls)) {
        console.log(`  ${stem}: ${url}`);
      }
    }
    ```
  </Tab>
</Tabs>

### Get Available Modes

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    modes = client.stems.modes()

    print("Available modes:")
    for m in modes["modes"]:
        print(f"  {m['mode']}: {m['description']} ({m['stem_count']} stems)")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    const modes = await client.stems.modes();

    console.log('Available modes:');
    modes.modes.forEach(m => {
      console.log(`  ${m.mode}: ${m.description} (${m.stem_count} stems)`);
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X GET "https://api.audiopod.ai/api/v1/stem-extraction/modes"
    ```
  </Tab>
</Tabs>

### Check Job Status

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod

    client = AudioPod(api_key="ap_your_api_key")

    status = client.stems.status(5512)

    print(f"Status: {status['status']}")

    if status["status"] == "COMPLETED":
        print("Quality scores:")
        for stem, score in status["quality_scores"].items():
            print(f"  {stem}: {score:.2f}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod from 'audiopod';

    const client = new AudioPod({ apiKey: 'ap_your_api_key' });

    const status = await client.stems.status(5512);

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

    if (status.status === 'COMPLETED') {
      console.log('Quality scores:');
      for (const [stem, score] of Object.entries(status.quality_scores)) {
        console.log(`  ${stem}: ${score.toFixed(2)}`);
      }
    }
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X GET "https://api.audiopod.ai/api/v1/stem-extraction/status/5512" \
      -H "X-API-Key: $AUDIOPOD_API_KEY"
    ```
  </Tab>
</Tabs>

***

## Response Format

**Completed Job Response:**

```json theme={null}
{
  "id": 5512,
  "status": "COMPLETED",
  "source_type": "URL",
  "stem_paths": {
    "vocals": "stems/5512/vocals.wav",
    "drums": "stems/5512/drums.wav",
    "bass": "stems/5512/bass.wav",
    "guitar": "stems/5512/guitar.wav",
    "piano": "stems/5512/piano.wav",
    "other": "stems/5512/other.wav"
  },
  "quality_scores": {
    "vocals": 0.64,
    "drums": 0.35,
    "bass": 0.87,
    "guitar": 0.38,
    "piano": 0.0,
    "other": 0.36
  },
  "download_urls": {
    "vocals": "https://media.audiopod.ai/...",
    "drums": "https://media.audiopod.ai/...",
    "bass": "https://media.audiopod.ai/...",
    "guitar": "https://media.audiopod.ai/...",
    "piano": "https://media.audiopod.ai/...",
    "other": "https://media.audiopod.ai/..."
  },
  "completed_at": "2025-12-11T12:39:37.379848"
}
```

***

## Pricing

**Base rate:** \$0.10 per minute of audio processed for standard modes (`2stem`,
`4stem`, `6stem`, `16stem`).

| Duration   | Cost (standard modes) |
| ---------- | --------------------- |
| 3 minutes  | \$0.30                |
| 5 minutes  | \$0.50                |
| 10 minutes | \$1.00                |
| 1 hour     | \$6.00                |

### Premium packages

Premium separation packages route through a higher-fidelity engine and bill at
a multiplier of the base rate:

| Package                                                         | Multiplier | Effective rate |
| --------------------------------------------------------------- | ---------- | -------------- |
| `karaoke` (lead vocal + backing vocal + instrumental)           | **1.5×**   | \$0.15/min     |
| `vocal_gender` (male + female + instrumental)                   | **1.5×**   | \$0.15/min     |
| `instrument_isolator` (any single instrument + everything-else) | **2.0×**   | \$0.20/min     |

<Info>
  Check your balance and usage at [API Wallet](/account/api-wallet).
</Info>

***

## Error Handling

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from audiopod import AudioPod, InsufficientBalanceError, AuthenticationError

    try:
        client = AudioPod(api_key="ap_...")
        result = client.stems.separate(url="...", mode="six")
    except AuthenticationError:
        print("Invalid API key")
    except InsufficientBalanceError as e:
        print(f"Need ${e.required_cents / 100:.2f}, have ${e.available_cents / 100:.2f}")
    except ValueError as e:
        print(f"Invalid input: {e}")
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import AudioPod, { InsufficientBalanceError, AuthenticationError } from 'audiopod';

    try {
      const client = new AudioPod({ apiKey: 'ap_...' });
      const result = await client.stems.separate({ url: '...', mode: 'six' });
    } catch (error) {
      if (error instanceof AuthenticationError) {
        console.log('Invalid API key');
      } else if (error instanceof InsufficientBalanceError) {
        console.log(`Need $${error.requiredCents / 100}, have $${error.availableCents / 100}`);
      } else {
        console.log(`Error: ${error.message}`);
      }
    }
    ```
  </Tab>
</Tabs>

***

## Status Codes

| Status       | Description                           |
| ------------ | ------------------------------------- |
| `PENDING`    | Job queued, waiting for worker        |
| `PROCESSING` | Stem separation in progress           |
| `COMPLETED`  | Success - download URLs available     |
| `FAILED`     | Error occurred - check error\_message |

***

## Next Steps

<Columns cols={2}>
  <Card title="API Wallet" icon="wallet" href="/account/api-wallet">
    Manage billing and view usage history.
  </Card>

  <Card title="Noise Reduction" icon="volume-xmark" href="/api-reference/noise-reduction">
    Clean up stems for better quality.
  </Card>
</Columns>
