Skip to content

Instantly share code, notes, and snippets.

@ahampriyanshu
Last active February 1, 2022 09:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahampriyanshu/3beaac83e60f319adaf22e3095f284e1 to your computer and use it in GitHub Desktop.
Save ahampriyanshu/3beaac83e60f319adaf22e3095f284e1 to your computer and use it in GitHub Desktop.
GUI wrapper for spotdl

spotdl-gui

snap

Installation

  • Note : This application depends on ffmpeg.

Install ffmpeg(skip if already installed)

Linux

  • Debian-based : sudo apt install ffmpeg
  • Fedora-based : yum install ffmpeg ffmpeg-devel
  • Arch-based : sudo pacman -S ffmpeg

Windows

  • Download the zipped file by clicking here
  • Extract the file
  • Rename the extracted folder to ffmpeg
  • Move the folder to C: drive
  • Open cmd and run setx /m PATH "C:\ffmpeg\bin;%PATH%"
  • To verify the installation run ffmpeg -version

Mac

brew install ffmpeg

Install pip(skip if already installed)

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python3 get-pip.py

Setup

mkdir spot_dl_gui && cd spot_dl_gui
curl https://gist.github.com/ahampriyanshu/3beaac83e60f319adaf22e3095f284e1/raw/dc4206f58bde340bd8b982d148d63eb429ffe3bf/setup.py -o setup.py
curl https://gist.github.com/ahampriyanshu/3beaac83e60f319adaf22e3095f284e1/raw/dc4206f58bde340bd8b982d148d63eb429ffe3bf/requirements.txt -o requirements.txt
pip3 install -r requirements.txt
python3 setup.py

Dependencies

Dependency Version
spotdl 3.3.1
tkinter 1.3.2
ffmpeg 1.4
future==0.18.2
requests==2.25.1
rich==9.10.0
six==1.15.0
spotdl==3.3.1
spotipy==2.16.1
tkintertable==1.3.2
toml==0.10.2
tqdm==4.56.0
urllib3==1.26.3
ytmusicapi==0.13.1
import os
import sys
import re
from tkinter import *
import subprocess
from threading import *
import tkinter.font as tkFont
downloadQueue = []
class Error(Exception):
"""Base class for other exceptions"""
pass
class DownloadError(Error):
"""Raised when error occurs while downloading"""
pass
class DuplicateUrlError(Error):
"""Raised when duplicate url is entered"""
pass
class EmptyStringError(Error):
"""Raised when an empty string is entered"""
pass
def filterQuery(rawQuery):
return "'{}'".format(rawQuery)
def getSong():
downloadBtn.config(state=DISABLED)
addBtn.config(state=DISABLED)
addBtn.config(bg="#273239")
i = 0
totalTask = len(downloadQueue)
while not downloadQueue == []:
alert.config(text="Connecting to spotify")
query = downloadQueue.pop()
try:
downloadBtn.config(text=f'Downloading {i+1} out of {totalTask}')
alert.config(text="Connection established")
cmd = subprocess.run(f'spotdl "{query}"', shell=True)
if cmd.returncode:
raise DownloadError
except PermissionError:
alert.config(text="Directory inaccessible")
except MemoryError:
alert.config(text="Out of memroy")
except DownloadError:
alert.config(text="Error occured while downloading")
except Exception as e:
print(e)
alert.config(
text="Unknown error, perhaps your internet connection")
finally:
alert.config(text="Downloading complete")
listbox.delete(END)
downloadBtn.config(text="Download")
downloadBtn.config(state=NORMAL)
addBtn.config(state=NORMAL)
i+1
def startDownload():
if downloadQueue == []:
downloadBtn.config(text="Download queue is empty!")
addBtn.config(bg="red")
return
downloadThread = Thread(target=getSong)
downloadThread.start()
def addQuery():
addBtn.config(bg="#273239")
query = querEntry.get()
querEntry.delete(0, END)
try:
if(not (query and not query.isspace())):
raise EmptyStringError
if not re.compile("^(spotify:|https://[a-z]+\.spotify\.com/)").match(query):
query = filterQuery(query)
if query in downloadQueue:
raise DuplicateUrlError
except EmptyStringError:
alert.config(text="Empty String!")
except DuplicateUrlError:
alert.config(text="Task already exists")
except Exception as e:
print(e)
alert.config(text="Unknown Error!")
else:
listbox.insert(END, query)
downloadQueue.append(query)
alert.config(text="Task added successfully")
if __name__ == "__main__":
root = Tk()
root.title("Spotify Downloader")
root.geometry("600x450")
root.resizable(width=False, height=False)
ft = tkFont.Font(family='Agency FB', size=14)
querEntry = Entry(root, borderwidth="1px", font=ft,
fg="#273239", justify="center")
querEntry.place(x=50, y=30, width=380, height=50)
ft = tkFont.Font(family='Agency FB', size=10)
addBtn = Button(root, activeforeground="#ffffff", activebackground="#666666", bg="#273239",
command=addQuery, font=ft, fg="#ffffff", justify="center", text="Add", relief="flat")
addBtn.place(x=450, y=30, width=100, height=50)
listbox = Listbox(root)
listbox.place(x=50, y=110, width=500, height=200)
ft = tkFont.Font(family='Agency FB', size=10)
downloadBtn = Button(root, activeforeground="#ffffff", activebackground="#666666",
command=startDownload, bg="#273239", font=ft, fg="#ffffff", justify="center", text="Download", relief="flat")
downloadBtn.place(x=200, y=340, width=200, height=50)
ft = tkFont.Font(family='Helvetica', size=10)
alert = Label(root, font=ft, fg="#000000", justify="center", text="")
alert.place(x=50, y=410, width=500)
root.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment