Zurya commited on
Commit
462f236
·
verified ·
1 Parent(s): 8a3fbf6

Upload main.py

Browse files
Files changed (1) hide show
  1. main.py +105 -0
main.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import tempfile
4
+ import numpy as np
5
+ import librosa
6
+ from fastapi import FastAPI, File, UploadFile
7
+ from fastapi.responses import JSONResponse
8
+ import tensorflow as tf
9
+
10
+ app = FastAPI(title="AI Music Mood Categorizer")
11
+
12
+ # 1. Define the 8 target moods matching our Flutter app
13
+ MOODS = ["gym", "travel", "chill", "sleep", "love", "sad", "party", "study"]
14
+
15
+ # 2. Load your TensorFlow Model (Placeholder)
16
+ # In production, you would uncomment this and load your trained model:
17
+ # model = tf.keras.models.load_model("mood_classifier.h5")
18
+
19
+ def extract_features(audio_path):
20
+ """
21
+ Extracts audio features using librosa.
22
+ This takes the 15-second audio chunk sent by the Flutter app.
23
+ """
24
+ # Load audio with librosa
25
+ # sr=22050 is the default sample rate.
26
+ y, sr = librosa.load(audio_path, sr=22050)
27
+
28
+ # Extract features
29
+ # MFCCs (Mel-frequency cepstral coefficients) describe the 'shape' of the sound
30
+ mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
31
+ mfcc_mean = np.mean(mfcc.T, axis=0)
32
+
33
+ # Chroma measures pitch/harmonic content (useful for 'sad' vs 'happy' chords)
34
+ chroma = librosa.feature.chroma_stft(y=y, sr=sr)
35
+ chroma_mean = np.mean(chroma.T, axis=0)
36
+
37
+ # Spectral contrast (useful for distinguishing energetic music)
38
+ contrast = librosa.feature.spectral_contrast(y=y, sr=sr)
39
+ contrast_mean = np.mean(contrast.T, axis=0)
40
+
41
+ # Tempo (BPM)
42
+ tempo, _ = librosa.beat.beat_track(y=y, sr=sr)
43
+
44
+ # Combine all features into a single numpy array
45
+ # This is what your ML model will take as input for prediction
46
+ features = np.hstack([mfcc_mean, chroma_mean, contrast_mean, tempo])
47
+ return features, tempo[0]
48
+
49
+ @app.post("/analyze")
50
+ async def analyze_audio(file: UploadFile = File(...)):
51
+ """
52
+ Endpoint that receives the 15s audio chunk from Flutter,
53
+ extracts features, runs the AI model, and returns the mood.
54
+ """
55
+ try:
56
+ # 1. Save the uploaded audio chunk to a temporary file
57
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio:
58
+ content = await file.read()
59
+ temp_audio.write(content)
60
+ temp_audio_path = temp_audio.name
61
+
62
+ # 2. Extract AI Features using Librosa
63
+ features, bpm = extract_features(temp_audio_path)
64
+
65
+ # 3. Predict Mood using TensorFlow (Mock logic)
66
+ # In production, you would run:
67
+ # prediction = model.predict(np.array([features]))
68
+ # predicted_index = np.argmax(prediction)
69
+ # predicted_mood = MOODS[predicted_index]
70
+
71
+ # --- MOCK HEURISTIC FOR TESTING ---
72
+ # Since you haven't trained the TFLite/TF model yet,
73
+ # this heuristic uses the BPM (tempo) to mock a prediction
74
+ # so you can test the Flutter app immediately!
75
+ predicted_mood = "chill"
76
+ if bpm > 140:
77
+ predicted_mood = "gym" # Aggressive, fast
78
+ elif bpm > 120:
79
+ predicted_mood = "party" # Upbeat
80
+ elif bpm > 100:
81
+ predicted_mood = "travel" # Moving
82
+ elif bpm < 70:
83
+ predicted_mood = "sleep" # Very slow, ambient
84
+ elif bpm < 90:
85
+ predicted_mood = "sad" # Slow, melancholic
86
+ # ----------------------------------
87
+
88
+ # Clean up temp file
89
+ os.remove(temp_audio_path)
90
+
91
+ return JSONResponse(content={
92
+ "mood": predicted_mood,
93
+ "bpm": float(bpm),
94
+ "status": "success"
95
+ })
96
+
97
+ except Exception as e:
98
+ return JSONResponse(
99
+ status_code=500,
100
+ content={"status": "error", "message": str(e)}
101
+ )
102
+
103
+ # To run this server locally for testing:
104
+ # pip install -r requirements.txt
105
+ # uvicorn main:app --host 0.0.0.0 --port 8000