Spaces:
Sleeping
Sleeping
| 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() | |
| 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) | |
| def root(): | |
| return {"message": "TrueTrace FastAPI backend is running!"} | |