pytube pythonでyoutubeの動画ダウンローダを作る

今回はyoutubeから動画のダウンロードを行うためのライブラリ、pytubeを用いてyoutubeのダウンローダを作成する方法についてです。

pytubeの導入から、実際にダウンロードを行うサンプルプログラムでの解説など、丁寧に説明していきたいと思います。

youtubeからダウンロードすることのできる動画の種類

youtubeに少し詳しい方ならわかると思いますが、youtubeで動画を視聴する際に画質を選択するボタンがあると思います。

動画によってまちまちですが、1080p HD、720p HD、480p、320p、、、
などなど、たくさんの種類の解像度が選択できるようになっています。

つまり、どの解像度の動画をダウンロードするかを選択して保存する必要があります。

pytubeで動画をダウンロードする際にも、
ダウンロードできる動画のリストを取得 -> その中から保存したいものを選ぶ

という流れでダウンロードを行います。

pytubeのインストール

早速、pytubeをインストールしていきましょう。

pytubeはpythonのパッケージ管理ツール、pipを用いてインストールすることができます。

$ pip install pytube

この一行をターミナルに打ち込むだけで、pytubeが使用可能となります。

pytubeのgithubアカウント

pytubeのgithubアカウントはいかになります。

https://github.com/nficano/pytube

youtubeの仕様変更などにより、一時的にpytubeが使用できなくなることがあります。
(youtube側が404エラーを吐く等)
そのようなエラーがあるときは、pytubeのgithubにissueが上がっていないか確認してみましょう。

サンプルコード

githubにpytubeを用いてyoutubeから動画をダウンロードするコードを上げてみました。

pytubeそのものの使い方を学びたい方は以下で使い方を解説しますが、
すぐ使いたい方はこちらをみてみてください。

https://github.com/myrobo/youtube_dl

動画をダウンロードする一番シンプルなサンプルコード

まずはじめに、githubのチュートリアルにも記載されている一番シンプルなサンプルコードをみていきましょう。

#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

from pytube import YouTube
YouTube( "http://youtube.com/watch?v=xxxxxxxxxx" ).streams.first().download()

チュートリアルのコードをsample1.pyとして記述した、ごくごくシンプルなサンプルコードになります。

このコードのv=xxxxxxxxxxの部分にyoutubeのアドレスの該当する文字列を記入すれば、これだけでも使用可能です。

<解説>

from pytube import YouTube
pytubeを使います。という宣言をここでしています。

YouTube( “http://youtube.com/watch?v=xxxxxxxxxx” ).streams.first().download()
この部分で、youtubeのアドレスからダウンロードできる動画のリストを取得しています。

YouTube( “http://youtube.com/watch?v=xxxxxxxxxx” ).streams.first().download()
末尾の部分で、リストの中の一番上のものをダウンロードする。といったオペレーションをしています。

感の良い方はお気づきかもしれませんが、こちらのサンプルコードはダウンロード可能なリストの一番上のものに決め打ちしてダウンロードしています。

なので、動画によっては180pという超超低画質なものがダウンロードされる可能性があったり、最悪の場合は音声のみのファイルや、動画のみのファイルがダウンロードされる場合もあります。

また、youtubeのアドレスをファイルを開いて毎回編集するという作業も必要となってしまいます。

そこで、このサンプルコードをベースに改良を加えていきます。

引数からのyoutubeアドレス入力に対応させたサンプルコード

先ほどのサンプルコードを改良してコマンドライン引数からyoutubeのアドレスを入力できるようにしてみます。

つまり、

$ python youtube_downloader1.py https://youtube.com/watch?v=xxxxxxxxxx

このようにターミナルに入力することで動画をダウンロードできるようにしてみます。

#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

from pytube import YouTube
import sys

if len( sys.argv ) != 2:
     print( "引数の数に謝りがあります。")
     sys.exit()

download_link = sys.argv[1]
YouTube( download_link ).streams.first().download()

<解説>

if len( sys.argv ) != 2:
     print( "引数の数に謝りがあります。")
     sys.exit()

この部分では、引数の数のエラー処理を行なっています。
引数の数が正しくなかった場合にはここで処理を中止します。

download_link = sys.argv[1]
YouTube( download_link ).streams.first().download()

引数の数が正しかった場合には、引数をダウンロードのリンクとしてpytubeの関数に渡します。

ダウンロード可能なリストの中から選択してダウンロードする

次に、ダウンロードできる動画リストを表示して、どれをダウンロードするかを選択できるように改良してみます。

#!/usr/local/bin/python3
# -*- coding: utf-8 -*-

from pytube import YouTube
import sys

download_directory = "/home/username/Video"

if len( sys.argv ) != 2:
     print( "引数の数に謝りがあります。")
     sys.exit()

download_link = sys.argv[1]

# ダウンロード可能なリストを表示する
available_list = YouTube( download_kink ).streams.all()
for element in available_list:
     print( element )

# この時点でコンソールのダウンロード可能なリストが表示される
# この中から、ダウンロードしたいもののitag番号をユーザ側で入力する
print( "ダウンロードするファイルのitag番号を入力してください。" )
itag = input( ">>>" )

# 入力されたitagを用いて動画をダウンロード
YouTube( download_link ).streams.get_by_itag( itag ).download( download_directory )

先ほどのサンプルからさらに手を加えた所について解説していきます

<解説>

download_directory = "/home/username/Video"

動画の保存先を指定できるようにしてみました。各自保存したい場所に変更して使用してください。
後で使用します。

# ダウンロード可能なリストを表示する
available_list = YouTube( download_kink ).streams.all()
for element in available_list:
     print( element )

この部分で、ダウンロード可能なリストをコンソールに表示しています。
例えば某動画の場合、リストは以下のような形で表示されます。

<Stream: itag="18" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.42001E" acodec="mp4a.40.2">
<Stream: itag="36" mime_type="video/3gpp" res="240p" fps="30fps" vcodec="mp4v.20.3" acodec="mp4a.40.2">
<Stream: itag="17" mime_type="video/3gpp" res="144p" fps="30fps" vcodec="mp4v.20.3" acodec="mp4a.40.2">
<Stream: itag="137" mime_type="video/mp4" res="1080p" fps="30fps" vcodec="avc1.640028">
<Stream: itag="248" mime_type="video/webm" res="1080p" fps="30fps" vcodec="vp9">
<Stream: itag="136" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.4d401f">
<Stream: itag="247" mime_type="video/webm" res="720p" fps="30fps" vcodec="vp9">
<Stream: itag="135" mime_type="video/mp4" res="480p" fps="30fps" vcodec="avc1.4d401f">
<Stream: itag="244" mime_type="video/webm" res="480p" fps="30fps" vcodec="vp9">
<Stream: itag="134" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.4d401e">
<Stream: itag="243" mime_type="video/webm" res="360p" fps="30fps" vcodec="vp9">
<Stream: itag="133" mime_type="video/mp4" res="240p" fps="30fps" vcodec="avc1.4d4015">
<Stream: itag="242" mime_type="video/webm" res="240p" fps="30fps" vcodec="vp9">
<Stream: itag="160" mime_type="video/mp4" res="144p" fps="30fps" vcodec="avc1.4d400c">
<Stream: itag="278" mime_type="video/webm" res="144p" fps="30fps" vcodec="vp9">
<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2">
<Stream: itag="171" mime_type="audio/webm" abr="128kbps" acodec="vorbis">
<Stream: itag="249" mime_type="audio/webm" abr="50kbps" acodec="opus">
<Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus">
<Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus">

このように、動画リストにはitagと呼ばれる識別子がついています。
今回はこのitagを指定することで、ダウンロードする動画を指定します。

ダウンロードできるファイルにも様々なものがあり、mime_type が video/mp4 となっているのが動画ファイルとなります。
audio/mp4 となっているのは音声のみのファイルとなります。
また、video/mp4 となっているものでも、高解像度のものは動画のみのものがあることもありますので注意が必要です。

mime_typeが video/webm となっているものもあり、こちらも動画ファイルなのですが、mp4の方がメジャーで使いやすいと思いますので、特にこだわりがないのであればmp4のものを指定してあげれば良いと思います。

# この時点でコンソールのダウンロード可能なリストが表示される
# この中から、ダウンロードしたいもののitag番号をユーザ側で入力する
print( "ダウンロードするファイルのitag番号を入力してください。" )
itag = input( ">>>" )

この部分では、ユーザのitag入力を読み込む部分となります。

コンソールにはこのように表示されるので、>>>の後にitagを打ち込み、エンターを押します。
例えば、先ほどのリストで video/mp4 の720p ( itag : 136 )の動画が欲しいなら、

ダウンロードするファイルのitag番号を入力してください。
>>> 136

136とタイプしてエンターを押します。

# 入力されたitagを用いて動画をダウンロード
YouTube( download_link ).streams.get_by_itag( itag ).download( download_directory )

この部分にて、先ほど入力したitagをもつ動画をダウンロードしてきます。

.download( download_directory )
とすることで、動画の保存先を指定することができます。

追記(pytubeのバージョンを上げる)

時々、youtubeの仕様変更に伴い、pytubeがエクセプションを投げてくることがあります。

最近私はこのようなエラーに遭遇したことがありました。
pytube.exceptions.RegexMatchError: regex pattern ((?:v=|\/)([0-9A-Za-z_-]{11}).*) had zero matches

このような場合は、インストールされているpytubeのバーションを上げることで解決することがあります。

以下のコマンドでpytubeのバーションを上げましょう。

$ pip install --upgrade pytube

以上、pytubeの使い方でした。