Skip to content

sp-mujuni/Hz

Repository files navigation

Moodra - Audio Emotion Analyzer

Moodra is a Python-based music mood detection app that analyzes an uploaded audio file and predicts the most likely emotion label for the clip. It combines a Flask web app, a PyTorch classifier, and Librosa-based audio feature extraction to turn a song snippet into a mood prediction plus feature-level analysis.

The repository also includes utilities for preparing training data, retraining the model, and validating that the packaged artifacts load correctly. In practice, this project is organized around three flows:

  1. Run the web app and upload audio for prediction.
  2. Prepare and retrain the model from labeled WAV files.
  3. Verify the model, encoder, and import paths before deployment.

What the app does

The main Flask app accepts an audio file on the /predict endpoint, saves it under static/uploads/, calls the prediction pipeline, and returns JSON containing:

  • the predicted mood
  • prediction confidence
  • a probability breakdown for every known label
  • derived audio features such as tempo, key, energy, valence, spectral centroid, spectral rolloff, and zero-crossing rate
  • a small set of recommended track placeholders derived from the predicted mood

The browser UI in templates/homepage.html is a single-page upload experience that lets users add multiple audio files, play previews, and analyze each file individually or in bulk.

Project structure

.
|-- app.py                      # Flask web app and /predict endpoint
|-- predict_mood.py             # Model loading, feature extraction, prediction
|-- music_mood_therapy_prototype.py  # Dataset, classifier, and training loop
|-- retrain_model.py            # Retrain the classifier from data/metadata.csv
|-- convert_mp3_to_wav.py       # Convert MP3 training audio to WAV and generate metadata
|-- debug_app.py                # Local debugging helper for import/path checks
|-- sanity-check.py             # Lightweight environment sanity checks
|-- test_imports.py             # Import verification script
|-- test_model_loading.py       # Validates model.pth and label_encoder.pkl loading
|-- test_paths.py               # Confirms absolute path resolution for artifacts
|-- FIX_502_ERROR.md            # Notes for troubleshooting Python/runtime startup issues
|-- Procfile                    # Gunicorn entrypoint for hosted environments
|-- requirements.txt            # Python dependencies
|-- model.pth                   # Trained PyTorch model weights
|-- label_encoder.pkl           # Saved label encoder for class mapping
|-- data/
|   |-- metadata.csv            # Training metadata: file_path,mood
|   |-- mp3audio/               # Source MP3 training files
|   `-- wavaudio/               # Converted WAV training files
|-- static/
|   `-- uploads/                # Uploaded audio files for prediction
`-- templates/
	`-- homepage.html           # Frontend UI

How it works

Prediction pipeline

  1. The user uploads an audio file in the browser.
  2. Flask stores the file in static/uploads/.
  3. predict_mood.py loads model.pth and label_encoder.pkl with a cached artifact loader.
  4. The file is converted into MFCC features via extract_features() in music_mood_therapy_prototype.py.
  5. The classifier returns a label distribution and the top prediction.
  6. Additional descriptive audio features are extracted with Librosa and returned alongside the prediction.

Model architecture

The classifier is a small feed-forward neural network defined in music_mood_therapy_prototype.py:

  • input layer: 40 MFCC features
  • hidden layer 1: 128 units with ReLU and dropout
  • hidden layer 2: 64 units with ReLU
  • output layer: one neuron per emotion class

The current artifact loader in predict_mood.py is defensive: it checks the saved encoder first, then the checkpoint, and can partially load the model if the final layer size does not match exactly.

Audio features used

The app combines two views of the input audio:

  • MFCC features for the classifier input
  • analysis metrics for display and debugging

The analysis metrics currently include tempo, key, energy, valence, spectral centroid, spectral rolloff, and zero-crossing rate.

Supported labels

The training set currently contains these mood labels:

  • Angry
  • Calm
  • Happy
  • Romantic
  • Sad
  • Zoned

If you retrain the model with a different label set, the saved label_encoder.pkl becomes the source of truth for label ordering.

Requirements

The project targets Python 3 and depends on the packages listed in requirements.txt, including:

  • Flask
  • PyTorch and Torchaudio
  • Librosa
  • NumPy, Pandas, SciPy
  • scikit-learn
  • Pydub
  • Gunicorn for hosted deployment

Setup

1. Create and activate a virtual environment

cd C:\External_Files\GitHub\Hz
py -3.11 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip

2. Install dependencies

pip install -r requirements.txt

3. Confirm the model artifacts are present

The app expects these files in the repository root:

  • model.pth
  • label_encoder.pkl

If either file is missing, prediction will fail until the model is retrained or the artifact is restored.

Run the app locally

Start the Flask server with:

python app.py

Then open the local Flask address printed in the terminal, usually http://127.0.0.1:5000/.

The browser UI lets you:

  • choose audio files through a file picker
  • drag and drop audio into the upload zone
  • preview the uploaded audio before analysis
  • analyze one file or all files in the queue
  • see the predicted mood and supporting probabilities

API usage

POST /predict

Send multipart form data with an audio field.

Example using curl:

curl -X POST http://127.0.0.1:5000/predict \
	-F "audio=@path/to/song.wav"

Success response fields include:

  • success
  • mood
  • confidence
  • probabilities
  • details
  • audio_url

If no file is provided, the endpoint returns a 400 error. If prediction fails, the app returns a 500 error with a helpful message and, in debug mode, a traceback.

Retraining the model

Use retrain_model.py when you have updated labeled training data in data/metadata.csv.

python retrain_model.py

This script:

  • loads the dataset from data/metadata.csv
  • builds a MusicDataset
  • trains a MoodClassifier
  • saves updated artifacts to model.pth and label_encoder.pkl
  • prints a quick prediction sanity check after training

The default training loop in music_mood_therapy_prototype.py uses CrossEntropyLoss and Adam with a learning rate of 0.001.

Preparing training audio

convert_mp3_to_wav.py is a helper for turning MP3 source audio into WAV files and generating metadata.

It:

  • scans a source directory for MP3 files
  • converts each file to WAV with pydub
  • infers a mood label from the filename when possible
  • writes data/metadata.csv in the format expected by the dataset loader

The script is intended as a dataset preparation utility. In the current repository, the source files live under data/mp3audio/ and the converted WAV files live under data/wavaudio/.

Testing and validation

The repository includes a few lightweight validation scripts:

  • python test_imports.py checks that the major dependencies and internal modules import correctly.
  • python test_model_loading.py verifies that model.pth and label_encoder.pkl can be loaded.
  • python test_paths.py prints the resolved artifact locations for path debugging.
  • python sanity-check.py is a lightweight environment check.

These scripts are useful before deploying or after changing environments because the app depends on a working Python stack, valid model artifacts, and correct file paths.

Deployment

The repository includes a Procfile configured for Gunicorn:

web: gunicorn app:app

That means the app can be deployed to a hosting platform that understands Procfiles and runs a WSGI app. Before deployment, make sure:

  • requirements.txt is installed cleanly
  • model.pth and label_encoder.pkl are included in the deployed package
  • the runtime can write to static/uploads/

Troubleshooting

Model file or encoder missing

If prediction fails with a missing artifact error, check that model.pth and label_encoder.pkl are in the repo root. predict_mood.py searches multiple locations, but the root directory is the expected default.

Upload path issues

The Flask app resolves static/uploads/ relative to app.py and creates the directory if needed. If uploads fail in a hosted environment, verify the process has write permissions.

Python startup or 502 errors

FIX_502_ERROR.md documents a known class of environment problems where Python itself is broken or partially corrupted. If Flask crashes before requests reach /predict, follow the cleanup and virtual environment guidance in that file.

Dependency or import failures

If the app stops importing correctly after environment changes, run test_imports.py first. It is the fastest way to identify a broken package installation.

Notes for contributors

  • Keep metadata.csv aligned with the actual labels used to train the model.
  • Update label_encoder.pkl whenever the label set changes.
  • Do not assume the saved classifier output size is fixed; predict_mood.py already handles some checkpoint/encoder mismatches.
  • Treat static/uploads/ as a runtime scratch directory, not as source data.

About

Analyze emotion portrayed in music

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages