music-player / README.md
prasanth.thangavel
Improve documentation
8b2a9bc
metadata
title: Music Player
emoji: πŸ’»
colorFrom: indigo
colorTo: blue
sdk: docker
pinned: false
license: mit
short_description: My personal music player

Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference

Music Player with Supabase Integration

A modern music player with persistent playlist storage using Supabase client API.

Features

  • 🎡 Play local audio files (MP3, WAV)
  • 🎚️ Advanced playback controls
  • πŸ“ Create and manage playlists
  • πŸ”„ Loop and shuffle functionality
  • βž• Queue songs to play next and reorder them
  • πŸ“€ Upload new songs to the music library
  • πŸ’Ύ Persistent storage with Supabase
  • πŸ“± Responsive design
  • 🎨 Modern UI with Material Design
  • πŸ” Secure API-based storage

Setup Instructions

1. Supabase Project Setup

  1. Create a free account at Supabase
  2. Create a new project
  3. Go to Settings β†’ API and copy your credentials:
    • Project URL (starts with https://)
    • service_role [secret] key (starts with eyJ...)

2. Database Schema

Run this SQL in your Supabase SQL Editor to create the required tables:

-- Create playlists table
CREATE TABLE playlists (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create playlist_songs table
CREATE TABLE playlist_songs (
    id SERIAL PRIMARY KEY,
    playlist_id INTEGER REFERENCES playlists(id) ON DELETE CASCADE,
    song_name VARCHAR(500) NOT NULL,
    song_order INTEGER DEFAULT 0,
    added_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Create user_preferences table
CREATE TABLE user_preferences (
    id SERIAL PRIMARY KEY,
    preference_key VARCHAR(100) UNIQUE NOT NULL,
    preference_value TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Insert default preferences
INSERT INTO user_preferences (preference_key, preference_value) VALUES 
('is_looping', 'false'),
('is_shuffling', 'false'),
('volume', '1.0'),
('current_playlist', 'all')
ON CONFLICT (preference_key) DO NOTHING;

3. Environment Variables

Set these environment variables in your Hugging Face Space settings:

  • SUPABASE_URL: Your Supabase project URL
  • SUPABASE_KEY: Your Supabase anon public key

4. Local Development

  1. Clone the repository
  2. Install dependencies: pip install -r requirements.txt
  3. Create a .env file:
    SUPABASE_URL=your_supabase_project_url
    SUPABASE_KEY=your_supabase_anon_key
    FLASK_ENV=development
    
  4. Run the application: python app.py

5. Testing

Test your Supabase connection:

python test_supabase_client.py

6. Docker Deployment

# Build and run locally
docker build -t musicplayer .
docker run -p 7860:7860 -e SUPABASE_URL=your_url -e SUPABASE_KEY=your_key musicplayer

# Or use docker-compose
docker-compose up --build

API Endpoints

  • GET /api/playlists - Get all playlists
  • POST /api/playlists - Create a new playlist
  • GET /api/playlists/<id>/songs - Get songs in a playlist
  • DELETE /api/playlists/<id> - Delete a playlist
  • GET /api/preferences/<key> - Get user preference
  • POST /api/preferences/<key> - Set user preference

Architecture

This application uses:

  • Flask for the web server
  • Supabase Client for database operations
  • JavaScript for frontend functionality
  • Docker for containerization

System Architecture Diagram

graph TB
    subgraph "Frontend Layer"
        UI[🎡 Web Interface<br/>HTML/CSS/JavaScript]
        Player[🎧 Audio Player<br/>HTML5 Audio API]
        FileUpload[πŸ“€ File Upload<br/>Drag & Drop]
    end
    
    subgraph "Backend Layer"
        Flask[🐍 Flask Server<br/>Port 7860]
        API[πŸ”— REST API<br/>Endpoints]
        FileHandler[πŸ“ File Handler<br/>Upload Management]
        Logger[πŸ“‹ Logging System<br/>app.log]
    end
    
    subgraph "Database Layer"
        Supabase[πŸ—„οΈ Supabase Database<br/>PostgreSQL]
        PlaylistsTable[(πŸ“‹ playlists<br/>id, name, timestamps)]
        SongsTable[(🎡 playlist_songs<br/>id, playlist_id, song_name, order)]
        PrefsTable[(βš™οΈ user_preferences<br/>key, value, timestamps)]
    end
    
    subgraph "Storage Layer"
        AudioFiles[🎡 Audio Files<br/>static/audio/]
        StaticFiles[πŸ“‚ Static Assets<br/>CSS, JS, Images]
    end
    
    subgraph "Deployment Layer"
        Docker[🐳 Docker Container<br/>Containerized App]
        HF[πŸ€— Hugging Face Space<br/>Cloud Deployment]
    end
    
    subgraph "API Endpoints"
        GET_Playlists[GET /api/playlists]
        POST_Playlists[POST /api/playlists]
        GET_Songs[GET /api/playlists/:id/songs]
        DELETE_Playlist[DELETE /api/playlists/:id]
        GET_Prefs[GET /api/preferences/:key]
        POST_Prefs[POST /api/preferences/:key]
        POST_Upload[POST /api/upload]
        GET_Debug[GET /api/debug/logs]
    end
    
    %% Frontend to Backend
    UI -->|HTTP Requests| Flask
    Player -->|Play Audio| AudioFiles
    FileUpload -->|Upload Files| FileHandler
    
    %% Backend Internal
    Flask --> API
    API --> FileHandler
    Flask --> Logger
    
    %% API to Database
    GET_Playlists --> PlaylistsTable
    POST_Playlists --> PlaylistsTable
    GET_Songs --> SongsTable
    DELETE_Playlist --> PlaylistsTable
    GET_Prefs --> PrefsTable
    POST_Prefs --> PrefsTable
    POST_Upload --> AudioFiles
    GET_Debug --> Logger
    
    %% Database Connections
    API -->|Supabase Client| Supabase
    Supabase --> PlaylistsTable
    Supabase --> SongsTable
    Supabase --> PrefsTable
    
    %% File System
    FileHandler --> AudioFiles
    Flask --> StaticFiles
    
    %% Deployment
    Flask --> Docker
    Docker --> HF
    
    %% Styling
    classDef frontend fill:#e1f5fe,stroke:#01579b,stroke-width:2px,color:#000000
    classDef backend fill:#f3e5f5,stroke:#4a148c,stroke-width:2px,color:#000000
    classDef database fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px,color:#000000
    classDef storage fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#000000
    classDef deployment fill:#fce4ec,stroke:#880e4f,stroke-width:2px,color:#000000
    classDef api fill:#fff8e1,stroke:#f57f17,stroke-width:2px,color:#000000
    
    class UI,Player,FileUpload frontend
    class Flask,API,FileHandler,Logger backend
    class Supabase,PlaylistsTable,SongsTable,PrefsTable database
    class AudioFiles,StaticFiles storage
    class Docker,HF deployment
    class GET_Playlists,POST_Playlists,GET_Songs,DELETE_Playlist,GET_Prefs,POST_Prefs,POST_Upload,GET_Debug api

Data Flow

  1. User Interaction: User interacts with the web interface to play music, create playlists, upload files
  2. API Communication: Frontend sends HTTP requests to Flask backend API endpoints
  3. Database Operations: Backend performs CRUD operations on Supabase PostgreSQL database
  4. File Management: Audio files are stored locally and served through Flask static file handling
  5. Persistence: User preferences and playlist data are stored in Supabase for persistence across sessions

Todo

Testing

  • Test docker locally for faster iterative testing.
    docker build -t musicplayer .
    docker run -p 7860:7860 musicplayer
    

Enhancements

Completed

  • Add persistent storage with Supabase
  • Fix loop functionality
  • Add search functionality
  • Add file upload functionality

Ongoing and Future works*

  • Improve the UI/UX
    • [Missing feature] No button to pause/resume playing
    • Implement YouTube Music-inspired UI
    • Add a aesthetically beautiful background theme/color/design
    • Improve the icons/buttons and overall design
    • Make it very mobile responsive
    • Add audio visualization
  • Add equalizer
  • Add lyrics display feature (with syncronised scrolling)
  • Add user authentication
  • Add offline capabilities

*in the order or priority