# Separación Demucs

Separa la música en stems (voces, batería, bajo, otros) con Demucs.

{% hint style="success" %}
Todos los ejemplos se pueden ejecutar en servidores GPU alquilados a través de [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

## Alquilar en CLORE.AI

1. Visita [CLORE.AI Marketplace](https://clore.ai/marketplace)
2. Filtrar por tipo de GPU, VRAM y precio
3. Elegir **Bajo demanda** (tarifa fija) o **Spot** (precio de puja)
4. Configura tu pedido:
   * Selecciona imagen Docker
   * Establece puertos (TCP para SSH, HTTP para interfaces web)
   * Agrega variables de entorno si es necesario
   * Introduce el comando de inicio
5. Selecciona pago: **CLORE**, **BTC**, o **USDT/USDC**
6. Crea el pedido y espera el despliegue

### Accede a tu servidor

* Encuentra los detalles de conexión en **Mis Pedidos**
* Interfaces web: Usa la URL del puerto HTTP
* SSH: `ssh -p <port> root@<proxy-address>`

## ¿Qué es Demucs?

Demucs de Meta AI puede:

* Separar las voces de la música
* Extraer batería, bajo y otros instrumentos
* Procesar cualquier formato de audio
* Extracción de stems de alta calidad

## Despliegue rápido

**Imagen Docker:**

```
pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime
```

**Puertos:**

```
22/tcp
7860/http
```

**Comando:**

```bash
pip install demucs gradio && \
python -c "
import gradio as gr
from demucs.pretrained import get_model
from demucs.apply import apply_model
import torch
import torchaudio
import tempfile
import os

model = get_model('htdemucs')
model.cuda()

def separate(audio_path, stem):
    wav, sr = torchaudio.load(audio_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    stems = {'drums': 0, 'bass': 1, 'other': 2, 'vocals': 3}
    output = sources[stems[stem]].cpu()

    with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as f:
        torchaudio.save(f.name, output, sr)
        return f.name

demo = gr.Interface(
    fn=separate,
    inputs=[gr.Audio(type='filepath'), gr.Dropdown(['vocals', 'drums', 'bass', 'other'])],
    outputs=gr.Audio(),
    title='Demucs Audio Separator'
)
demo.launch(server_name='0.0.0.0', server_port=7860)
"
```

## Accediendo a tu servicio

Después del despliegue, encuentra tu `http_pub` URL en **Mis Pedidos**:

1. Ir a **Mis Pedidos** página
2. Haz clic en tu pedido
3. Encuentra la `http_pub` URL (por ejemplo, `abc123.clorecloud.net`)

Usa `https://TU_HTTP_PUB_URL` en lugar de `localhost` en los ejemplos abajo.

## Instalación

```bash
pip install demucs

# o
pip install -e git+https://github.com/facebookresearch/demucs#egg=demucs
```

## Uso desde la línea de comandos

### Separación básica

```bash

# Separar en 4 stems
demucs song.mp3

# Salida: separated/htdemucs/song/{drums,bass,other,vocals}.wav
```

### Opciones

```bash
demucs \
    --two-stems vocals \     # Solo voces + instrumental
    -n htdemucs \            # Nombre del modelo
    -d cuda \                # Usar GPU
    -o ./output \            # Directorio de salida
    --mp3 \                  # Salida en MP3
    song.mp3
```

### Procesar carpeta

```bash
demucs --two-stems vocals -d cuda ./songs/*.mp3
```

## API de Python

### Separación básica

```python
from demucs.pretrained import get_model
from demucs.apply import apply_model
import torchaudio
import torch

# Cargar modelo
model = get_model('htdemucs')
model.cuda()
model.eval()

# Cargar audio
wav, sr = torchaudio.load("song.mp3")
wav = wav.cuda()

# Separar
with torch.no_grad():
    sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

# forma de sources: [4, canales, muestras]

# 0: batería, 1: bajo, 2: otros, 3: voces

# Guardar stems
stems = ['drums', 'bass', 'other', 'vocals']
for i, stem in enumerate(stems):
    torchaudio.save(f"{stem}.wav", sources[i].cpu(), sr)
```

### Obtener solo las voces

```python
def extract_vocals(audio_path):
    wav, sr = torchaudio.load(audio_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    vocals = sources[3].cpu()  # Índice 3 = voces
    return vocals, sr

vocals, sr = extract_vocals("song.mp3")
torchaudio.save("vocals.wav", vocals, sr)
```

### Obtener instrumental (sin voces)

```python
def extract_instrumental(audio_path):
    wav, sr = torchaudio.load(audio_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    # Sumar batería + bajo + otros
    instrumental = sources[0] + sources[1] + sources[2]
    return instrumental.cpu(), sr

instrumental, sr = extract_instrumental("song.mp3")
torchaudio.save("instrumental.wav", instrumental, sr)
```

## Variantes de modelo

| Modelo       | Stems | Calidad | Velocidad |
| ------------ | ----- | ------- | --------- |
| htdemucs     | 4     | Mejor   | Medio     |
| htdemucs\_ft | 4     | Best+   | Lento     |
| htdemucs\_6s | 6     | Genial  | Medio     |
| mdx\_extra   | 4     | Genial  | Rápido    |

### Modelo de 6 stems

```python
model = get_model('htdemucs_6s')

# Stems: batería, bajo, otros, voces, guitarra, piano
```

### Modelo afinado

```python
model = get_model('htdemucs_ft')

# Mayor calidad pero más lento
```

## Procesamiento por lotes

```python
import os
from demucs.pretrained import get_model
from demucs.apply import apply_model
import torchaudio
import torch

model = get_model('htdemucs')
model.cuda()
model.eval()

input_dir = "./songs"
output_dir = "./separated"

for filename in os.listdir(input_dir):
    if filename.endswith(('.mp3', '.wav', '.flac')):
        input_path = os.path.join(input_dir, filename)
        song_output_dir = os.path.join(output_dir, filename.rsplit('.', 1)[0])
        os.makedirs(song_output_dir, exist_ok=True)

        print(f"Procesando: {filename}")

        wav, sr = torchaudio.load(input_path)
        wav = wav.cuda()

        with torch.no_grad():
            sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

        stems = ['drums', 'bass', 'other', 'vocals']
        for i, stem in enumerate(stems):
            torchaudio.save(
                os.path.join(song_output_dir, f"{stem}.wav"),
                sources[i].cpu(),
                sr
            )

        print(f"Guardado: {song_output_dir}")
```

## Servidor API

```python
from fastapi import FastAPI, UploadFile
from fastapi.responses import FileResponse
from demucs.pretrained import get_model
from demucs.apply import apply_model
import torchaudio
import torch
import tempfile
import os

app = FastAPI()

model = get_model('htdemucs')
model.cuda()
model.eval()

@app.post("/separate")
async def separate(file: UploadFile, stem: str = "vocals"):
    # Guardar archivo subido
    with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
        content = await file.read()
        tmp.write(content)
        tmp_path = tmp.name

    # Cargar y separar
    wav, sr = torchaudio.load(tmp_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    stems = {'drums': 0, 'bass': 1, 'other': 2, 'vocals': 3}
    output = sources[stems[stem]].cpu()

    # Guardar salida
    with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as out:
        torchaudio.save(out.name, output, sr)
        return FileResponse(out.name, media_type="audio/wav")

@app.post("/instrumental")
async def get_instrumental(file: UploadFile):
    with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
        content = await file.read()
        tmp.write(content)
        tmp_path = tmp.name

    wav, sr = torchaudio.load(tmp_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    # Combinar stems que no son vocales
    instrumental = sources[0] + sources[1] + sources[2]

    with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as out:
        torchaudio.save(out.name, instrumental.cpu(), sr)
        return FileResponse(out.name, media_type="audio/wav")

# Ejecutar: uvicorn server:app --host 0.0.0.0 --port 8000
```

## Optimización de memoria

### Para audio largo

```python
from demucs.apply import apply_model

# Usar división para audio largo
sources = apply_model(
    model,
    wav.unsqueeze(0),
    split=True,         # Dividir en fragmentos
    overlap=0.25,       # Solapamiento entre fragmentos
    progress=True
)[0]
```

### Para VRAM limitada

```python

# Usar CPU para algunas operaciones
model.cpu()
wav = wav.cpu()

# O usar procesamiento por segmentos
sources = apply_model(
    model,
    wav.unsqueeze(0),
    split=True,
    segment=10  # segmentos de 10 segundos
)[0]
```

## Casos de uso

### Pista karaoke

```python
def create_karaoke(song_path):
    wav, sr = torchaudio.load(song_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    # Todo excepto las voces
    karaoke = sources[0] + sources[1] + sources[2]
    return karaoke.cpu(), sr
```

### Preparación para remix

```python
def extract_all_stems(song_path, output_dir):
    wav, sr = torchaudio.load(song_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    stems = ['drums', 'bass', 'other', 'vocals']
    paths = {}

    for i, stem in enumerate(stems):
        path = os.path.join(output_dir, f"{stem}.wav")
        torchaudio.save(path, sources[i].cpu(), sr)
        paths[stem] = path

    return paths
```

### Extracción de acapella

```python
def extract_acapella(song_path):
    wav, sr = torchaudio.load(song_path)
    wav = wav.cuda()

    with torch.no_grad():
        sources = apply_model(model, wav.unsqueeze(0), split=True)[0]

    vocals = sources[3]
    return vocals.cpu(), sr
```

## Consejos de calidad

### Para mejores resultados

* Usar entrada sin pérdida (WAV, FLAC)
* Mayor frecuencia de muestreo = mejor calidad
* Usa `htdemucs_ft` para trabajos críticos

### Postprocesamiento

```python
from pydub import AudioSegment
from pydub.effects import normalize, high_pass_filter

# Cargar vocal separada
vocals = AudioSegment.from_wav("vocals.wav")

# Eliminar rumor bajo
vocals = high_pass_filter(vocals, 80)

# Normalizar
vocals = normalize(vocals)

vocals.export("vocals_clean.wav", format="wav")
```

## Rendimiento

| Duración del audio | GPU      | Tiempo  |
| ------------------ | -------- | ------- |
| canción de 3 min   | RTX 3090 | \~15s   |
| canción de 3 min   | RTX 4090 | \~10s   |
| canción de 3 min   | A100     | \~8s    |
| álbum de 1 hora    | RTX 3090 | \~5 min |

## Solución de problemas

### Memoria insuficiente

```bash

# Usar segmentos más pequeños
demucs --segment 10 song.mp3
```

### Separación deficiente

* Usar el modelo htdemucs\_ft
* Comprobar la calidad de entrada
* Evitar MP3s muy comprimidos

### Artefactos

* Aumentar el solapamiento
* Usar un modelo de mayor calidad
* Comprobar si hay recorte (clipping) en la entrada

## Estimación de costos

Tarifas típicas del marketplace de CLORE.AI (a fecha de 2024):

| GPU       | Tarifa por hora | Tarifa diaria | Sesión de 4 horas |
| --------- | --------------- | ------------- | ----------------- |
| RTX 3060  | \~$0.03         | \~$0.70       | \~$0.12           |
| RTX 3090  | \~$0.06         | \~$1.50       | \~$0.25           |
| RTX 4090  | \~$0.10         | \~$2.30       | \~$0.40           |
| A100 40GB | \~$0.17         | \~$4.00       | \~$0.70           |
| A100 80GB | \~$0.25         | \~$6.00       | \~$1.00           |

*Los precios varían según el proveedor y la demanda. Consulta* [*CLORE.AI Marketplace*](https://clore.ai/marketplace) *para las tarifas actuales.*

**Ahorra dinero:**

* Usa **Spot** market para cargas de trabajo flexibles (a menudo 30-50% más barato)
* Paga con **CLORE** tokens
* Compara precios entre diferentes proveedores

## Próximos pasos

* [Clon de voz RVC](/guides/guides_v2-es/audio-y-voz/rvc-voice-clone.md) - Procesar las voces extraídas
* [AudioCraft Music](/guides/guides_v2-es/audio-y-voz/audiocraft-music.md) - Generar nueva música
* [Whisper Transcription](/guides/guides_v2-es/audio-y-voz/whisper-transcription.md) - Transcribir las voces


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-es/audio-y-voz/demucs-separation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
