DEV Community

Mate Technologies
Mate Technologies

Posted on

🎵 Build a Professional Spotify-Style Music Player with Python (PulsePlayer Tutorial)

In this tutorial, we’ll build a modern desktop music player using Python — featuring playlist management, album art rotation, audio visualization, drag-and-drop support, and VLC-powered playback.

We’ll build PulsePlayer, a professional Spotify-style music player with a clean architecture.

👉 Source Code:
https://github.com/rogers-cyber/PulsePlayer

👉 Download EXE:
https://github.com/rogers-cyber/PulsePlayer/releases/tag/v1.0.1

🚀 What You’ll Build

Spotify-style music player UI

Playlist management

Audio playback with VLC

Album art extraction

Lyrics display

Audio visualizer

Drag & drop support

Loop and playback controls

Smooth rotating album artwork

📦 Step 1 — Install Dependencies

Create requirements.txt:

ttkbootstrap
python-vlc
Pillow
tinytag
numpy
tkinterdnd2
pyaudio
Enter fullscreen mode Exit fullscreen mode

Install:

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

You must also install VLC Media Player on your system.

🧠 Step 2 — Import Required Libraries

These libraries handle:

UI (Tkinter + ttkbootstrap)

Audio playback (VLC)

Images (Pillow)

Metadata (TinyTag)

Visualization (NumPy)

import sys
import os
import io
import random
import threading
import tkinter as tk
from tkinter import filedialog, messagebox

import ttkbootstrap as tb
from ttkbootstrap.constants import *

from pathlib import Path
from PIL import Image, ImageTk, ImageDraw
from tinytag import TinyTag
import vlc
import numpy as np
from tkinterdnd2 import TkinterDnD
Enter fullscreen mode Exit fullscreen mode

Optional audio support:

try:
    import pyaudio
    PYAUDIO_AVAILABLE = True
except:
    PYAUDIO_AVAILABLE = False
Enter fullscreen mode Exit fullscreen mode

⚙️ Step 3 — App Configuration

Store app settings in constants.

APP_NAME = "PulsePlayer"
SUPPORTED_AUDIO = (".mp3", ".wav", ".flac", ".m4a", ".ogg")

ROTATION_SPEED = 0.4
FPS_DELAY = 16
Enter fullscreen mode Exit fullscreen mode

Why?

Easy to update later

Keeps code clean

Central configuration

🛠 Step 4 — Create Audio Utility Functions

This handles:

Time formatting

Album art extraction

Lyrics reading

Audio validation

Format Time

class AudioUtils:

    @staticmethod
    def format_time(sec):
        sec = int(sec)
        return f"{sec//60:02d}:{sec%60:02d}"
Enter fullscreen mode Exit fullscreen mode

Converts seconds → MM:SS.

Extract Album Art

@staticmethod
def extract_album_art(path):
    try:
        tag = TinyTag.get(path, image=True)
        if tag.images and tag.images.front_cover:
            img = Image.open(io.BytesIO(tag.images.front_cover.data))
            return img.resize((250, 250))
    except:
        pass
    return None
Enter fullscreen mode Exit fullscreen mode

Reads album art from MP3 metadata.

Validate Audio Files

@staticmethod
def is_valid_audio(path):
    return path.lower().endswith(SUPPORTED_AUDIO)
Enter fullscreen mode Exit fullscreen mode

Prevents invalid files from being added.

📂 Step 5 — Build Playlist Manager

Responsible for:

Adding files

Filtering search results

class PlaylistManager:
    def __init__(self):
        self.playlist = []

    def add_files(self, files):
        valid = [f for f in files if AudioUtils.is_valid_audio(f)]
        self.playlist.extend(valid)

    def filter(self, query):
        if not query:
            return self.playlist
        return [
            f for f in self.playlist
            if query.lower() in os.path.basename(f).lower()
        ]
Enter fullscreen mode Exit fullscreen mode

This keeps file logic separate from the UI.

🎧 Step 6 — Create Music Player Engine (Core Logic)

This controls:

Playback

Volume

Track switching

Looping

We keep this separate from GUI → clean architecture.

Initialize VLC Player

class MusicPlayerEngine:

    def __init__(self):
        self.vlc_instance = vlc.Instance("--no-video", "--quiet")
        self.player = self.vlc_instance.media_player_new()

        self.filtered_playlist = []
        self.current_index = -1

        self.loop_mode = False
        self.single_loop = False
Enter fullscreen mode Exit fullscreen mode

Load and Play Track

def load_track(self, path):
    media = self.vlc_instance.media_new(path)
    self.player.set_media(media)

def play(self):
    self.player.play()
Enter fullscreen mode Exit fullscreen mode

VLC handles decoding and playback.

Seek and Time Control

def get_time(self):
    return self.player.get_time() / 1000

def seek(self, sec):
    self.player.set_time(int(sec * 1000))
Enter fullscreen mode Exit fullscreen mode

Used by the progress bar.

📊 Step 7 — Build Audio Visualizer

We create animated bars reacting to playback.

class AudioVisualizer:
    def __init__(self, canvas, num_bars=50):
        self.canvas = canvas
        self.num_bars = num_bars
        self.bars = []
Enter fullscreen mode Exit fullscreen mode

Create Bars

for i in range(self.num_bars):
    x0 = i * 5
    x1 = x0 + 3
    bar = self.canvas.create_rectangle(x0, 100, x1, 100, fill="#1DB954")
    self.bars.append(bar)
Enter fullscreen mode Exit fullscreen mode

Each bar updates continuously.

Animate Visualizer

def update(self, root, engine):
    if engine.is_playing():
        heights = [random.randint(10, 100) for _ in range(self.num_bars)]
Enter fullscreen mode Exit fullscreen mode

This simulates audio activity.

🖥 Step 8 — Build Main GUI Application

This handles:

Layout

Controls

User interaction

Initialize Window

class SpotifyPlayerApp:

    def __init__(self):
        self.root = TkinterDnD.Tk()
        self.root.geometry("1200x680")
        self.root.title(APP_NAME)

        tb.Style("darkly")
Enter fullscreen mode Exit fullscreen mode

We use a modern dark theme.

Create Layout Panels

left = tb.Frame(self.root)
left.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

right = tb.Frame(self.root)
right.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
Enter fullscreen mode Exit fullscreen mode

Left → playlist

Right → player controls

🔍 Step 9 — Playlist UI
Search Box

search = tb.Entry(left)
search.pack(fill=tk.X)
Enter fullscreen mode Exit fullscreen mode

Playlist Listbox

self.listbox = tk.Listbox(left)
self.listbox.pack(fill=tk.BOTH, expand=True)
self.listbox.bind("<Double-1>", self.play_selected)
Enter fullscreen mode Exit fullscreen mode

Double-click to play.

🎵 Step 10 — Playback Controls

tb.Button(controls, text="▶", command=self.play_selected)
tb.Button(controls, text="⏸", command=self.pause)
tb.Button(controls, text="⏹", command=self.stop)
tb.Button(controls, text="⏭", command=self.next_track)
Enter fullscreen mode Exit fullscreen mode

These call engine methods.

🖼 Step 11 — Album Art with Circular Mask

We turn square images into circles.

def _apply_circle_mask(self, img):
    size = img.size
    mask = Image.new("L", size, 0)
    draw = ImageDraw.Draw(mask)
    draw.ellipse((0, 0, size[0], size[1]), fill=255)

    result = img.copy()
    result.putalpha(mask)
    return result
Enter fullscreen mode Exit fullscreen mode

🔄 Step 12 — Animate Album Rotation

def animate_album(self):
    self.rotation_angle = (self.rotation_angle + ROTATION_SPEED) % 360

    rotated = self.album_original.rotate(
        self.rotation_angle,
        resample=Image.BICUBIC
    )
Enter fullscreen mode Exit fullscreen mode

Creates Spotify-style rotating artwork.

⏱ Step 13 — Progress Bar & Track Time

def update_progress_gui(self):
    length = self.engine.get_length()
    pos = self.engine.get_time()

    self.progress_var.set(pos)
Enter fullscreen mode Exit fullscreen mode

Updates every 500ms.

🎯 Step 14 — Run the Application

if __name__ == "__main__":
    app = SpotifyPlayerApp()
    app.run()
Enter fullscreen mode Exit fullscreen mode

Launches the music player.

🎉 Final Result

You now have a professional desktop music player with:

Clean architecture

Modern UI

VLC playback engine

Metadata support

Visual effects

Playlist system

📥 Get the Full Project

👉 Source Code:
https://github.com/rogers-cyber/PulsePlayer

👉 Download Windows Build:
https://github.com/rogers-cyber/PulsePlayer/releases/tag/v1.0.1

❤️ If You Learned Something

⭐ Star the repository

🚀 Share the article

🎵 Build your own custom music player features!

Top comments (0)