4

I am writing small program which downloads song from youtube (using pytube) and I want to add python tkinter GUI to show percent value when the file is downloading.

Now when I execute my code, program at first downloads the file (takes about 60sec) and only then shows the label with 100%. What should I change in my code if I want to see label value climbing from 0% to 100% at the same time when the file is been downloaded?

Code Python3:

from pytube import YouTube
import tkinter as tk
from tkinter import ttk

# main application shows:
# label Loading..
# label which configure values when file is downloading 
# inderterminate progress bar
class MainApplication(tk.Frame):

def __init__(self, master=None, *args, **kwargs):
    tk.Frame.__init__(self, master)
    self.master = master

    self.master.grid_rowconfigure(0, weight=0)
    self.master.grid_columnconfigure(0, weight=1)

    self.youtubeEntry = "https://www.youtube.com/watch?v=vVy9Lgpg1m8"
    self.FolderLoacation = "C:/Users/Jonis/Desktop/"

    # pytube
    self.yt = YouTube(self.youtubeEntry)

    video_type = self.yt.streams.filter(only_audio = True).first()

    # file size of a file
    self.MaxfileSize = video_type.filesize

    # Loading label
    self.loadingLabel = ttk.Label(self.master, text="Loading...", font=("Agency FB", 30))
    self.loadingLabel.grid(pady=(100,0))

    # loading precent label which must show % donwloaded
    self.loadingPercent = tk.Label(self.master, text="", fg="green", font=("Agency FB", 30))
    self.loadingPercent.grid(pady=(30,30))

    # indeterminate progress bar
    self.progressbar = ttk.Progressbar(self.master, orient="horizontal", length=500, mode='indeterminate')
    self.progressbar.grid(pady=(50,0))
    self.progressbar.start()    

    # call Download file func
    self.DownloadFile


def DownloadFile(self):
    self.yt.register_on_progress_callback(self.show_progress_bar)
    self.yt.streams.filter(only_audio=True).first().download(self.FolderLoacation)

# func count precent of a file
def show_progress_bar(self, stream=None, chunk=None, file_handle=None, bytes_remaining=None):

    # loadingPercent label configure value %
    self.loadingPercent.config(text=str(100 - (100*(bytes_remaining/self.MaxfileSize))))


root = tk.Tk()
root.title("Youtube downloader")
root.geometry("1920x1080")
app = MainApplication(root)
root.mainloop()` 
Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130
Jonas.S.
  • 155
  • 1
  • 4
  • 14

1 Answers1

3

The issue which appears to be is that you need to call self.DownloadFile and self.show_progress_bar at the same time as you mentioned. To call both functions at the same time the best solution is to use thread library

from pytube import YouTube
import tkinter as tk
from tkinter import ttk
import threading


# main application shows:
# label Loading..
# label which configure values when file is downloading 
# inderterminate progress bar
class MainApplication(tk.Frame):

def __init__(self, master=None, *args, **kwargs):
    tk.Frame.__init__(self, master)
    self.master = master

    self.master.grid_rowconfigure(0, weight=0)
    self.master.grid_columnconfigure(0, weight=1)

    self.youtubeEntry = "https://www.youtube.com/watch?v=vVy9Lgpg1m8"
    self.FolderLoacation = "C:/Users/Jonis/Desktop/"

    # pytube
    self.yt = YouTube(self.youtubeEntry)

    video_type = self.yt.streams.filter(only_audio = True).first()

    # file size of a file
    self.MaxfileSize = video_type.filesize

    # Loading label
    self.loadingLabel = ttk.Label(self.master, text="Loading...", font=("Agency FB", 30))
    self.loadingLabel.grid(pady=(100,0))

    # loading precent label which must show % donwloaded
    self.loadingPercent = tk.Label(self.master, text="0", fg="green", font=("Agency FB", 30))
    self.loadingPercent.grid(pady=(30,30))

    # indeterminate progress bar
    self.progressbar = ttk.Progressbar(self.master, orient="horizontal", length=500, mode='indeterminate')
    self.progressbar.grid(pady=(50,0))
    self.progressbar.start()    

    threading.Thread(target=self.yt.register_on_progress_callback(self.show_progress_bar)).start()

    # call Download file func
    threading.Thread(target=self.DownloadFile).start()



def DownloadFile(self):


    self.yt.streams.filter(only_audio=True).first().download(self.FolderLoacation)

# func count precent of a file
def show_progress_bar(self, stream=None, chunk=None, file_handle=None, bytes_remaining=None):

    # loadingPercent label configure value %
    self.loadingPercent.config(text=str(int(100 - (100*(bytes_remaining/self.MaxfileSize)))))


root = tk.Tk() 
root.title("Youtube downloader")
root.geometry("1920x1080")
app = MainApplication(root)
root.mainloop()
Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130
Jonas.S.
  • 155
  • 1
  • 4
  • 14
  • Counting didn't always start here at 100 – Codador Apr 13 '20 at 17:27
  • It outputs an error: `percent = (100 * (fileSizeInBytes - remaining)) / fileSizeInBytes TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'` – Pw Wolf Jul 21 '21 at 08:11