Random_Pythoneer59
Random_Pythoneer59

Reputation: 728

Pytube progress only shows 99 and 100

I am trying to show progress in pytube while its downloading a video. but it only shows 99 and 100, and then Completed.

Here is my code:

from pytube import YouTube
import os

max_file_size = 0

def on_progress(stream, data_chunk, bytes_remaining):
    percent = int(100 - (100 * (bytes_remaining/max_file_size)))
    print(percent)

def on_comp(stream, path):
    print('Completed')

yt = YouTube('https://www.youtube.com/watch?v=qxYbHzn8bbU&t=84s', 
    on_progress_callback=on_progress, on_complete_callback=on_comp)       
video = yt.streams.first()
max_file_size = video.filesize
video.download(os.getcwd())

Output:

99
100
Completed

Thanks!

Upvotes: 0

Views: 773

Answers (1)

furas
furas

Reputation: 142641

Digging in source code I found in pytube.request line

default_range_size = 9437184  # 9MB

which is used as chunk size in lines

stop_pos = min(downloaded + default_range_size, file_size) - 1
range_header = f"bytes={downloaded}-{stop_pos}"

so it download 9MB in one chunk.

You download file which has only ~9MB so it downloads almost all in one chunk and it can display only 99% or 100%.

If you try with longer file using

video = yt.streams[2] 
# or 
video = yt.streams.get_by_itag(22)
# or
video = yt.streams.get_highest_resolution()

then it will download ~45MB and it will display 20%, 40%, 60%, 80%, 100%


Maybe if you could change default_range_size into smaller value then it will display percent for smaller files too - but I think it would need to change it directly in source code, so you can't do it in easy way.


Minimal working code - with other small changes.

I use

  • f'{percent:.0%}' to display 0.20 as 20% so I don't have to calculate it as on my own,
  • f'{max_file_size:_}' to display size as 104_465_890 instead of 104465890,
  • end='\r' to display percent in in the same line and replace previous value.
from pytube import YouTube

def on_progress(stream, data_chunk, bytes_remaining):
    #print('bytes_remaining:', bytes_remaining)
    downloaded = max_file_size - bytes_remaining
    percent = downloaded/max_file_size
    print(f'Downloaded: {percent:.0%}', end='\r')

def on_complete(stream, path):
    print('Completed:', path)

# --- main ---

url = 'https://www.youtube.com/watch?v=aqz-KE-bpKQ'  # "Big Buck Bunny" ~100MB
#url = 'https://www.youtube.com/watch?v=qxYbHzn8bbU' # ~45MB

yt = YouTube(url,
             on_progress_callback=on_progress,
             on_complete_callback=on_complete)

#for item in yt.streams:
#    print(item)

#video = yt.streams[2]
#video = yt.streams.get_by_itag(22)
video = yt.streams.get_highest_resolution()

max_file_size = video.filesize
print(f'Size: {max_file_size:_} bytes')

video.download(skip_existing=False)

Upvotes: 2

Related Questions