STAY INFORMED
following content serves as a personal note and may lack complete accuracy or certainty.

Minimal-Mistakes instruction
Useful vscode Shortcut Keys
Unix Commands
npm Commands
Vim Commands
Git Note
Useful Figma Shortcut Keys

2 minute read

Programming languages used

  • python

Introduction

Downloading a video from YouTube is quite a tough job. Download extensions to download YouTube videos or use another website to get the video.

However, you can do it easily using python with pytube which is lightweight, dependency-free Python library.

You need to install the library.

prerequisites

pip3 install pytube

and import

code

import pytube

I want to make this program with GUI, so we need to initialize window.

initialize

class MyGUI:

    def __init__(self):
        self.mainWindow = Tk()
        self.mainWindow.geometry(f"500x500+700+200")
        self.frame1 = Frame(self.mainWindow, width=480, height=480)
        self.frame1.place(x=10, y=10)

inputs

We need to take input the URL and resolution. I will use entry and radio buttons for these.

self.urlLabel = Label(self.frame1, text="URL", font=14)
self.urlLabel.place(x=10, y=10)
self.url = Entry(self.frame1)
self.url.place(x=50, y=10)

self.mp4Choice=StringVar()
self.mp4Choice.set("360")

self.mp4rb1=Radiobutton(self.frame1, text="360p", font=14, variable=self.mp4Choice, value="360")
self.mp4rb1.place(x=300, y=10)
self.mp4rb1=Radiobutton(self.frame1, text="720p", font=14, variable=self.mp4Choice, value="720")
self.mp4rb1.place(x=380, y=10)

I will add one more entry to change the title of the downloaded video or not.

self.titleLabel = Label(self.frame1, text="Title(optional)", font=14)
self.titleLabel.place(x=10, y=80)
self.title = Entry(self.frame1)
self.title.place(x=10, y=100)

function

Now, add a button to test it.

button

self.downBtn = Button(self.frame1, text="Download", font=14, command=self.do_this)
self.downBtn.place(x=10, y=150)

function

def do_this(self):
    get_url = self.url.get()
    yt = YouTube(get_url)
    stream = yt.streams.get_by_itag(18) # select stream
    stream.download()

It works. If you wonder “yt.streams.get_by_itag(18)”, check this link

Now, need to modify the function.

def do_this(self):
    try:
        get_url = self.url.get()
        get_title = self.title.get()
        get_selected_mp4 = self.mp4_chocie.get()
        yt = YouTube(get_url)

    except:
        showerror("Error", "Invalid URL")

    else:
        # if title is set, use the title
        if get_title:
            yt.title = get_title

        # get value of selected radio button
        if get_selected_mp4 == "360":
            stream = yt.streams.get_by_itag(18)
        elif get_selected_mp4 == "720":
            stream = yt.streams.get_by_itag(22)
        stream.download()
        showinfo("Result", f"Video({get_selected_mp4}p) was successfully download")

more info

Learned New

I noticed we can download only audio as well. So I will change radio button to combo box because there are 7 choices to download video or audio.

Let’s create a list containing combo box elements. Also I learned one new thing in combo box, state=”readonly”. This ensures that the user can only choose values from the provided list and cannot manually edit the text.

from tkinter import ttk # need to import for combo box

self.streams = ["video/mp4, res=360p", "video/mp4, res=720p", "audio/mp4, abr=48kbps",
                "audio/mp4, abr=128kbps", "audio/webm, abr=50kbps", "audio/webm, abr=70kbps",
                "audio/webm, abr=160kbps",]
                #
self.stream_box = ttk.Combobox(self.frame1, values=self.streams, state="readonly")
self.stream_box.place(x=10, y=150)

and modify the function

# add map to optimize
def do_this(self):
    itag_map = {
        "video/mp4, res=360p": 18,
        "video/mp4, res=720p": 22,
        "audio/mp4, abr=48kbps": 139,
        "audio/mp4, abr=128kbps": 140,
        "audio/webm, abr=50kbps": 249,
        "audio/webm, abr=70kbps": 250,
        "audio/webm, abr=160kbps": 251
        }
    try:
        get_url = self.url.get()
        get_title = self.title.get()
        get_selected_stream = self.stream_box.get()
        yt = YouTube(get_url)

    except:
        showerror("Error", "Invalid URL")

    else:
        itag = itag_map.get(get_selected_stream)

        # if title is set, use the title
        if get_title:
            yt.title = get_title

        if itag is not None:
            stream = yt.streams.get_by_itag(itag)

            # slice after a = to get selected stream quality
            split_stream_elements = get_selected_stream.split("=")

            # check whether it is video or audio using slice
            selected_type = split_stream_elements[0][:5]
            selected_qual = split_stream_elements[1]

            stream.download()
            showinfo("Result", f"{selected_type}({selected_qual}) was successfully download")