Skip to content

Commit e6e60b8

Browse files
committed
add youtube video download tutorial
1 parent 252c6c1 commit e6e60b8

File tree

6 files changed

+259
-0
lines changed

6 files changed

+259
-0
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
141141
- [How to Automate Login using Selenium in Python](https://www.thepythoncode.com/article/automate-login-to-websites-using-selenium-in-python). ([code](web-scraping/automate-login))
142142
- [How to Make a Currency Converter in Python](https://www.thepythoncode.com/article/make-a-currency-converter-in-python). ([code](web-scraping/currency-converter))
143143
- [How to Extract Google Trends Data in Python](https://www.thepythoncode.com/article/extract-google-trends-data-in-python). ([code](web-scraping/extract-google-trends-data))
144+
- [How to Make a YouTube Video Downloader in Python](https://www.thepythoncode.com/article/make-a-youtube-video-downloader-in-python). ([code](web-scraping/youtube-video-downloader))
144145

145146
- ### [Python Standard Library](https://www.thepythoncode.com/topic/python-standard-library)
146147
- [How to Transfer Files in the Network using Sockets in Python](https://www.thepythoncode.com/article/send-receive-files-using-sockets-python). ([code](general/transfer-files/))

Diff for: web-scraping/youtube-video-downloader/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# [How to Make a YouTube Video Downloader in Python](https://www.thepythoncode.com/article/make-a-youtube-video-downloader-in-python)
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytube
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
from pytube import YouTube
3+
4+
5+
# the function takes the video url as an argument
6+
def video_downloader(video_url):
7+
8+
# passing the url to the YouTube object
9+
my_video = YouTube(video_url)
10+
11+
# downloading the video in high resolution
12+
my_video.streams.get_highest_resolution().download()
13+
14+
# return the video title
15+
return my_video.title
16+
17+
# the try statement will run if there are no errors
18+
try:
19+
# getting the url from the user
20+
youtube_link = input('Enter the YouTube link:')
21+
22+
print(f'Downloading your Video, please wait.......')
23+
24+
# passing the url to the function
25+
video = video_downloader(youtube_link)
26+
# printing the video title
27+
print(f'"{video}" downloaded succussfully!!')
28+
29+
#the except will catch ValueError, URLError, RegexMatchError and simalar
30+
except:
31+
print(f'Failed to download video\nThe '\
32+
'following might be the causes\n->No internet '\
33+
'connection\n->Invalid video link')
34+
35+
36+
# YouTube(url).streams.filter(res="360p").first().download()
37+
38+
#YouTube(url).streams.first().download()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
from tkinter import *
2+
from tkinter import ttk
3+
from pytube import YouTube
4+
from tkinter.messagebox import showinfo, showerror, askokcancel
5+
import threading
6+
7+
8+
9+
# the function to download the video
10+
def download_video():
11+
# the try statement to excute the download the video code
12+
try:
13+
# getting video url from entry
14+
video_link = url_entry.get()
15+
# getting video resolution from Combobox
16+
resolution = video_resolution.get()
17+
# checking if the entry and combobox is empty
18+
if resolution == '' and video_link == '':
19+
# display error message when combobox is empty
20+
showerror(title='Error', message='Please enter both the video URL and resolution!!')
21+
# checking if the resolution is empty
22+
elif resolution == '':
23+
# display error message when combobox is empty
24+
showerror(title='Error', message='Please select a video resolution!!')
25+
# checking if the comboxbox value is None
26+
elif resolution == 'None':
27+
# display error message when combobox value is None
28+
showerror(title='Error', message='None is an invalid video resolution!!\n'\
29+
'Please select a valid video resolution')
30+
# else let's download the video
31+
else:
32+
# this try statement will run if the resolution exists for the video
33+
try:
34+
# this function will track the video download progress
35+
def on_progress(stream, chunk, bytes_remaining):
36+
# the total size of the video
37+
total_size = stream.filesize
38+
# this function will get the size of the video
39+
def get_formatted_size(total_size, factor=1024, suffix='B'):
40+
# looping through the units
41+
for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
42+
if total_size < factor:
43+
return f"{total_size:.2f}{unit}{suffix}"
44+
total_size /= factor
45+
# returning the formatted video size
46+
return f"{total_size:.2f}Y{suffix}"
47+
48+
# getting the formatted video size calling the function
49+
formatted_size = get_formatted_size(total_size)
50+
# the size downloaded after the start
51+
bytes_downloaded = total_size - bytes_remaining
52+
# the percentage downloaded after the start
53+
percentage_completed = round(bytes_downloaded / total_size * 100)
54+
# updating the progress bar value
55+
progress_bar['value'] = percentage_completed
56+
# updating the empty label with the percentage value
57+
progress_label.config(text=str(percentage_completed) + '%, File size:' + formatted_size)
58+
# updating the main window of the app
59+
window.update()
60+
61+
# creating the YouTube object and passing the the on_progress function
62+
video = YouTube(video_link, on_progress_callback=on_progress)
63+
# downlaoding the actual video
64+
video.streams.filter(res=resolution).first().download()
65+
# popup for dispalying the video downlaoded success message
66+
showinfo(title='Download Complete', message='Video has been downloaded successfully.')
67+
# ressetting the progress bar and the progress label
68+
progress_label.config(text='')
69+
progress_bar['value'] = 0
70+
# the except will run when the resolution is not available or invalid
71+
except:
72+
showerror(title='Download Error', message='Failed to download video for this resolution')
73+
# ressetting the progress bar and the progress label
74+
progress_label.config(text='')
75+
progress_bar['value'] = 0
76+
77+
# the except statement to catch errors, URLConnectError, RegMatchError
78+
except:
79+
# popup for displaying the error message
80+
showerror(title='Download Error', message='An error occurred while trying to ' \
81+
'download the video\nThe following could ' \
82+
'be the causes:\n->Invalid link\n->No internet connection\n'\
83+
'Make sure you have stable internet connection and the video link is valid')
84+
# ressetting the progress bar and the progress label
85+
progress_label.config(text='')
86+
progress_bar['value'] = 0
87+
88+
89+
90+
# function for searching video resolutions
91+
def searchResolution():
92+
# getting video url from entry
93+
video_link = url_entry.get()
94+
# checking if the video link is empty
95+
if video_link == '':
96+
showerror(title='Error', message='Provide the video link please!')
97+
# if video link not empty search resolution
98+
else:
99+
try:
100+
# creating a YouTube object
101+
video = YouTube(video_link)
102+
# an empty list that will hold all the video resolutions
103+
resolutions = []
104+
# looping through the video streams
105+
for i in video.streams.filter(file_extension='mp4'):
106+
# adding the video resolutions to the resolutions list
107+
resolutions.append(i.resolution)
108+
# adding the resolutions to the combobox
109+
video_resolution['values'] = resolutions
110+
# when search is complete notify the user
111+
showinfo(title='Search Complete', message='Check the Combobox for the available video resolutions')
112+
# catch any errors if they occur
113+
except:
114+
# notify the user if errors are caught
115+
showerror(title='Error', message='An error occurred while searching for video resolutions!\n'\
116+
'Below might be the causes\n->Unstable internet connection\n->Invalid link')
117+
118+
119+
120+
121+
122+
# the function to run the searchResolution function as a thread
123+
def searchThread():
124+
t1 = threading.Thread(target=searchResolution)
125+
t1.start()
126+
127+
128+
# the function to run the download_video function as a thread
129+
def downloadThread():
130+
t2 = threading.Thread(target=download_video)
131+
t2.start()
132+
133+
134+
135+
136+
# creates the window using Tk() fucntion
137+
window = Tk()
138+
139+
# creates title for the window
140+
window.title('YouTube Video Downloader')
141+
# dimensions and position of the window
142+
window.geometry('500x460+430+180')
143+
# makes the window non-resizable
144+
window.resizable(height=FALSE, width=FALSE)
145+
146+
# creates the canvas for containing all the widgets
147+
canvas = Canvas(window, width=500, height=400)
148+
canvas.pack()
149+
150+
# loading the logo
151+
logo = PhotoImage(file='youtubelogo.png')
152+
# creates dimensions of the logo
153+
logo = logo.subsample(10, 10)
154+
# adding the logo to the canvas
155+
canvas.create_image(250, 80, image=logo)
156+
157+
158+
"""Styles for the widgets"""
159+
# style for the label
160+
label_style = ttk.Style()
161+
label_style.configure('TLabel', foreground='#000000', font=('OCR A Extended', 15))
162+
163+
# style for the entry
164+
entry_style = ttk.Style()
165+
entry_style.configure('TEntry', font=('Dotum', 15))
166+
167+
# style for the button
168+
button_style = ttk.Style()
169+
button_style.configure('TButton', foreground='#000000', font='DotumChe')
170+
171+
172+
# creating a ttk label
173+
url_label = ttk.Label(window, text='Enter Video URL:', style='TLabel')
174+
# creating a ttk entry
175+
url_entry = ttk.Entry(window, width=76, style='TEntry')
176+
177+
# adding the label to the canvas
178+
canvas.create_window(114, 200, window=url_label)
179+
# adding the entry to the canvas
180+
canvas.create_window(250, 230, window=url_entry)
181+
182+
183+
# creating resolution label
184+
resolution_label = Label(window, text='Resolution:')
185+
# adding the label to the canvas
186+
canvas.create_window(50, 260, window=resolution_label)
187+
188+
189+
# creating a combobox to hold the video resolutions
190+
video_resolution = ttk.Combobox(window, width=10)
191+
# adding the combobox to the canvas
192+
canvas.create_window(60, 280, window=video_resolution)
193+
194+
195+
# creating a button for searching resolutions
196+
search_resolution = ttk.Button(window, text='Search Resolution', command=searchThread)
197+
# adding the button to the canvas
198+
canvas.create_window(85, 315, window=search_resolution)
199+
200+
201+
# creating the empty label for displaying download progress
202+
progress_label = Label(window, text='')
203+
# adding the label to the canvas
204+
canvas.create_window(240, 360, window=progress_label)
205+
206+
# creating a progress bar to display progress
207+
progress_bar = ttk.Progressbar(window, orient=HORIZONTAL, length=450, mode='determinate')
208+
# adding the progress bar to the canvas
209+
canvas.create_window(250, 380, window=progress_bar)
210+
211+
# creating the button
212+
download_button = ttk.Button(window, text='Download Video', style='TButton', command=downloadThread)
213+
# adding the button to the canvas
214+
canvas.create_window(240, 410, window=download_button)
215+
216+
217+
# runs the window infinitely
218+
window.mainloop()
65.7 KB
Loading

0 commit comments

Comments
 (0)