13

Is there a way to add progress bar in pytube? I don't know how to use the following method:

pytube.Stream().on_progress(chunk, file_handler, bytes_remaining)

My code:

from pytube import YouTube
# from pytube import Stream
from general import append_to_file


def downloader(video_link, down_dir=None):
    try:
        tube = YouTube(video_link)
        title = tube.title
        print("Now downloading,  " + str(title))
        video = tube.streams.filter(progressive=True, file_extension='mp4').first()
        print('FileSize : ' + str(round(video.filesize/(1024*1024))) + 'MB')
        # print(tube.streams.filter(progressive=True, file_extension='mp4').first())
        # Stream(video).on_progress()
        if down_dir is not None:
            video.download(down_dir)
        else:
            video.download()
        print("Download complete, " + str(title))
        caption = tube.captions.get_by_language_code('en')
        if caption is not None:
            subtitle = caption.generate_srt_captions()
            open(title + '.srt', 'w').write(subtitle)
    except Exception as e:
        print("ErrorDownloadVideo  |  " + str(video_link))
        append_to_file('debug', format(e))
    # FILESIZE print(tube.streams.filter(progressive=True, file_extension='mp4').first().filesize/(1024*1024))
xskxzr
  • 12,442
  • 12
  • 37
  • 77
Gayan Jeewantha
  • 335
  • 1
  • 3
  • 9

9 Answers9

14

You can also do like this without writing your own function.

code:

from pytube import YouTube
from pytube.cli import on_progress #this module contains the built in progress bar. 
link=input('enter url:')
yt=YouTube(link,on_progress_callback=on_progress)
videos=yt.streams.first()
videos.download()
print("(:")
  • Does this only work in cmd? I try to use this in Pycharm but it doesn't work at all. – Toma Mar 03 '23 at 21:45
7

Call your progress function inside the Youtube class

yt = YouTube(video_link, on_progress_callback=progress_function)

This is your progress function

def progress_function(self,stream, chunk,file_handle, bytes_remaining):

    size = stream.filesize
    p = 0
    while p <= 100:
        progress = p
        print str(p)+'%'
        p = percent(bytes_remaining, size)

This computes the percentage converting the file size and the bytes remaining

def percent(self, tem, total):
        perc = (float(tem) / float(total)) * float(100)
        return perc
Netzer
  • 37
  • 1
  • 9
5

This is something interesting!

We can emulate the download animation of linux with the following code:

def progress_function(chunk, file_handle, bytes_remaining):
    global filesize
    current = ((filesize - bytes_remaining)/filesize)
    percent = ('{0:.1f}').format(current*100)
    progress = int(50*current)
    status = '█' * progress + '-' * (50 - progress)
    sys.stdout.write(' ↳ |{bar}| {percent}%\r'.format(bar=status, percent=percent))
    sys.stdout.flush()

yt_obj = YouTube('<<some youtube video URL>>', on_progress_callback=progress_function)

Output looks like:

↳ |██████████████████████████████████----------------| 68.4%

Have fun!!

vagdevi k
  • 1,478
  • 9
  • 25
4

I know this is already answered, but I came across this and for me, the progress was counting down from 100 to 0. Since I wanted to fill a progress bar with the percentage value, I couldn't use this.

So I came up with this solution:

def progress_func(self, stream, chunk, file_handle,bytes_remaining):
    size = self.video.filesize
    progress = (float(abs(bytes_remaining-size)/size))*float(100))
    self.loadbar.setValue(progress)

The loadbar is my Progress Bar from PyQt5. Hope this helps someone.

nonimportant
  • 406
  • 4
  • 15
moRa
  • 63
  • 7
4

The callback function takes three arguments, not four: stream, chunk and bytes_remaining.

Run_Script
  • 2,487
  • 2
  • 15
  • 30
  • Why ? The doc for the lastest version show these three arguments : `on_progress(chunk: bytes, file_handler: BinaryIO, bytes_remaining: int)` I used stream and bytes_remaining and it works but I don't understand why ! – Maxouille Dec 13 '20 at 19:24
3

Here is a bit advanced version

def on_progress(vid, chunk, bytes_remaining):
    total_size = vid.filesize
    bytes_downloaded = total_size - bytes_remaining
    percentage_of_completion = bytes_downloaded / total_size * 100
    totalsz = (total_size/1024)/1024
    totalsz = round(totalsz,1)
    remain = (bytes_remaining / 1024) / 1024
    remain = round(remain, 1)
    dwnd = (bytes_downloaded / 1024) / 1024
    dwnd = round(dwnd, 1)
    percentage_of_completion = round(percentage_of_completion,2)

    #print(f'Total Size: {totalsz} MB')
    print(f'Download Progress: {percentage_of_completion}%, Total Size:{totalsz} MB, Downloaded: {dwnd} MB, Remaining:{remain} MB')

yt.register_on_progress_callback(on_progress)

Vipin K
  • 31
  • 2
2

Somewhat shorter option:

yt = YouTube(video_link, on_progress_callback=progress_function)

video = yt.streams.first() # or whatever 

# Prints something like "15.555% done..." 
def progress_function(stream, chunk, file_handle, bytes_remaining):
    print(round((1-bytes_remaining/video.filesize)*100, 3), '% done...')

You can, of course, limit the progress output, for instance, to values like 10, 20, 30%... - just surround the print statement with the required if-clause.

Zubo
  • 1,543
  • 2
  • 20
  • 26
1
from pytube import Playlist
from pytube import YouTube

previousprogress = 0
def on_progress(stream, chunk, bytes_remaining):
    global previousprogress
    total_size = stream.filesize
    bytes_downloaded = total_size - bytes_remaining 

    liveprogress = (int)(bytes_downloaded / total_size * 100)
    if liveprogress > previousprogress:
        previousprogress = liveprogress
        print(liveprogress)


yt = YouTube('https://www.youtube.com/watch?v=4zqKJBxRyuo&ab_channel=SleepEasyRelax-KeithSmith')
yt.register_on_progress_callback(on_progress)
yt.streams.filter(only_audio=True).first().download()
tichra
  • 557
  • 5
  • 18
0

You can add progress bar like this. ignore silly type error (if any)

pytube.request.default_range_size = 1048576    # this is for chunck size, 1MB size



yt = YouTube(url)
video = yt.streams.first()

video.download(<whatever>)


def progress_callback(stream, chunk, bytes_remaining):
    size = video.filesize
    progress = int(((size - bytes_remaining) / size) * 100)
    print(progress)
    # do call progress bar from GUI here


def complete_callback(stream, file_handle):
    print("downloading finished")
    # progress bar stop call from GUI here


yt.register_on_progress_callback(progress_callback)
yt.register_on_complete_callback(complete_callback)