I am trying to make a downloader with a progress bar for youtube videos using pytube, but I am stuck on an error.
My code:
from pytube import YouTube
def on_progress(stream, chunk, bytes_remaining):
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage_of_completion = bytes_downloaded / total_size * 100
print(percentage_of_completion)
url = "https://www.youtube.com/wat
ch?v=XQZgdHfAAjI&list=PLec973iciX1S0bLNOdmIejMVnUnBWpIwz"
yt_obj = YouTube(url).register_on_progress_callback(on_progress)
stream = yt_obj.streams.filter(progressive=True).get_highest_resolution().download()
size = stream.filesize
print(f"file size is {size}")
When I run this code, I get the following error:
Traceback (most recent call last):
File "pytube_progress.py", line 15, in <module>
stream = yt_obj.streams.filter(progressive=True).get_highest_resolution().download()
AttributeError: 'NoneType' object has no attribute 'streams'
Interestingly, when I replace this line of code: yt_obj = YouTube(url).register_on_progress_callback(on_progress)
with yt_obj = YouTube(url)
every thing works fine, and there are no errors.
Documentation for the register_on_progress_callback()
function can be found here.
The first problem in your code is, when the line
yt_obj = YouTube(url).register_on_progress_callback(on_progress)
is executed, since the register_on_progress_callback()
function doesn't return anything, the variable yt_obj
is assigned the value None
. Then, when you have yt_obj.streams
later in your code, that triggers the AttributeError
.
The second problem is with this line:
stream = yt_obj.streams.filter(progressive=True).get_highest_resolution().download()
The download()
function returns a str
, not a Stream
.
Here is a working version of your code, with these two problems fixed:
from pytube import YouTube
def on_progress(stream, chunk, bytes_remaining):
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage_of_completion = bytes_downloaded / total_size * 100
print(percentage_of_completion)
url = "https://www.youtube.com/watch?v=XQZgdHfAAjI&list=PLec973iciX1S0bLNOdmIejMVnUnBWpIwz"
# Create the YouTube object first
yt_obj = YouTube(url)
# Then register the callback
yt_obj.register_on_progress_callback(on_progress)
# Download the video, getting back the file path the video was downloaded to
file_path = yt_obj.streams.filter(progressive=True).get_highest_resolution().download()
print(f"file_path is {file_path}")