voice-isolation-live / docs /step-2-fastapi-backend.md
TonyLikeDev's picture
initial commit
0f623ae
|
Raw
History Blame Contribute Delete
3.19 kB
# 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