View on Github
from tkinter import *
from tkinter import ttk
from pytube import YouTube
from tkinter.messagebox import showinfo, showerror, askokcancel
import threading
import os
# the function for closing the application
def close_window():
# if askokcancel is True, close the window
if askokcancel(title='Close Application', message='Do you want to close MP3 downloader?'):
# this distroys the window
window.destroy()
# the function to download the mp3 audio
def download_audio():
# the try statement to excute the download the video code
# getting video url from entry
mp3_link = url_entry.get()
# checking if the entry and combobox is empty
if mp3_link == '':
# display error message when url entry is empty
showerror(title='Error', message='Please enter the MP3 URL')
# else let's download the audio file
else:
# this try statement will run if the mp3 url is filled
try:
# this function will track the audio file download progress
def on_progress(stream, chunk, bytes_remaining):
# the total size of the audio
total_size = stream.filesize
# this function will get the size of the audio file
def get_formatted_size(total_size, factor=1024, suffix='B'):
# looping through the units
for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
if total_size < factor:
return f"{total_size:.2f}{unit}{suffix}"
total_size /= factor
# returning the formatted audio file size
return f"{total_size:.2f}Y{suffix}"
# getting the formatted audio file size calling the function
formatted_size = get_formatted_size(total_size)
# the size downloaded after the start
bytes_downloaded = total_size - bytes_remaining
# the percentage downloaded after the start
percentage_completed = round(bytes_downloaded / total_size * 100)
# updating the progress bar value
progress_bar['value'] = percentage_completed
# updating the empty label with the percentage value
progress_label.config(text=str(percentage_completed) + '%, File size:' + formatted_size)
# updating the main window of the app
window.update()
# creating the YouTube object and passing the the on_progress function
audio = YouTube(mp3_link, on_progress_callback=on_progress)
# extracting and downloading the audio file
output = audio.streams.get_audio_only().download()
# this splits the audio file, the base and the extension
base, ext = os.path.splitext(output)
# this converts the audio file to mp3 file
new_file = base + '.mp3'
# this renames the mp3 file
os.rename(output, new_file)
# popup for dispalying the mp3 downlaoded success message
showinfo(title='Download Complete', message='MP3 has been downloaded successfully.')
# ressetting the progress bar and the progress label
progress_label.config(text='')
progress_bar['value'] = 0
# the except will run when an expected error occurs during downloading
except:
showerror(title='Download Error', message='An error occurred while trying to ' \
'download the MP3\nThe following could ' \
'be the causes:\n->Invalid link\n->No internet connection\n'\
'Make sure you have stable internet connection and the MP3 link is valid')
# ressetting the progress bar and the progress label
progress_label.config(text='')
progress_bar['value'] = 0
# the function to run the download_audio function as a thread
def downloadThread():
t1 = threading.Thread(target=download_audio)
t1.start()
# creates the window using Tk() fucntion
window = Tk()
# this will listen to the close window event
window.protocol('WM_DELETE_WINDOW', close_window)
# creates title for the window
window.title('MP3 Downloader')
# the icon for the application, this will replace the default tkinter icon
window.iconbitmap(window, 'icon.ico')
# dimensions and position of the window
window.geometry('500x400+430+180')
# makes the window non-resizable
window.resizable(height=FALSE, width=FALSE)
# creates the canvas for containing all the widgets
canvas = Canvas(window, width=500, height=400)
canvas.pack()
"""Styles for the widgets"""
# style for the label
label_style = ttk.Style()
label_style.configure('TLabel', foreground='#000000', font=('OCR A Extended', 15))
# style for the entry
entry_style = ttk.Style()
entry_style.configure('TEntry', font=('Dotum', 15))
# style for the button
button_style = ttk.Style()
button_style.configure('TButton', foreground='#000000', font='DotumChe')
# loading the MP3 logo
logo = PhotoImage(file='mp3_icon.png')
# creates dimensions for the logo
logo = logo.subsample(2, 2)
# adding the logo to the canvas
canvas.create_image(180, 80, image=logo)
# the Downloader label just next to the logo
mp3_label = ttk.Label(window, text='Downloader', style='TLabel')
canvas.create_window(340, 125, window=mp3_label)
# creating a ttk label
url_label = ttk.Label(window, text='Enter MP3 URL:', style='TLabel')
# creating a ttk entry
url_entry = ttk.Entry(window, width=72, style='TEntry')
# adding the label to the canvas
canvas.create_window(114, 200, window=url_label)
# adding the entry to the canvas
canvas.create_window(250, 230, window=url_entry)
# creating the empty label for displaying download progress
progress_label = Label(window, text='')
# adding the label to the canvas
canvas.create_window(240, 280, window=progress_label)
# creating a progress bar to display progress
progress_bar = ttk.Progressbar(window, orient=HORIZONTAL, length=450, mode='determinate')
# adding the progress bar to the canvas
canvas.create_window(250, 300, window=progress_bar)
# creating the button
download_button = ttk.Button(window, text='Download MP3', style='TButton', command=downloadThread)
# adding the button to the canvas
canvas.create_window(240, 330, window=download_button)
# this runs the app infinitely
window.mainloop()