Youtube video downloader using Python
Introduction
So as i was going along with 'Internet made easy', his second project was a youtube video downloader.
So i had some issues with the code given in the video i.e. The video resolution was not that high.
So i looked all over the place and found snippets to add in and make it work.
Today we'll walk through that.
Libraries
Some of the libraries we'll need are:-
os
shutil
pytube
moviepy
sys
from sys import argv
from pytube import YouTube
import moviepy.editor as mpe
import os
import shutil
Code
- First as usual we check if the program is being run as main and take the link to download the video as a terminal argument. We then give it as an argument for the function
downloader()
if __name__=="__main__":
link= argv[1]
downloader(link)
Now its time to define the downloader function.
First we'll set a default name for the audio and video we'll be downloading
We will then create a youtube object with the link and print its title and views.
def downloader(link):
vname="clip.mp4"
aname="audio.mp3"
yt=YouTube(link)
title=yt.title
print("Title :",yt.title)
print("Views :",yt.views )
Now since some youtube videos stream video and audio as different streams(I'm not too clear about this part). We have to download the audio and video separately.
If we use the .streams function from the pytube library we can see all the different streams that youtube streams.
print(yt.streams)
<Stream: itag="18" mime_type="video/mp4" res="360p" fps="24fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">
<Stream: itag="22" mime_type="video/mp4" res="720p" fps="24fps" vcodec="avc1.64001F" acodec="mp4a.40.2" progressive="True" type="video">
<Stream: itag="313" mime_type="video/webm" res="2160p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="271" mime_type="video/webm" res="1440p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="137" mime_type="video/mp4" res="1080p" fps="24fps" vcodec="avc1.640028" progressive="False" type="video">
<Stream: itag="248" mime_type="video/webm" res="1080p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="136" mime_type="video/mp4" res="720p" fps="24fps" vcodec="avc1.4d401f" progressive="False" type="video">
<Stream: itag="247" mime_type="video/webm" res="720p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="135" mime_type="video/mp4" res="480p" fps="24fps" vcodec="avc1.4d401e" progressive="False" type="video">
<Stream: itag="244" mime_type="video/webm" res="480p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="134" mime_type="video/mp4" res="360p" fps="24fps" vcodec="avc1.4d4015" progressive="False" type="video">
<Stream: itag="243" mime_type="video/webm" res="360p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="133" mime_type="video/mp4" res="240p" fps="24fps" vcodec="avc1.4d400d" progressive="False" type="video">
<Stream: itag="242" mime_type="video/webm" res="240p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="160" mime_type="video/mp4" res="144p" fps="24fps" vcodec="avc1.4d400b" progressive="False" type="video">
<Stream: itag="278" mime_type="video/webm" res="144p" fps="24fps" vcodec="vp9" progressive="False" type="video">
<Stream: itag="139" mime_type="audio/mp4" abr="48kbps" acodec="mp4a.40.5" progressive="False" type="audio">
<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">
Out of all these streams only 2 streams have both audio and video (its the first two with both an acodec and vcodec)
So if we just tried to select and download the highest resolution stream using
.get_highest_resolution()
it would look for the highest resolution with both audio and video. which is 720p.So what do we do? This is where moviepy library comes in.
This library can take separate audio and video files and stitch them together. Although this can sometimes have slight sync issues.
The first step is to download the audio and video separately like so
video = yt.streams.filter(subtype='mp4', res='1080p').first().download()
os.rename(video,vname)
audio=yt.streams.filter(only_audio=True).first().download()
os.rename(audio,aname)
We name them using the names we defined in aname and vname.
So now we gotta prep the files to be put into the moviepy library and then stitch it together as below.
video=mpe.VideoFileClip(vname)
audio=mpe.AudioFileClip(aname)
final=video.set_audio(audio)
We then create the final mp4 file with both audio and video then delete the separate files we downloaded.
We can also move this file to a directory of choice if necessary as below.
The codec field basically just says what type of file we are making
final.write_videofile(f"{title}.mp4",codec="libx264")
os.remove(vname)
os.remove(aname)
shutil.move(f"{title}.mp4", "/home/manmohan/Documents/videos")
Conclusion
In conclusion i had a lot of fun with this project
I learn about how youtube videos have many streams and stuff a bit.
I learned to move and delete files from python.
There are still some issues with the downloaded file sometimes but it works properly most of the time.
Like always any advice is welcome thank you for reading this.