
In one of my first articles on Medium, I showed how to train a Convolutional Neural Network to classify images coming from old GameBoy games – Mario and Wario. After over a year, I wanted to revisit one aspect of the process – downloading videos (and potentially audio) from YouTube videos and extracting frames as images. We can use such images for various Machine Learning projects.
Setup
In my previous article, I used a library called pytube
to download the videos. However, after some changes introduced by YouTube, it is not really usable anymore – any attempt to download videos results in KeyError: 'url_encoded_fmt_stream_map'
. Also, the library is not actively maintained anymore.
That is why in this article I suggest using pytube3
, which is a fork of the original pytube
library and has the error fixed (it only works with Python 3). All the functionalities of the original library are preserved and we actually still use import pytube
to import the library (even though we install it using pip install pytube3
).
Below I present the list of all the imports required for this article:
from pytube import YouTube
# misc
import os
import shutil
import math
import datetime
# plots
import matplotlib.pyplot as plt
%matplotlib inline
# image operation
import cv2
Downloading a video
In this part, I present how to download a YouTube video using Python. I will use a classic video game from GameBoy – Mega Man: Dr. Wily’s Revenge. The first step is to create an instance of the YouTube
class using the link to the video we want to download.
video = YouTube('https://www.youtube.com/watch?v=NqC_1GuY3dw')
Using this object, we can download the video/audio, and inspect some of the properties of the video itself. Some of the interesting methods we can use are:
length
– length of the video in secondsrating
– the rating of the videoviews
– the number of views
The next step is to inspect the available streams using the streams
method. We can chain it with the all
method to see all the available streams.
video.streams.all()
Running that line of code returns the following list of media formats:
For a more in-depth description of the options regarding the media formats and working with streams, I refer to pytube
‘s documentation available here.
Let’s narrow down all the available streams to mp4 files using the filter method:
video.streams.filter(file_extension = "mp4").all()
Running the code results in the following selection:
In this case, we will use the first available option, the one in 360p (resolution). To download the video, we first indicate which one we want to download by using the itag
and then download the file using the download
method. The full code for downloading the video is as follows:
video.streams.get_by_itag(18).download()
In the download
method, we can also specify the destination path for the video. The default value is the current directory.
Extract frames from the video
I created a special class called FrameExtractor
to – as the name pretty much reveals it – extract individual frames from the video and save them as images. The class is defined as follows:
While instantiating the object of the FrameExtractor
class, we need to provide the path to the video we want to work with. In the __init__
method, we also extract some characteristics of the video such as the total number of frames and the frames per second (FPS). In general, the class provides functionality to extract every x-th frame from the video, as the difference between any two neighboring frames will be minimal. We provide a few convenience methods as well. All the methods are described below:
get_video_duration
– prints the duration of the videoget_n_images
– prints the number of images that will be extracted given we extract every x-th frame (indicated byevery_x_frame
)extract_frames
– this is the main method of the class, which is used to extract the images. The bare minimum is providing the value forevery_x_frame
and the name of the image (the numbers indicating the sequence will be added automatically at the end of the name). By default, the images will be saved in the current directory. We can also provide a path to the desired directory (dest_path
), and if it does not exist, it will be created for us. We can also specify the format of the image file, the default is JPG.
Now it is time to actually use the class. We start by instantiating the object of the FrameExtractor
class:
fe = FrameExtractor('Game Boy Longplay [009] Mega Man Dr Wilys Revenge.mp4')
Next, we investigate the length of the video:
fe.get_video_duration()
# Duration: 0:39:48.333333
As an example, let’s assume we want to extract every 1000th frame. To calculate the number of images extracted using this setting, we run:
fe.get_n_images(every_x_frame=1000)
# Extracting every 1000 (nd/rd/th) frame would result in 71 images.
As the last step, we extract the images:
fe.extract_frames(every_x_frame=1000,
img_name='megaman',
dest_path='megaman_images')
# Created the following directory: megaman_images
The indicated directory did not exist prior to using the extract_frames
method, so it was automatically created and we saw a printed statement confirming this.
Finally, we define a short function for viewing the downloaded images:
def show_image(path):
image = cv2.imread(path)
plt.imshow(image)
plt.show()
show_image('megaman_images/megaman_61.jpg')
Running the code results in displaying the following image:

Conclusions
In this article, I described how to download videos from YouTube using the pytube3
library and coded a custom class used for extracting frames as images from the downloaded videos. A potential modification to the class is to account for skipping the first n seconds of the video, as the beginning often contains title screens, company logos, etc. The same could be done about the end of the video. However, for the time being, we can also account for that by manually deleting the images that are of no use to us.
You can find the code used for this article on my GitHub. As always, any constructive feedback is welcome. You can reach out to me on Twitter or in the comments.
Liked the article? Become a Medium member to continue learning by reading without limits. If you use this link to become a member, you will support me at no extra cost to you. Thanks in advance and see you around!
I recently published a book on using Python for solving practical tasks in the financial domain. If you are interested, I posted an article introducing the contents of the book. You can get the book on Amazon or Packt’s website.