File size: 3,191 Bytes
0f623ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# Step 2 β€” FastAPI Backend

**Status: TODO**

## Goal

Build an API that accepts an audio file upload, runs Demucs on it, and returns the cleaned vocals file.

---

## Install dependencies

```bash
source venv/bin/activate
pip install fastapi uvicorn python-multipart
```

---

## Files to create

```
backend/
β”œβ”€β”€ main.py            # FastAPI app β€” routes and server config
β”œβ”€β”€ demucs_runner.py   # Demucs logic β€” takes a file path, returns output path
└── uploads/           # Temp folder for uploaded files
    └── .gitkeep
```

---

## How to build it

### 1. Create `backend/demucs_runner.py`

This file has one job: take a file path, run Demucs, return the path to `vocals.wav`.

```python
import subprocess
import os

def run_demucs(input_path: str) -> str:
    subprocess.run([
        "demucs", "--two-stems=vocals", "-n", "mdx_extra", input_path
    ], check=True)

    filename = os.path.splitext(os.path.basename(input_path))[0]
    output_path = f"separated/mdx_extra/{filename}/vocals.wav"
    return output_path
```

### 2. Create `backend/main.py`

Two endpoints:
- `POST /upload` β€” accepts audio file, runs Demucs, returns download URL
- `GET /download/{filename}` β€” serves the processed `.wav` file

```python
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
import shutil, os, uuid
from backend.demucs_runner import run_demucs

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

UPLOAD_DIR = "backend/uploads"

@app.post("/upload")
async def upload_audio(file: UploadFile = File(...)):
    ext = os.path.splitext(file.filename)[1]
    unique_name = f"{uuid.uuid4()}{ext}"
    save_path = os.path.join(UPLOAD_DIR, unique_name)

    with open(save_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)

    output_path = run_demucs(save_path)
    filename = os.path.basename(output_path)

    return {"download_url": f"/download/{filename}", "status": "done"}

@app.get("/download/{filename}")
def download_audio(filename: str):
    file_path = f"separated/mdx_extra/{filename}/vocals.wav"
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="File not found")
    return FileResponse(file_path, media_type="audio/wav")
```

### 3. Run the server

```bash
source venv/bin/activate
uvicorn backend.main:app --reload
```

Server runs at: `http://localhost:8000`

---

## Test it manually

```bash
curl -X POST http://localhost:8000/upload \
  -F "file=@mp3/Recording 1.mp3"
```

Expected response:
```json
{"download_url": "/download/vocals.wav", "status": "done"}
```

Then open `http://localhost:8000/download/vocals.wav` in the browser to download the file.

---

## Notes

- `uuid4()` on the filename prevents collisions if two people upload at the same time
- CORS is open (`*`) for now β€” fine for a demo, tighten it before production
- No file size limit set yet β€” add one later if needed
- Uploaded files in `backend/uploads/` are not cleaned up automatically β€” add a cleanup step later