Spaces:
Sleeping
Sleeping
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
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.
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 URLGET /download/{filename}β serves the processed.wavfile
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
source venv/bin/activate
uvicorn backend.main:app --reload
Server runs at: http://localhost:8000
Test it manually
curl -X POST http://localhost:8000/upload \
-F "file=@mp3/Recording 1.mp3"
Expected response:
{"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