Do you find it troublesome to always look for a YouTube video downloader with your privacy at risk? Downloading a YouTube video using an external extension might be maddening because of the mouse click ads and other issues while using that extension.
So, why not we create our own bot that can download any YouTube video with just simply running a Python script? Everything would be in our control then, awesome, right?
In this article, we are going to see how we can make a Python script to automate the YouTube video downloading activity.
After going through this article, you can say NO
to all those annoying ads, privacy issues, authorisation to different extensions and can finally have total control.
Let's get started!
What Are We Going To Use?
We are going to use Python and one of its amazing 3rd party library, pytube.
To install pytube:
$ pip install pytube
Collecting pytube
Downloading pytube-10.7.2-py3-none-any.whl (42 kB)
|████████████████████████████████| 42 kB 3.4 MB/s
Installing collected packages: pytube
Successfully installed pytube-10.7.2
$
More on pytube:
- pytube is a very serious, lightweight, dependency-free Python library (and command-line utility) for downloading YouTube Videos.
- pytube is a lightweight library written in Python. It has no third-party dependencies and aims to be highly reliable.
- pytube also makes pipelining easy, allowing you to specify callback functions for different download events, such as
on progress
oron complete
. - Finally, pytube also includes a command-line utility, allowing you to quickly download videos right from the terminal.
Features:
- Support for both progressive & DASH streams.
- Support for downloading complete playlist.
- Easily register
on_download_progress
&on_download_complete
callbacks. - Command-line interfaced included.
- Caption track support.
- Outputs caption tracks to
.srt
format (SubRip Subtitle). - Ability to capture thumbnail URL.
- Extensively documented source code.
- No third-party dependencies (written in pure Python).
On a high level, to download a video using the library in a script, we'll need to first import the YouTube class from the library, and pass it an argument of the video URL. Then we can download different streams present on that YouTube object.
Now, let's move on to use this information to build our first YouTube video downloader.
Get The Streams
First, we will make a simple script to get all the available streams for the given YouTube video URL. Open a file name it whatever you like with the .py
extension, let's say for our case we name it pytube_demo.py
, add the following code in it and run:
# ./pytube_demo.py
from pytube import YouTube
video_url = input("Enter YouTube Video URL: ")
youtube_obj = YouTube(video_url)
print(youtube_obj.streams)
After you hit run, when the terminal prompts you to enter a video URL, enter this https://www.youtube.com/watch?v=fibIyvTleqc
, it is one of my favourite songs Daydreamer
by AURORA
.
Note: You can enter any YouTube video URL here, what we are going to explore further doesn't depend on which URL you enter.
Enter YouTube Video URL: https://www.youtube.com/watch?v=fibIyvTleqc
[<Stream: itag="18" mime_type="video/mp4" res="360p" fps="25fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">, <Stream: itag="137" mime_type="video/mp4" res="1080p" fps="25fps" vcodec="avc1.640028" progressive="False" type="video">, <Stream: itag="248" mime_type="video/webm" res="1080p" fps="25fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="136" mime_type="video/mp4" res="720p" fps="25fps" vcodec="avc1.4d401f" progressive="False" type="video">, <Stream: itag="247" mime_type="video/webm" res="720p" fps="25fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="135" mime_type="video/mp4" res="480p" fps="25fps" vcodec="avc1.4d401e" progressive="False" type="video">, <Stream: itag="244" mime_type="video/webm" res="480p" fps="25fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="134" mime_type="video/mp4" res="360p" fps="25fps" vcodec="avc1.4d401e" progressive="False" type="video">, <Stream: itag="243" mime_type="video/webm" res="360p" fps="25fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="133" mime_type="video/mp4" res="240p" fps="25fps" vcodec="avc1.4d4015" progressive="False" type="video">, <Stream: itag="242" mime_type="video/webm" res="240p" fps="25fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="160" mime_type="video/mp4" res="144p" fps="25fps" vcodec="avc1.4d400c" progressive="False" type="video">, <Stream: itag="278" mime_type="video/webm" res="144p" fps="25fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2" progressive="False" type="audio">, <Stream: itag="249" mime_type="audio/webm" abr="50kbps" acodec="opus" progressive="False" type="audio">, <Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus" progressive="False" type="audio">, <Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus" progressive="False" type="audio">]
So, we got a list of Stream
objects, each stream object giving us information about different aspects of a video.
If we see res
attribute of stream object, we see that we have 360p
, 1080p
, 720p
, 480p
, 240p
and 144p
with different vcodec
attribute. This res
represents the resolution of a video, we can select any stream of desired resolution to download.
Also, notice that we have only audio option streams available as well to download.
Next, we will create a filter for video resolution and to keep it simple we will not dive into audio downloadable streams.
Filter Stream Based On Resolution
Update the code in the pytube_demo.py
file to the below code:
# ./pytube_demo.py
from pytube import YouTube
def get_stream_for_res(streams, res):
"""
Filter on the basis of a given resolution. Return a list of filtered streams.
"""
stream = list(filter(lambda x: x.resolution == res, streams))
return stream
video_url = input("Enter YouTube Video URL: ").strip()
youtube_obj = YouTube(video_url)
video_res = input(f"Enter YouTube Video Resolution for {youtube_obj.title}: ").strip()
req_stream_obj = get_stream_for_res(youtube_obj.streams, video_res)
print(req_stream_obj)
Hit run and we can see following output in the terminal:
Enter YouTube Video URL: https://www.youtube.com/watch?v=fibIyvTleqc
Enter YouTube Video Resolution for AURORA - Daydreamer (Audio): 720p
[<Stream: itag="136" mime_type="video/mp4" res="720p" fps="25fps" vcodec="avc1.4d401f" progressive="False" type="video">, <Stream: itag="247" mime_type="video/webm" res="720p" fps="25fps" vcodec="vp9" progressive="False" type="video">]
First, we take the video URL and creates the YouTube
object, then we take custom input from the user while displaying the title of the video using youtube_obj.title
. After receiving the resolution, say 720p
, we call the function get_stream_for_res
that filters the given list of streams on the given resolution. At last, we can see the output, it contains 2 stream objects in a list, both objects have different values for some attributes but have the same resolution.
Without diving deep on what all other attribute means, let's just simply take the first element of the list and download the video.
Download Stream Based On Resolution
Now update the code to the following to download the YouTube video (complete script):
# ./pytube_demo.py
from pytube import YouTube
def get_stream_for_res(streams, res):
stream = list(filter(lambda x: x.resolution == res, streams))
return stream
video_url = input("Enter YouTube Video URL: ").strip()
youtube_obj = YouTube(video_url)
video_res = input(f"Enter YouTube Video Resolution for {youtube_obj.title}: ").strip()
req_stream_obj = get_stream_for_res(youtube_obj.streams, video_res)[0]
req_stream_obj.download()
print(f"YouTube Video {youtube_obj.title} Downloaded With Resolution {video_res}")
When we run the above script, we get the following output and a downloaded video:
Enter YouTube Video URL: https://www.youtube.com/watch?v=fibIyvTleqc
Enter YouTube Video Resolution for AURORA - Daydreamer (Audio): 720p
YouTube Video AURORA - Daydreamer (Audio) Downloaded With Resolution 720p
Now, if we check our directory where we ran the script, we can find the downloaded video.
Note:
You may notice that some streams listed have both a video codec and audio codec, while others have just video or just audio, this is a result of YouTube supporting a streaming technique called Dynamic Adaptive Streaming over HTTP (DASH).
In the context of pytube, the implications are for the highest quality streams; you now need to download both the audio and video tracks and then post-process them with software like FFmpeg to merge them.
The legacy streams that contain the audio and video in a single file (referred to as “progressive download”) are still available, but only for resolutions 720p and below.
The video downloaded from the given code has a Stream object whose attribute progressive
is False
. The given video URL does not have legacy streams available for 720p
but if you notice there is one stream with progressive
as True
and res
as 360p
.
<Stream: itag="18" mime_type="video/mp4" res="360p" fps="25fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">
So, go ahead and experiment with it and don't forget to check out the progressive
attribute.
What Next?
Well, that's it from me. If you followed this and ran the final script, you would be seeing a downloaded video in your working directory.
You can take it to the next level by creating a UI for this utility. You can host this as a service that would be strictly private to you.
What are you waiting for then? Use Tkinter, PyQT, Kivy, Flask or Django and make a UI with more functions like a select option for audio and video, for video resolution and for audio ABR, etc. and say NO
to all those annoying ads, privacy issues, several authorisations to different extensions and have total control over your downloaded videos.
Just starting your Open Source Journey? Don't forget to check Hello Open Source
Want to showcase your Python project or just out there to explore? Check Awesome Python Repos
Want to make a simple and awesome game from scratch? Check out PongPong
Want to
++
your GitHub Profile README? Check out Quote - README
Till next time!
Namaste 🙏
Top comments (5)
I try, but the video downloaded theres nothing voice.
As per the official documentation:
It seems that the video that I downloaded from the given code has a Stream object whose attribute
progressive
isFalse
. The given video URL does not have legacy streams available for720p
but if you notice there is one stream withprogressive
asTrue
andres
as360p
.Thank you for pointing it out, I have updated the post.
thanks a lot🙌
Title is kinda click bait
"Your Own YouTube Downloader" which is actually a thin wrapper around library (and not even youtube-dl)
I will go ahead and try
youtube_dl
as well, thanks for letting me know ☺️