-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathmp3_downloader.py
161 lines (134 loc) · 6.38 KB
/
mp3_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
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
window.destroy()
# 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
else:
# this try statement will run if the mp3 url is filled
try:
# 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
window.update()
# 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_label.config(text='')
progress_bar['value'] = 0
# the except will run when an expected error occurs during downloading
except:
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_label.config(text='')
progress_bar['value'] = 0
# the function to run the download_audio function as a thread
def downloadThread():
t1 = threading.Thread(target=download_audio)
t1.start()
# 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
window.geometry('500x400+430+180')
# 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)
canvas.pack()
"""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
window.mainloop()