-
Notifications
You must be signed in to change notification settings - Fork 1
/
Downloader.py
162 lines (128 loc) · 5.81 KB
/
Downloader.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
from notifypy import Notify
import threading
import pytube
import time
import os
import re
thread_lock = threading.Lock() # thread lock initiated so that the other threads cannot access it !
'''
The timer function is actaully a decorator used to used calculate the time taken to download
the video/playlist. It is used along with playlist and single video download(playlist).
'''
def timer(func):
def wrapper(*args,**kwargs):
start = time.time()
return_val = func(*args,**kwargs)
print(f'Download Completed In {round(time.time() - start)} seconds !')
return return_val
return wrapper
'''
A simple fucntion to send notification after downloading a video/playlist
return: None
params: msg(str)
'''
def notify(msg:str):
notification = Notify()
notification.title = "YT Downloader v1.1"
notification.message = msg #custom msg for playlists and video !
notification.icon = './media_resources/yt.ico'
notification.audio = './media_resources/notification_sound.wav'
notification.send()
class Downloader():
'''
The Downloader class contains the methods for downloading both single and playlist videos
The user has the option to choose from only audio/video/full hd etc when it comes to
downloading single videos, and in the case of playlists, the download is defaulted to
max resolution !
'''
def __init__(self):
self.dic_for_video = {}
print(f'Powered By : Pytube {pytube.__version__}\n')
'''
The below function is used for downloading a single video from youtube,
the checks are made for empty links and then the video is saved as the
same name as the title itself in the Youtube Videos Download folder.
\Downloads
|
|
\Youtube Videos(Created by the script)
|
|
----Currently Downloaded Video.pm4
params: video_directory and the video link
return: None
'''
def download_single_video(self, VID_DIR:str, video_link:str):
try:
y = pytube.YouTube(video_link)
print(f"\nThe Video you Searched For is {y.title} Author: {y.author}")
counter = 1
format_value = input('Please enter the format of your choice !\n1)video\n2)audio\n>>')
for i in y.streams.filter(type='video' if format_value == '1' else 'audio',file_extension='mp4'):
list = str(i).split(" ")
itag, type, quality, fps_bitrate, audio_video = re.findall(r'"([^"]*)"',str(list[1]) + str(list[2]) + str(list[3]) + str(list[4]) + str(list[6]))
self.dic_for_video[counter] = itag
print(f"{counter}) Type:{type} \tQuality: {quality} \tFPS/BitRate: {fps_bitrate} \tHas Both Video/Audio: {audio_video}")
counter += 1
id_number = input('Enter the ID number of The video to download the video >> ')
start = time.time()
print('Starting download....')
y.streams.get_by_itag(self.dic_for_video.get(int(id_number))).download(VID_DIR)
print(f'Video download complete in {round(time.time() - start,3)} secs !')
notify(f'Download complete and the video is saved to {VID_DIR}')
except Exception as e:
print(e)
finally:
print('Done....\n')
'''
The playlist downloader downloads all the playslist videos from the playlist,
into a folder which is created after the name of the playlist itself.
/Downloads
|
|
/Youtube Videos
|
|
/<Playlist Name>(created by the script)
|
Videos(corresponding playlist videos)
params: directory_path, and the playlist link
'''
@timer
def download_playlist(self, VID_DIR:str, playlist_link:str):
thread_pool_list=[]
playlist =pytube.Playlist(playlist_link)
print(f'Playlist Title: {playlist.title} Number of Videos: {len(playlist.video_urls)}')
PLAYLIST_DIR = playlist.title #the playlist title will be the playlist videos folder
PLAYLIST_DIR = re.sub('\\ /', ' or ', PLAYLIST_DIR) # remove the / or \ and replace with or
PLAYLIST_VIDS_DIR = os.path.join(VID_DIR,PLAYLIST_DIR) # join path
if not os.path.isdir(PLAYLIST_VIDS_DIR): # create a new folder if not exists
os.mkdir(PLAYLIST_VIDS_DIR)
print(f'The Current Playlist Will be Saved in {PLAYLIST_VIDS_DIR} Directory !')
print('Playlist download started')
try:
for video in playlist:
thread = threading.Thread(target=self.download_single_playlist_video,args=(PLAYLIST_VIDS_DIR, video))
thread.daemon = True
thread_pool_list.append(thread)
thread.start()
for thread in thread_pool_list:
thread.join()
notify(f'{playlist.title} Download Complete !\n',)
print(PLAYLIST_DIR,end=' ')
except Exception as e:
print(e)
'''
The function downloads the max resolution video(with audio) from the playist.
params: Playlist dir and the playlist video link
'''
@timer
def download_single_playlist_video(self, VID_DIR, video_url):
try:
thread_lock.acquire() #thread lock acqured !
video = pytube.YouTube(video_url)
video.streams.filter(progressive=True).get_highest_resolution().download(r'{}'.format(VID_DIR))
print(video.title,end=' ')
thread_lock.release() #thread lock released !
except Exception as e:
print(e)