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.