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
+ import os
7
+
8
+
9
+ # the function for closing the application
10
+ def close_window ():
11
+ # if askokcancel is True, close the window
12
+ if askokcancel (title = 'Close Application' , message = 'Do you want to close MP3 downloader?' ):
13
+ # this distroys the window
14
+ window .destroy ()
15
+
16
+
17
+ # the function to download the mp3 audio
18
+ def download_audio ():
19
+ # the try statement to excute the download the video code
20
+ # getting video url from entry
21
+ mp3_link = url_entry .get ()
22
+ # checking if the entry and combobox is empty
23
+ if mp3_link == '' :
24
+ # display error message when url entry is empty
25
+ showerror (title = 'Error' , message = 'Please enter the MP3 URL' )
26
+ # else let's download the audio file
27
+ else :
28
+ # this try statement will run if the mp3 url is filled
29
+ try :
30
+ # this function will track the audio file download progress
31
+ def on_progress (stream , chunk , bytes_remaining ):
32
+ # the total size of the audio
33
+ total_size = stream .filesize
34
+ # this function will get the size of the audio file
35
+ def get_formatted_size (total_size , factor = 1024 , suffix = 'B' ):
36
+ # looping through the units
37
+ for unit in ["" , "K" , "M" , "G" , "T" , "P" , "E" , "Z" ]:
38
+ if total_size < factor :
39
+ return f"{ total_size :.2f} { unit } { suffix } "
40
+ total_size /= factor
41
+ # returning the formatted audio file size
42
+ return f"{ total_size :.2f} Y{ suffix } "
43
+
44
+ # getting the formatted audio file size calling the function
45
+ formatted_size = get_formatted_size (total_size )
46
+ # the size downloaded after the start
47
+ bytes_downloaded = total_size - bytes_remaining
48
+ # the percentage downloaded after the start
49
+ percentage_completed = round (bytes_downloaded / total_size * 100 )
50
+ # updating the progress bar value
51
+ progress_bar ['value' ] = percentage_completed
52
+ # updating the empty label with the percentage value
53
+ progress_label .config (text = str (percentage_completed ) + '%, File size:' + formatted_size )
54
+ # updating the main window of the app
55
+ window .update ()
56
+
57
+ # creating the YouTube object and passing the the on_progress function
58
+ audio = YouTube (mp3_link , on_progress_callback = on_progress )
59
+ # extracting and downloading the audio file
60
+ output = audio .streams .get_audio_only ().download ()
61
+ # this splits the audio file, the base and the extension
62
+ base , ext = os .path .splitext (output )
63
+ # this converts the audio file to mp3 file
64
+ new_file = base + '.mp3'
65
+ # this renames the mp3 file
66
+ os .rename (output , new_file )
67
+ # popup for dispalying the mp3 downlaoded success message
68
+ showinfo (title = 'Download Complete' , message = 'MP3 has been downloaded successfully.' )
69
+ # ressetting the progress bar and the progress label
70
+ progress_label .config (text = '' )
71
+ progress_bar ['value' ] = 0
72
+ # the except will run when an expected error occurs during downloading
73
+ except :
74
+ showerror (title = 'Download Error' , message = 'An error occurred while trying to ' \
75
+ 'download the MP3\n The following could ' \
76
+ 'be the causes:\n ->Invalid link\n ->No internet connection\n ' \
77
+ 'Make sure you have stable internet connection and the MP3 link is valid' )
78
+ # ressetting the progress bar and the progress label
79
+ progress_label .config (text = '' )
80
+ progress_bar ['value' ] = 0
81
+
82
+
83
+
84
+ # the function to run the download_audio function as a thread
85
+ def downloadThread ():
86
+ t1 = threading .Thread (target = download_audio )
87
+ t1 .start ()
88
+
89
+
90
+ # creates the window using Tk() fucntion
91
+ window = Tk ()
92
+
93
+ # this will listen to the close window event
94
+ window .protocol ('WM_DELETE_WINDOW' , close_window )
95
+
96
+ # creates title for the window
97
+ window .title ('MP3 Downloader' )
98
+
99
+ # the icon for the application, this will replace the default tkinter icon
100
+ window .iconbitmap (window , 'icon.ico' )
101
+
102
+ # dimensions and position of the window
103
+ window .geometry ('500x400+430+180' )
104
+ # makes the window non-resizable
105
+ window .resizable (height = FALSE , width = FALSE )
106
+
107
+ # creates the canvas for containing all the widgets
108
+ canvas = Canvas (window , width = 500 , height = 400 )
109
+ canvas .pack ()
110
+
111
+ """Styles for the widgets"""
112
+ # style for the label
113
+ label_style = ttk .Style ()
114
+ label_style .configure ('TLabel' , foreground = '#000000' , font = ('OCR A Extended' , 15 ))
115
+
116
+ # style for the entry
117
+ entry_style = ttk .Style ()
118
+ entry_style .configure ('TEntry' , font = ('Dotum' , 15 ))
119
+
120
+ # style for the button
121
+ button_style = ttk .Style ()
122
+ button_style .configure ('TButton' , foreground = '#000000' , font = 'DotumChe' )
123
+
124
+ # loading the MP3 logo
125
+ logo = PhotoImage (file = 'mp3_icon.png' )
126
+ # creates dimensions for the logo
127
+ logo = logo .subsample (2 , 2 )
128
+ # adding the logo to the canvas
129
+ canvas .create_image (180 , 80 , image = logo )
130
+
131
+ # the Downloader label just next to the logo
132
+ mp3_label = ttk .Label (window , text = 'Downloader' , style = 'TLabel' )
133
+ canvas .create_window (340 , 125 , window = mp3_label )
134
+
135
+ # creating a ttk label
136
+ url_label = ttk .Label (window , text = 'Enter MP3 URL:' , style = 'TLabel' )
137
+ # creating a ttk entry
138
+ url_entry = ttk .Entry (window , width = 72 , style = 'TEntry' )
139
+
140
+ # adding the label to the canvas
141
+ canvas .create_window (114 , 200 , window = url_label )
142
+ # adding the entry to the canvas
143
+ canvas .create_window (250 , 230 , window = url_entry )
144
+
145
+ # creating the empty label for displaying download progress
146
+ progress_label = Label (window , text = '' )
147
+ # adding the label to the canvas
148
+ canvas .create_window (240 , 280 , window = progress_label )
149
+
150
+ # creating a progress bar to display progress
151
+ progress_bar = ttk .Progressbar (window , orient = HORIZONTAL , length = 450 , mode = 'determinate' )
152
+ # adding the progress bar to the canvas
153
+ canvas .create_window (250 , 300 , window = progress_bar )
154
+
155
+ # creating the button
156
+ download_button = ttk .Button (window , text = 'Download MP3' , style = 'TButton' , command = downloadThread )
157
+ # adding the button to the canvas
158
+ canvas .create_window (240 , 330 , window = download_button )
159
+
160
+ # this runs the app infinitely
161
+ window .mainloop ()
0 commit comments