I want to update self.error_label
in realtime but I do not know what's going wrong it is not updating in realtime, Even though I have added Thread
, seems like it is not working. I see Download 100% when it is fully downloaded, not in between like 20%, 48% and so on.
import customtkinter
from pytube import YouTube
import re
from threading import Thread
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
self._set_appearance_mode("System")
self.geometry("720x480")
self.title('PyTube')
# Progress bar
self.progressbar = customtkinter.CTkProgressBar(self, width=500)
self.progressbar.set(0)
self.progressbar.pack()
#Error label
self.error_label = customtkinter.CTkLabel(self, text='Welcome!') #<----------------
self.error_label.pack()
#User input box
................
def progress_callback(self, stream, chunk, bytes_remaining):
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage = bytes_downloaded / total_size * 100
self.error_label.configure(text=f'Download {percentage}%')
def youtube_video_download(self, link, res):
yt = YouTube(link, on_progress_callback=self.progress_callback)
vid = yt.streams.filter(progressive=True, resolution=res).first()
vid.download()
def Download(self):
if self.link_validate(self.user_input.get()):
if self.tabview.get() == 'Video':
if self.video_quality.get() != '':
Thread(target=self.youtube_video_download, args=(self.user_input.get(), self.video_quality.get(), )).start()
else:
self.error('Video quality is not selected!', 'red')
if __name__=="__main__":
app = App()
app.mainloop()
I've updated your code slightly so that it works when copy pasting:
import customtkinter
import pytube.request
from pytube import YouTube
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
self._set_appearance_mode("System")
# change chunk size to 25 kilobytes to have working progressbar even on small files
pytube.request.default_range_size = 25600
self.geometry("720x480")
self.title('PyTube')
# Progress bar
self.progressbar = customtkinter.CTkProgressBar(self, width=500)
self.progressbar.set(0)
self.progressbar.pack()
# Error label
self.error_label = customtkinter.CTkLabel(
self, text='Welcome!') # <----------------
self.error_label.pack()
self.button = customtkinter.CTkButton(self, command=self.Download)
self.button.pack()
def progress_callback(self, stream, chunk, bytes_remaining):
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage = bytes_downloaded / total_size * 100
self.error_label.configure(text=f'Download {percentage}%')
self.error_label.update()
def youtube_video_download(self, link):
yt = YouTube(link, on_progress_callback=self.progress_callback)
vid = yt.streams.filter(progressive=True).first()
vid.download()
def Download(self):
self.youtube_video_download(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ")
if __name__ == "__main__":
app = App()
app.mainloop()
The changes that are important are these:
You need to update the error label to display the new value from within the progress_callback
so the value gets updated while downloading and not after it's done so add self.error_label.update()
to the bottom of the progress_callback
change the chunk size of pytube to something smaller as the default chunk size can be too big for a smooth progress bar and sometimes you wont even really see the progress if you dont decrease it (optional but suggested if you want a smooth animation of the progressbar filling):
import pytube.request
pytube.request.default_range_size = 25600