Download video and audio from YouTube playlists using PyTube
We have all been there. You are a music lover, who want to break free from music streaming services. It might be only because of the costs, also because you cannot find the artists or music you adore there. For me, it was mostly about listening to the artists who do not have a huge fan pool and their profiles on the streaming services were quite messy. I began downloading music from different websites. However, apps I used for this purpose arbitrarily began preventing downloads of some artists and music.
In response, I created a small script that can download single/multiple videos or audios from video links (works when there is reference to a playlist too) or playlist links. It first asks if it should handle the link as a single object or a playlist with multiple objects. Then, you need to enter the YouTube link. Finally, you will need to select the format you would like to receive the file.
Let's start.
Install libraries and dependencies
The app makes use of libraries PyTube, PyDub and OS for handling all operations that I mentioned earlier. PyDub library that we use for video -> audio conversion depends on ffmpeg package. I do not know how to install it for Windows or Linux. If you are a MacOS user, start your computer's terminal and run the code below. It is a big package, might take a while to download.
Having installed ffmpeg now we are able to add our libraries. Most probably you will not have PyTube and PyDub on your system. Run the codes below in your text editor's terminal one by one to install.
Import all required libraries.
Define a path to save
Basically where you want to save your files. The reason I want to make it clear is that on MacOS you might encounter those Error No: 30 Read only path errors if you want to create a local folder by code. A solution is to define a path on your removable drive, where you created the path folder and gave necessary Read & Write permissions in the folder settings. It is not recommended to change access settings on your system disk. In my case, these were my removable HDD and YouTube Folder in that.
Check if your playlist sub-folder exists and create if not
I have created functionality to separate files in a specific folder in relation to their playlist name. This helps differentiate between files when you download in bulk.
Replace characters to prevent conflicts in file format conversion
We need to pay attention that PyTube ignores some characters from the video title when downloading the file. The reason is simple: preventing file name errors. Many may suppose that this is none of our concern but when it comes to handling the mp4 file to convert into mp3 there is a lot of headache. This code is called by the video title variable in the PyDub bit (you will see in audio downloaders), and preemptively cleans it from funky characters. These are all characters I could detect, let me know if there are more.
Create function to download video files
Single
I preferred the highest resolution for all videos for the sake for simplicity. Check respective part in PyTube docs to filter different versions.
Playlist
Notice the change in the output path.
Create function to download audio files + convert to mp3
The main problem with the audio files downloaded from YouTube is that they have mp4 encoding, just like a video. Though QuickTime Player might play this file very well, for whatever reason, Apple Music app turns out to believe that the audio file is actually two times as long. First half is made of the actual audio, second part is complete silence. It would be a torture to set start-end times for all of them in Apple Music app, so we need to convert them to .mp3 files using PyDub and ffmpeg.
Single
Playlist
Take user inputs
Navigate users
Upcoming iterations + conclusion
There are a few iterations on the way. I am adding the script to allow users to download all video + audio files from channels using PyTube's Channel class. There should also be a progress indicator for playlists: x out of total y or in form of percentage. I will be editing this post with those iterations as soon as ready for launch.