# Separate stems in a module

> Split a mix into vocals, drums, bass and other with the host separation task, then play the aligned stems through your Processor.

Canonical: https://maru.audio/docs/separate-stems-in-a-module
Documentation index: https://maru.audio/llms.txt

Stem separation turns one recording into aligned parts you can mute, solo,
remix or resample. It is part of [AI tasks in your module](https://maru.audio/docs/ai-tasks.md).
For what to expect from separated stems, read
[Split a song into stems](https://maru.audio/help/split-a-song-into-stems.md) in the
Help Center.

## 1. Declare the task and the stem buffer

The host separates and prepares the stems; your Processor plays them. Declare
the capability and one in-place data resource sized for the longest clip:

```ts
implementation: {
  kind: "processor",
  source: "src/dsp/processor.ts",
  resources: [
    {
      id: "stems",
      kind: "data",
      elementType: "f32",
      maxElements: 2 + 8 * SEPARATION_MAX_FRAMES,
      loading: "preload",
      storage: "in-place",
    },
  ],
},
ui: {
  entry: "./ui/index.tsx",
  hostCapabilities: { optional: ["audio.separation/v1"] },
},
```

`SEPARATION_MAX_FRAMES` comes from `@maruaudio/audio-contracts` (180 seconds at
44.1 kHz). The buffer layout is `[sourceRate, frames, vocalsL, vocalsR, drumsL,
drumsR, …]`: four stereo stems, aligned sample for sample.

The shared `@maruaudio/dsp/processors/stem-player` leaf plays that buffer on
the sample clock with per-stem gain, mute, solo and pan. StemSep's Processor
delegates to it entirely.

## 2. Drive it from the face

```tsx
const separation = face.separation
if (!separation) return <p>Stem separation is not available here.</p>

const { phase, source, results, progress } = separation.state

<Button onClick={separation.chooseSource}>Choose a song</Button>
<Button disabled={!source || phase === "separating"} onClick={separation.separate}>
  Separate
</Button>
```

| Member | Purpose |
| --- | --- |
| `methods`, `setMethod(id)` | The separation methods the host offers, each with `execution` (`local`, `server` or `commercial`), size, availability and a reason when unavailable |
| `chooseSource()`, `chooseExample(id)` | Pick a file or a host-supplied example |
| `separate()`, `cancel()` | Run or stop separation |
| `state.results`, `selectResult(id)` | Each run's stems with peaks and timing; selecting one loads it into the Processor |
| `exportStem(id)`, `exportAll()` | Host-encoded WAV exports |
| `configureKey?()`, `forgetKey?()` | A person's own key for a commercial provider |
| `trackRhythm?(source)`, `state.rhythm` | Beats and downbeats of the mix or the drum stem (see [Beats and tempo](https://maru.audio/docs/beats-and-tempo-in-a-module.md)) |
| `clearModelCache()` | Remove downloaded model files |

Always show the chosen method's `execution`. A `local` method keeps the audio on
the person's device; `server` and `commercial` methods upload it.

## Current implementations

| Method | Execution | Model |
| --- | --- | --- |
| On this device | `local` | [Spleeter](https://maru.audio/models/spleeter) 4-stem |
| Maru server | `server` | SCNet (evaluation) |
| Commercial provider | `commercial` | The provider's service, with the person's own key |

Show method labels and descriptions from `methods` rather than naming models in
your face.

## From an app or server

Apps submit `separate_audio_stems` with a prepared source and the stems they
want. See
[Add generative audio to your app](https://maru.audio/docs/generative-features.md#supply-audio-to-a-task).

## Limits and availability

- Up to 180 seconds and 128 MiB per source; long clips are processed in
  30-second windows.
- Separation runs on website module pages. Studio and native plug-ins do not
  offer it yet; a module there can still play stems it already has.

## Ask your agent

```text
Read the Maru docs page "Separate stems in a module", then read StemSep's
source with `maru module files stemsep` and `maru module read stemsep
src/index.ts`. Build a module that separates a song and lets me loop and
pitch-shift only the vocal stem.
```
