SSS18 commited on
Commit
1fb7ec6
·
verified ·
1 Parent(s): d85d8b2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +221 -0
app.py CHANGED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from flask_cors import CORS
3
+ from deepface import DeepFace
4
+ import base64
5
+ import io
6
+ from PIL import Image
7
+ import numpy as np
8
+ import logging
9
+ import traceback
10
+ import os
11
+ import spotipy
12
+ from spotipy.oauth2 import SpotifyClientCredentials
13
+
14
+ # Suppress TensorFlow warnings
15
+ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
16
+ os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
17
+
18
+ # Configure logging
19
+ logging.basicConfig(
20
+ level=logging.INFO,
21
+ format='%(asctime)s - %(levelname)s - %(message)s'
22
+ )
23
+ logger = logging.getLogger(_name_)
24
+
25
+ app = Flask(_name_)
26
+ CORS(app)
27
+
28
+ # Initialize Spotify
29
+ try:
30
+ # Set your Spotify credentials here or use environment variables
31
+ SPOTIFY_CLIENT_ID = os.getenv('SPOTIFY_CLIENT_ID', 'your_client_id_here')
32
+ SPOTIFY_CLIENT_SECRET = os.getenv('SPOTIFY_CLIENT_SECRET', 'your_client_secret_here')
33
+
34
+ client_credentials_manager = SpotifyClientCredentials(
35
+ client_id=SPOTIFY_CLIENT_ID,
36
+ client_secret=SPOTIFY_CLIENT_SECRET
37
+ )
38
+ spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
39
+ logger.info("Spotify API initialized successfully")
40
+ except Exception as e:
41
+ logger.error(f"Failed to initialize Spotify API: {str(e)}")
42
+ spotify = None
43
+
44
+ # Emotion to Spotify search queries
45
+ EMOTION_TO_MOOD = {
46
+ 'happy': ['happy hits', 'feel good', 'party music', 'upbeat pop'],
47
+ 'sad': ['sad songs', 'emotional ballads', 'melancholic', 'rainy day'],
48
+ 'angry': ['workout motivation', 'rock anthems', 'intense metal', 'aggressive'],
49
+ 'neutral': ['chill vibes', 'focus music', 'ambient', 'lo-fi beats'],
50
+ 'surprise': ['party hits', 'dance pop', 'exciting', 'upbeat'],
51
+ 'fear': ['calming music', 'meditation', 'peaceful', 'relaxation'],
52
+ 'disgust': ['energizing', 'workout', 'rock music', 'alternative']
53
+ }
54
+
55
+ @app.route('/', methods=['GET'])
56
+ def home():
57
+ return jsonify({
58
+ "message": "Emotion Detection + Music Recommendation API",
59
+ "endpoints": {
60
+ "/emotion": "POST - Detect emotion from image",
61
+ "/health": "GET - Health check"
62
+ },
63
+ "music_provider": "Spotify"
64
+ })
65
+
66
+ @app.route('/health', methods=['GET'])
67
+ def health():
68
+ return jsonify({
69
+ "status": "healthy",
70
+ "spotify_available": spotify is not None
71
+ }), 200
72
+
73
+ @app.route('/emotion', methods=['POST', 'OPTIONS'])
74
+ def detect_emotion():
75
+ if request.method == 'OPTIONS':
76
+ return jsonify({}), 200
77
+
78
+ try:
79
+ logger.info("Received emotion detection request")
80
+
81
+ data = request.get_json()
82
+
83
+ if not data or 'image' not in data:
84
+ logger.error("No image data in request")
85
+ return jsonify({
86
+ "success": False,
87
+ "error": "No image data provided"
88
+ }), 400
89
+
90
+ image_data = data['image']
91
+ logger.info(f"Received image data, length: {len(image_data)}")
92
+
93
+ if ',' in image_data:
94
+ image_data = image_data.split(',')[1]
95
+
96
+ try:
97
+ image_bytes = base64.b64decode(image_data)
98
+ logger.info(f"Decoded image bytes: {len(image_bytes)} bytes")
99
+ except Exception as e:
100
+ logger.error(f"Base64 decode error: {str(e)}")
101
+ return jsonify({
102
+ "success": False,
103
+ "error": "Invalid base64 image data"
104
+ }), 400
105
+
106
+ try:
107
+ image = Image.open(io.BytesIO(image_bytes))
108
+ logger.info(f"Image opened - Format: {image.format}, Size: {image.size}, Mode: {image.mode}")
109
+ except Exception as e:
110
+ logger.error(f"PIL image open error: {str(e)}")
111
+ return jsonify({
112
+ "success": False,
113
+ "error": "Invalid image format"
114
+ }), 400
115
+
116
+ if image.mode != 'RGB':
117
+ logger.info(f"Converting image from {image.mode} to RGB")
118
+ image = image.convert('RGB')
119
+
120
+ img_array = np.array(image)
121
+ logger.info(f"Numpy array shape: {img_array.shape}, dtype: {img_array.dtype}")
122
+
123
+ try:
124
+ logger.info("Starting DeepFace analysis...")
125
+ result = DeepFace.analyze(
126
+ img_array,
127
+ actions=['emotion'],
128
+ enforce_detection=False,
129
+ silent=True,
130
+ detector_backend='opencv'
131
+ )
132
+ logger.info("DeepFace analysis completed successfully")
133
+ except Exception as e:
134
+ logger.error(f"DeepFace analysis error: {str(e)}")
135
+ logger.error(traceback.format_exc())
136
+ return jsonify({
137
+ "success": False,
138
+ "error": f"Emotion detection failed: {str(e)}"
139
+ }), 500
140
+
141
+ if isinstance(result, list):
142
+ result = result[0]
143
+
144
+ dominant_emotion = result['dominant_emotion']
145
+ emotion_scores = result['emotion']
146
+
147
+ emotion_scores_serializable = {
148
+ emotion: float(score) for emotion, score in emotion_scores.items()
149
+ }
150
+
151
+ logger.info(f"Dominant emotion: {dominant_emotion}")
152
+
153
+ music_recommendations = []
154
+ if spotify:
155
+ try:
156
+ music_recommendations = get_music_from_spotify(dominant_emotion)
157
+ logger.info(f"Found {len(music_recommendations)} music recommendations")
158
+ except Exception as e:
159
+ logger.warning(f"Failed to get music recommendations: {str(e)}")
160
+
161
+ return jsonify({
162
+ "success": True,
163
+ "dominant_emotion": dominant_emotion,
164
+ "all_emotions": emotion_scores_serializable,
165
+ "confidence": float(emotion_scores[dominant_emotion]),
166
+ "music_recommendations": music_recommendations,
167
+ "suggested_moods": EMOTION_TO_MOOD.get(dominant_emotion, [])
168
+ })
169
+
170
+ except Exception as e:
171
+ logger.error(f"Unexpected error: {str(e)}")
172
+ logger.error(traceback.format_exc())
173
+ return jsonify({
174
+ "success": False,
175
+ "error": f"Internal server error: {str(e)}"
176
+ }), 500
177
+
178
+ def get_music_from_spotify(emotion):
179
+ """Get music playlists from Spotify based on emotion"""
180
+ try:
181
+ mood_keywords = EMOTION_TO_MOOD.get(emotion, ['chill'])
182
+ recommendations = []
183
+
184
+ for keyword in mood_keywords[:3]:
185
+ try:
186
+ results = spotify.search(q=keyword, type='playlist', limit=3)
187
+
188
+ for playlist in results['playlists']['items']:
189
+ if playlist:
190
+ # Get playlist image
191
+ thumbnail = ''
192
+ if playlist.get('images') and len(playlist['images']) > 0:
193
+ thumbnail = playlist['images'][0]['url']
194
+
195
+ recommendations.append({
196
+ 'title': playlist.get('name', ''),
197
+ 'playlist_id': playlist.get('id', ''),
198
+ 'playlist_url': playlist.get('external_urls', {}).get('spotify', ''),
199
+ 'thumbnail': thumbnail,
200
+ 'author': playlist.get('owner', {}).get('display_name', 'Spotify'),
201
+ 'item_count': playlist.get('tracks', {}).get('total', 0),
202
+ 'mood': keyword,
203
+ 'provider': 'spotify'
204
+ })
205
+
206
+ if len(recommendations) >= 6:
207
+ break
208
+
209
+ except Exception as e:
210
+ logger.warning(f"Search failed for keyword '{keyword}': {str(e)}")
211
+ continue
212
+
213
+ return recommendations[:6]
214
+
215
+ except Exception as e:
216
+ logger.error(f"Error getting music recommendations: {str(e)}")
217
+ return []
218
+
219
+ if _name_ == '_main_':
220
+ logger.info("Starting Emotion Detection + Music Recommendation API on port 7860...")
221
+ app.run(host='0.0.0.0', port=7860, debug=False)