Pytube进度只显示99和100

Pytube progress only shows 99 and 100

我正在尝试在 pytube 下载视频时显示进度。但是只显示99和100,然后Completed.

这是我的代码:

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())

输出:

99
100
Completed

谢谢!

深入挖掘我在 pytube.request

中找到的源代码
default_range_size = 9437184  # 9MB

用作行中的块大小

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

所以它下载 9MB 一个块。

您下载的文件只有 ~9MB 所以它几乎全部下载在一个块中并且它只能显示 99%100%.

如果您尝试使用

处理更长的文件
video = yt.streams[2] 
# or 
video = yt.streams.get_by_itag(22)
# or
video = yt.streams.get_highest_resolution()

然后会下载~45MB然后会显示20%, 40%, 60%, 80%, 100%


也许如果您可以将 default_range_size 更改为更小的值,那么对于较小的文件它也会显示百分比 - 但我认为它需要直接在源代码中更改它,所以您不能在简单的方法。


最少的工作代码 - 有其他小改动。

我用

  • f'{percent:.0%}'0.20 显示为 20% 这样我就不必自己计算了,
  • f'{max_file_size:_}' 将大小显示为 104_465_890 而不是 104465890
  • end='\r' 在同一行中显示百分比并替换之前的值。
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)