One of the biggest motivation for a programmer is creating amazing things using one’s programming skills. When a programmer starts building software and apps that he uses on a daily basis, he gets better at whatever he’s doing. How about creating a YouTube video and audio downloader on your own?
If you’re learning python, this could be an amazing project for you as a programmer. Creating something cool and bragging about it in front of your colleagues is actually a great feeling that everyone knows about. Most of us use YouTube video downloaders available on the internet but what if you have one of your own?
In this article, you’ll learn how to create YouTube video downloader with GUI in python. Here’s the code with only important details and explanations. I learned to create this a few weeks back.
Import required modules required to create YouTube video downloader with python:
from tkinter import * from PIL import Image from PIL import ImageTk from tkinter import ttk from pytube import * import requests import io import os import tkinter.messagebox import webbrowser
Define a class for the project with a default constructor:
class YT_download: def __init__(self, root): self.root = root
The very next steps:
- Create root as the Tk() object.
- Create an object of the class.
- Close the root using mainloop().
So the code looks like this:
class YT_download: def __init__(self, root): self.root = root root = Tk() obj = YT_download(root) root.mainloop()
Although this creating object and closing the root are last steps, but writing the basic skeletal syntax is always a smart thing to do.
Now, all the code that we write will be placed inside the class definition with proper indentation.
Define the default constructor __init__(self, root):
def __init__(self, root): self.root = root self.root.title("YouTube Video and Audio Downloader") self.root.geometry("500x420+300+50") self.root.resizable(False, False) self.root.config(bg = 'sky blue') header = Label(self.root,text = "YouTube Video and Audio Downloader", font = ("Times new roman", 17), bg = "gold", fg = "blue4", anchor = 'center').pack(side = TOP, fill = X) self.url = StringVar() urlLabel= Label(self.root,text = "Enter URL:", font = ("times new roman", 15), bg = "white").place(x = 10, y = 50) urlText= Entry(self.root, font = ("times new roman", 13), textvariable = self.url, bg = "pink").place(x = 115, y = 50, width = 270) #================ Programming Articles Website Link ================== #================ You can remove this code if you don't want to visit programming-articles.com ================== webbrowser.open("https://programming-articles.com") #=========== Code ended for programming-articles.com ====================== #================= Radio Buttons for choosing the filetype ==================== self.file_type = StringVar() self.file_type.set('Video') vid_radio = Radiobutton(self.root,text = "Video", variable = self.file_type, value = "Video", font = ("times new roman", 12), bg = "light green", activebackground = 'white').place(x = 125, y = 83, height = 20) aud_radio = Radiobutton(self.root,text = "Audio", variable = self.file_type, value = "Audio", font = ("times new roman", 12), bg = "light green", activebackground = 'white').place(x = 210, y = 83, height = 20) #================== SEARCH BUTTON =================================================== search_button = Button(self.root, text = "Search", command = self.search,font= ("times new roman", 14), bg= "sky blue").place(x = 320, y = 80, height = 26, width = 65) #=================== SPACE FOR VIDEO DETAILS, i.e., TITLE, THUMBNAIL, DESCRIPTION, ETC. ===================== frame = Frame(self.root, bd = 2, relief = RIDGE, bg = 'sandy brown') frame.place(x = 10, y = 115, width = 480, height = 190) self.file_title = Label(frame, text= "File Title", font = ("arial", 13), bg = "ivory2", anchor = 'c') self.file_title.place(x = 0, y = 0, relwidth = 1) self.thumbnail = Label(frame,text = "Video \nThumbnail", font = ("times new roman", 15), bg = "khaki1") self.thumbnail.place(x = 3, y = 28, width = 182, height = 154) desc_lbl = Label(frame,text = "Description", font = ("times new roman", 12), bg = "palegreen1").place(x = 190, y = 28) self.file_desc = Text(frame, font = ("times new roman", 13), bg = "lightyellow") self.file_desc.place(x = 190, y = 53, width = 283, height = 129) self.file_size= Label(self.root,text = "File Size: MB", font = ("times new roman", 12), bg = "red1") self.file_size.place(x = 10, y = 320) self.percentage_lbl= Label(self.root,text = "Downloading: 0%", font = ("times new roman", 12), bg = "red1") self.percentage_lbl.place(x = 158, y = 320) #========================= CLEAR AND DOWNLOAD BUTTON FOR RESETTING FRAME AND DOWNLOADING FILES ========================== reset_btn = Button(self.root, text = "Reset", command = self.reset, font= ("times new roman", 13), bg= "grey", fg = "white").place(x = 310, y = 320, height = 25, width = 60) self.download_btn = Button(self.root, text = "Download", state = DISABLED, command = self.download, font= ("times new roman", 13), bg= "red", fg = "white") self.download_btn.place(x = 390, y = 320, height = 25, width = 85) self.prog_Bar = ttk.Progressbar(self.root, orient = HORIZONTAL, length = 590, mode = "determinate") self.prog_Bar.place(x = 10, y = 360, width = 483, height = 20) self.msg= Label(self.root,text = "", font = ("times new roman", 16), bg = "sky blue") self.msg.place(x = 0, y = 385, relwidth = 1) #============ CREATING DIRECTORIES FOR DOWNLOADED FILES ======================== if os.path.exists('Audios') == False: os.mkdir('Audios') if os.path.exists('Videos') == False: os.mkdir('Videos')
I’ve added comments in between to add some details to the code, will be adding more details soon.
Define the method for search in the youtube video downloader using python:
def search(self): try: yt = YouTube(self.url.get()) #============= CONVERT IMAGE-URL INTO IMAGE ======= response = requests.get(yt.thumbnail_url) img_byte = io.BytesIO(response.content) self.img = Image.open(img_byte) self.img = self.img.resize((180, 140), Image.ANTIALIAS) self.img = ImageTk.PhotoImage(self.img) self.thumbnail.config(image = self.img) #======== Fetch size as per file type ======= if self.file_type.get() == 'Video': select_file = yt.streams.filter(progressive= True).first() if self.file_type.get() == 'Audio': select_file = yt.streams.filter(type="audio").first() self.size_inBytes = select_file.filesize max_size = self.size_inBytes/1024000 self.mb = str(round(max_size, 2)) + 'MB' #======== Updating the frame elements======= self.file_size.config(text = "Total Size: " + self.mb) self.file_title.config(text = yt.title[:50]) self.file_desc.delete('1.0', END) self.file_desc.insert(END, yt.description[:200]) self.download_btn.config(state = NORMAL) #===== popup error message in case wrong URL is entered ======== except: tkinter.messagebox.showinfo("Error", "Enter Valid URL")
Define a method for downloading the searched files using pytube:
#================= METHOD FOR DOWNLOADING FILES ================ def download(self): yt = YouTube(self.url.get(), on_progress_callback=self.progress_) #======== Fetch size as per file type ======= if self.file_type.get() == 'Video': select_file = yt.streams.filter(progressive= True).first() select_file.download('Videos/') if self.file_type.get() == 'Audio': select_file = yt.streams.filter(type="audio").first() select_file.download('Audios/')
Define a method for keeping track of the download progress:
#=================== METHOD FOR DOWNLOAD PROGRESS UPDATE ============================= def progress_(self,streams,chunk,bytes_remaining): percentage = (float(abs(bytes_remaining-self.size_inBytes)/self.size_inBytes))*(100) self.prog_Bar['value'] = percentage self.prog_Bar.update() self.percentage_lbl.config(text = f"Downloading: {str(round(percentage,2))}%") if round(percentage,2) == 100: self.msg.config(text = 'Download Complete', fg = "blue") self.download_btn.config(state = DISABLED)
Define a method for resetting/clearing the window:
#======================= METHOD FOR RESETTING THE WINDOW ===================== def reset(self): self.file_type.set('Video') self.url.set('') self.prog_Bar['value']=0 self.download_btn.config(state=DISABLED) self.msg.config(text = '') self.file_title.config(text = 'File Title') self.thumbnail.config(image = '') self.file_desc.delete('1.0', END) self.file_size.config(text = 'Total Size: Unknown') self.percentage_lbl.config(text = 'Downloaded: 0%')
You can download complete project from the link below:
Final Result: YouTube video and audio downloader with python

Summary
In this programming article, you learnt how to create GUI YouTube downloader with python. This project is intended to motivate and benefit beginner and intermediate python programmers.