Tech Blog of Jegrami's

How to Download Crystal-Clear YouTube Videos with Pytubefix & FFmpeg

Pytubefix is a drop-in replacement for Pytube, the original Python library for downloading YouTube videos. It's a 'fix' of the broken Pytube API, hence the name.

In this guide, I'll show you how to download YouTube videos in the best quality using Pytubefix and FFmpeg, a multimedia framework for processing video and audio files.

Before we begin, ensure you have Python 3, a code editor, and FFmpeg installed on your computer. Get the latest version of Python for your OS from the official website. If you're a Windows user (like me), follow this guide to download and set up FFmpeg quickly. For a code editor, VS Code is a good choice. Get it here. In addition to these tools, you should have a basic knowledge of Python and how to work in the command line.

Once you have these set up, you're good to go! Let's get started.

There are two methods for downloading videos with Pytubefix: the Progressive method and the DASH method.

The Progressive method

Pytubefix's default download method is the Progressive stream method. It gives you the video and audio streams in one file, and downloading it takes just five to six lines of code.

To get started, open your command line, navigate to your working directory, and install Pytubefix:

python -m pip install pytubefix

With Pytubefix installed, you're ready to write your script. Open your code editor and enter the following lines of code (I encourage you to type it rather than just copy-pasting):

from pytubefix import YouTube
from pytubefix.cli import on_progress
url = 'the_youtube_video_url'
yt = YouTube(url, 'WEB', on_progress_callback=on_progress)
ys = yt.streams.get_highest_resolution()
ys.download()

Let’s break down the code step by step:

First, we import the YouTube class from pytubefix.

Next, we import a function that displays a progress bar in the command line while downloading. This is optional but useful: it lets you see your download progress in the terminal.

We then copy the link to the YouTube video you want to download and assign it to the variable url.

The next line creates a YouTube object, passes it the video url and the on_progress function, and then assigns this object to the variable yt. The 'WEB' argument simply tells pytubefix to automatically create a po_token for you when downloading the video. Without it, the download might fail with the error This request was detected as a bot. Use use_po_token=True to view

With the YouTube object set up, the next line gets the highest-resolution media stream for this progressive download (remember, the default download method is progressive).

Finally, we call .download() on the selected stream. Straightforward and intuitive, isn't it?

This works fine, but it often produces poor video quality. Why? Because the highest resolution available for the progressive method is 720p, which isn’t always ideal.

The DASH method

The YouTube platform uses a streaming technique called Dynamic Adaptive Streaming over HTTP (DASH). DASH is designed for streaming high-quality media content over regular HTTP servers. So to get the best video quality, we need to take advantage of DASH.

The implication in the context of Pytubefix is that you get the audio and video streams as separate tracks. You'll have to then merge them with—you guessed it right—FFmpeg. But don't worry. The whole process is simple, efficient, and worth the extra steps. You'll see.

Let's jump into the code.

from pytubefix import YouTube
from pytubefix.cli import on_progress
from pathlib import Path
audio_path = Path('path/to/where/you/want/to/save/audio/file')
video_path = Path('path/to/where/you/want/to/save/video/file')
url = 'youtube_video_url'
yt = YouTube(url, 'WEB', on_progress_callback = on_progress)

#Get audio and video streams separately
audio_stream = yt.streams.filter(adaptive=True, file_extension='mp4', only_audio=True).order_by('abr').desc().first()
video_stream = yt.streams.filter(adaptive=True, file_extension='mp4', video_only=True).order_by('resolution').desc().first()

audio_stream.download(output_path=audio_path)
video_stream.download(output_path=video_path)

As you can see, the DASH method follows a similar approach to the progressive method, with only a few extra steps. Let's go over the new steps introduced.

In lines 3, 4, and 5, we import the Path module to handle file paths. Then we define folders for saving the separate audio and video files. Be sure to first create these folders if they don't already exist.

Having defined the video url and set up the YouTube object, we now filter by stream method using the function .filter() and choosing adaptive (DASH). Let's review all the keyword arguments passed to the filter method.

adaptive=true tells Pytubefix that we want the DASH method of download. file_extension='mp4' selects only the mp4 format (common for audio/video). only_audio=True selects the streams that contain only the audio track. only_video=True selects only the video stream. .order_by('abr').desc().first() tells Pytubefix to order the streams by audio bit rate (abr), in descending order (i.e., highest to lowest), choosing the first (the highest). For the video stream, it's pretty much the same: we order by resolution and choose the highest.

The last two lines download the audio and video files into their respective folders.

Running the script

To run the script, make sure you are in the directory where the script is saved, and then execute the following command: python -m your_script.py. Replace your_script.py with the actual filename

Once the download is completed, the files will be ready for merging.

Merging with FFmpeg

If you followed the FFmpeg installation guide I mentioned earlier, you should be able to run FFmpeg from any folder on your system. No need to navigate to a specific directory.

Now, from your working directory (or anywhere, really), run the following command:

ffmpeg -i 'path/to/video/file.mp4' -i 'path/to/audio/file.m4a' -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4

All these cryptic command-line arguments. Let's break them down one by one, shall we?

  • ffmpeg → Tells your computer to run the FFmpeg command-line tool.
  • -i → Specifies input files (first video, then audio).
  • -c:v copy → Tells FFmpeg to copy the video as is, without re-encoding it.
  • -c:a aac → Copies and encodes the audio in AAC (Advanced Audio Codec), a widely supported, high-quality format.

Note that the audio file extension is m4a. All I know is that it's an audio file format created by Apple. And that it's a better, more modern version of mp3.

  • -map 0:v:0 → Maps the first input file (0) to its first video stream (v:0).
  • -map 1:a:0 → Maps the second input file (1) to its first audio stream (a:0).
  • output.mp4 → Defines the name of the final merged file. You can call it whatever you like.

And that's it! FFmpeg will work its magic, merging your audio and video into a single file. Open it up and enjoy the best video quality YouTube has to offer.

Return to blog