Agrannya's picture
Update app.py
5d9400b verified
from fastapi import FastAPI, File, UploadFile, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import os
import shutil
import librosa
import numpy as np
from spotipy import Spotify
from spotipy.oauth2 import SpotifyClientCredentials
app = FastAPI()
# CORS for frontend integration
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # For production, restrict to your frontend URL
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Spotify API client initialization from environment variables (set as HF Secrets)
client_id = os.getenv('SPOTIPY_CLIENT_ID')
client_secret = os.getenv('SPOTIPY_CLIENT_SECRET')
if not client_id or not client_secret:
raise RuntimeError("Spotify API credentials not found in environment variables")
sp = Spotify(client_credentials_manager=SpotifyClientCredentials(client_id=client_id, client_secret=client_secret))
def extract_fingerprint(audio_path: str):
"""Extracts a simple MFCC-based fingerprint from the audio file."""
y, sr = librosa.load(audio_path, sr=22050, mono=True)
mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
fingerprint = np.mean(mfcc, axis=1)
return fingerprint.tolist()
@app.api_route("/recognize", methods=["GET", "POST"])
async def recognize(request: Request, file: UploadFile = File(None)):
if request.method == "GET":
return JSONResponse(
{"message": "Send a POST request with an audio file (field name: 'file') to recognize a song."}
)
# POST logic:
# Use fallback demo.mp3 if no file uploaded
if file is None or file.filename == "":
audio_path = "demo.mp3"
if not os.path.exists(audio_path):
return JSONResponse({"error": "No file uploaded and demo.mp3 not found"}, status_code=400)
else:
audio_path = f"temp_{file.filename}"
with open(audio_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
try:
fingerprint = extract_fingerprint(audio_path)
except Exception as e:
if audio_path.startswith("temp_") and os.path.exists(audio_path):
os.remove(audio_path)
return JSONResponse({"error": f"Audio processing failed: {str(e)}"}, status_code=500)
# For demo: search Spotify for a fixed song
try:
results = sp.search(q='Shape of You', type='track', limit=1)
if results['tracks']['items']:
track = results['tracks']['items'][0]
response = {
'title': track['name'],
'artist': track['artists'][0]['name'],
'album': track['album']['name'],
'cover_url': track['album']['images'][0]['url'],
'preview_url': track['preview_url']
}
else:
response = {'error': 'No match found'}
except Exception as e:
response = {'error': f'Spotify API error: {str(e)}'}
if audio_path.startswith("temp_") and os.path.exists(audio_path):
os.remove(audio_path)
return JSONResponse(content=response)
@app.get("/")
def root():
return {"message": "TrueTrace FastAPI backend is running!"}