Code for How to Make a YouTube Audio Downloader in Python Tutorial

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

# 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  
        # this try statement will run if the mp3 url is filled
            # 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
            # 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_bar['value'] = 0           
        # the except will run when an expected error occurs during downloading
            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_bar['value'] = 0

# the function to run the download_audio function as a thread   
def downloadThread():
    t1 = threading.Thread(target=download_audio)

# 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
# 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)

"""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