AetherTune is a context-aware music recommendation system that analyzes your current mood, activity, and real-time listening context to decide whether what you're playing right now is the right fit — and if not, suggests better alternatives instantly.
Unlike traditional platforms that rely on listening history, AetherTune focuses on what you need right now: evaluating your currently playing Spotify track against your activity using a trained machine learning model, then recommending replacements when the vibe doesn't match.
Modern music platforms are reactive, not intelligent:
- Recommendations are driven by past behaviour, not present context
- Users waste time scrolling to find the right music for their mood
- No platform truly understands what you're doing right now
Users often don't know what they want to listen to — they just know the current song isn't working.
AetherTune introduces moment-based personalization through three pillars:
| Pillar | Description |
|---|---|
| Mood-Aware | Evaluates audio features (valence, energy, acousticness) against your emotional state |
| Activity-Driven | Tailors recommendations to studying, driving, meditating, or exercising |
| Adaptive Learning | Adjusts its tolerance thresholds over time based on your feedback |
User selects Activity + Age
↓
Spotify API fetches currently playing track
↓
ML Model evaluates audio features against activity profile
↓
Dynamic Threshold check (sigmoid + feedback decay)
↓
┌─────────────────────────────────┐
│ Match? → "Song is suitable" │
│ No match? → 5 Recommendations│
└─────────────────────────────────┘
↓
User submits feedback → Threshold adapts over time
AetherTune doesn't use a fixed confidence cutoff. Instead, it computes a sigmoid-based dynamic threshold by age group, then adjusts it through a time-decaying feedback loop:
- More feedback = more personalised threshold
- Inactivity causes gradual decay back to the base — keeping the model fresh
- Adjustments are capped at ±0.2 to prevent drift
AetherTune/
├── main.py # FastAPI app — /predict and /feedback endpoints
├── auth.py # Spotify OAuth2 login & callback
├── spotify_service.py # Fetches currently playing track + audio features
├── recommendation.py # Activity-based Spotify track search
├── ml_model.py # Model training script (Random Forest)
├── database.py # SQLite schema — feedback & tolerance tables
├── models/
│ ├── activity_model.pkl # Trained MultiOutputClassifier
│ └── scaler.pkl # StandardScaler for feature normalisation
├── data/
│ ├── spotify_dataset.csv # Raw Spotify audio features dataset
│ └── spotify_dataset_labeled.csv # Labelled dataset with activity targets
├── static/
│ ├── logo.png
│ └── style.css
└── templates/
└── index.html # Jinja2 web frontend
| Property | Value |
|---|---|
| Model | MultiOutputClassifier wrapping RandomForestClassifier |
| Labels | studying, driving, meditating, exercising |
| Features | danceability, energy, loudness, speechiness, acousticness, instrumentalness, liveness, valence, tempo, age |
| Scaler | StandardScaler |
| Train/Test Split | 80 / 20 |
Label generation logic (rule-based for training):
studying → energy < 0.6 AND speechiness < 0.4
driving → energy > 0.5 AND tempo > 90
meditating → acousticness > 0.6 AND energy < 0.4
exercising → energy > 0.7 AND tempo > 120- Python 3.10+
- A Spotify Developer Account with a registered app
git clone https://github.com/your-username/AetherTune.git
cd AetherTunepip install -r requirements.txtCreate a .env file in the project root:
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secretNever commit your
.envfile. Add it to.gitignore.
The pre-trained model is already included in models/. To retrain:
python ml_model.pyuvicorn main:app --reloadVisit http://127.0.0.1:8000 in your browser.
Redirects to Spotify's OAuth2 authorization page.
Handles the OAuth2 callback and initialises the Spotify client.
Analyses the currently playing track and returns a suitability verdict.
Activity codes:
| Code | Activity |
|---|---|
0 |
Studying |
1 |
Driving |
2 |
Meditating |
3 |
Exercising |
Example response (suitable):
{
"Current_Track": {
"name": "Lo-Fi Chill",
"artist": "ChillHop Music",
"cover": "https://...",
"duration": 210000,
"progress": 45000,
"spotify_url": "https://open.spotify.com/track/..."
},
"message": "Song is suitable for studying ✅"
}Example response (not suitable):
{
"Current_Track": { ... },
"ALERT": "Song is NOT suitable for studying ❌",
"Recommended_Tracks": [
{ "name": "...", "artist": "...", "id": "...", "url": "..." }
]
}Submits user feedback to personalise the tolerance threshold.
| Layer | Technology |
|---|---|
| Backend | FastAPI, Uvicorn |
| ML | Scikit-learn (Random Forest, MultiOutputClassifier) |
| Data | Pandas, NumPy |
| Spotify Integration | Spotipy |
| Database | SQLite |
| Frontend | Jinja2 Templates, HTML/CSS |
| Auth | Spotify OAuth2 (via Spotipy) |
- Spotify OAuth2 integration
- Real-time track evaluation via ML model
- Activity-based recommendation fallback
- Adaptive feedback loop with time decay
- Replace simulated audio features with Spotify's live Audio Features API
- User accounts and persistent profiles
- Browser extension for passive, always-on context detection
- Mood inference from time-of-day and calendar context
- Expand to Apple Music and YouTube Music
| Name | Role |
|---|---|
| Riddhi Mishra | Co-creator |
| Ishan Gupta | Co-creator |
| Abhijeet Kumar | Co-creator |
| Yadvendra Tripathi | Co-creator |
| Avishi Sinha | Co-creator |
- Audio features in
spotify_service.pyare currently simulated withrandom.uniform. Replace with a live call to Spotify's Audio Features endpoint for production use. - The
spotify_clientinauth.pyis stored in memory (global variable). For a production deployment, use a proper session or token store (e.g., Redis).
This project is licensed under the MIT License.
