今回の自作ツールは、「YouTubeダウンロードツール」です。YouTubeダウンロードツールは有料・無料含めて数多く存在します。
無料で使えるものはダウンロード数が制限されていたり、透かしが入ったりで使い物にならないケースも多く、有料版はYouTube以外がダウンロードできるものの、それなりの費用が掛かります。
今回紹介する「YouTubeダウンロードツール」は、もちろん無料で制限も一切掛かりません。もちろん、YouTube側でダウンロード不可の設定が行われているものはダメですが、たいていのYouTube動画はダウンロードできると思います。
PythonでYouTube動画をダウンロードしたい方は、本記事を参考にトライしてみてください。
自作ツールを作るためのポイントと今後公開予定の自作ツール一覧を「【実践】Pythonで事務処理向け自作ツールを作ろう!」で紹介していますので、併せてご覧ください。
YouTubeダウンロードツールの紹介
今回紹介する自作ツールはYouTubeの動画ダウンローダーです。YouTube動画のURLをまとめて入力しておけば、順番にダウンロードしてくれます
- 1つのYouTube動画には画質が異なる複数の動画ファイルがアップロードされていますが、その中から最高品質の動画のみをダウンロードします。
- 動画アドレス一覧、保存先フォルダ名に入力した内容は保持され、次回起動時に復元されます。
- 保存先フォルダに保存された、拡張子 .webmの動画ファイルをmp4に変換したり、mp4の動画をmp3に変換することが可能です。
画面レイアウト
使い方
動画のダウンロード
動画アドレス一覧に入力したYouTube動画のアドレスに対して、上から順にダウンロードします。
- 動画アドレス一覧にダウンロードしたい動画アドレスを入力します。
動画アドレスを記載したテキストファイルをドラッグ&ドロップする方法でも入力が可能です。 - ダウンロードした動画を保存するためのフォルダを指定します。
- 「実行」ボタンをクリックします。
webm⇒mp4 変換
「保存先フォルダ」に置かれている、拡張子 ".Webm" のファイルを mp4形式の動画ファイルに変換します。
- フォルダ拡張子がwebm のファイルが保存されているフォルダを「保存先フォルダ」で選択します。
- webm⇒mp4のスイッチをONにします。
- 「変換」ボタンをクリックします。
動画⇒mp3 変換
「保存先フォルダ」に置かれている動画ファイルから音声データを取り出し、 mp3形式で保存します。
- 拡張子 ".webm" のファイルが保存されているフォルダを「保存先フォルダ」で選択します。
- 動画⇒mp3のスイッチをONにします。
- 「変換」ボタンをクリックします。
プログラムのダウンロードと動作環境の設定
Pythonと ffmpegのインストールが必要です。既に構築済みの方は無視して下さい。詳細は下記の個別記事をご覧ください。
自作ツールのためのポータブルPython開発・実行環境を作ろう! | プログラム実行時に必要 |
WinPython環境に ffmpeg を入れよう! | プログラム実行時に必要 |
WinPythonにVSCode Portable版を入れよう! | プログラム修正時に必要 |
Python 環境に下記のライブラリをインストールします。 command.bat を実行後、下記のコマンドを実行します。
pip install yt-dlp
pip install customtkinter
pip install CTkListbox
pip install pandas
pip install Pillow
pip install tkinterdnd2
下記のリンクからZipファイルをダウンロード&解凍します。次に、Python環境の任意の場所にフォルダを作成し、そこに解凍したファイル(6個)をコピーしてください。
YouTubeダウンロードツール
実行方法
次の手順で実行してください。
- WinPython のインストールフォルダ内にある command.bat を実行
- ダウンロードしたプログラムファイルをコピーした場所にカレントディレクトリを移動
- Python ui.py を実行
Python ui.py
しばらくすると下記の画面が表示されます。あとは本記事の最初で説明した使い方に沿って実行してください。
ダウンロード中はコマンドプロンプトに進行状況が表示されます。
YouTubeダウンロードツールの設計
以下は、プログラム作成にあたって必要事項を取りまとめた内容になります。単にYouTube動画をダウンロードしたい方は、無視して頂いて構いません。
ただ、DIYプログラミングにおいて参考になると思いますので、興味のある方は最後までお付き合いください。
仕様
画面項目 | 説明 |
---|---|
動画アドレス一覧 | 動画アドレスの入力欄。動画アドレスは複数行の入力が可能。 テキストファイルで保存された動画アドレス一覧をドラッグ&ドロップで読み込み可能 |
保存先フォルダ | ダウンロードした動画ファイルの保存先を指定。 フォルダをドラッグ&ドロップで指定することも可能。 |
開くボタン | フォルダ選択ダイアログを表示し、動画ファイル保存先が選択できる。 |
変換ボタン | 保存先フォルダに存在する動画ファイルに対して、「Web→mp4一括変換」、及び「動画→mp3一括変換」のチェック状態に応じてフォーマット変換を行う。 |
Webm→mp4一括変換 | 保存先フォルダに存在する、拡張子が ".webm" の動画ファイルすべてを対象に、mp4形式に変換する。 |
動画→mp3一括変換 | 保存先フォルダに存在する、拡張子が ".webm" の動画ファイルすべてを対象に、mp3形式に変換する。 |
実現方法
- 画面はCustomTkinter で作成
- YouTubeダウンロード機能は、yt_dlp を使用する(詳細はyt_dlp公式ページを参照)
- webm→mp4、動画→mp3の変換は ffmpeg を使用する(詳細は ffmpeg公式ページを参照)
プログラムの構成
本プログラムは5つの py ファイルで構成しています。この程度の規模なら1つのpyファイルにまとめても良いのですが、再利用性や拡張性を考慮し、あえて機能単位にファイルを分割しました。
モジュール名 | 役割 |
---|---|
ui.py | ユーザインターフェースを担当 |
manage.py | 画面の入力情報を用いて、youtube_dlとmovie_convert を適切に呼び出す |
customtkintercontrols.py | ファイル選択やフォルダ選択、ドラッグ&ドロップを実現するための補助 |
movie_convert.py | ffmpeg を使って動画変換を行う |
youtube_dl.py | 指定された動画アドレスから動画をダウンロードする |
appconfig.py | 画面に入力された値をJson形式のファイルに保存/読込する |
個々の処理手順
「実行」と「変換」ボタンがクリックされた時の処理を、簡易的なフローチャートで表現しました。
ソースコード
ui.py
import os
import manager as man
import customtkinter as ctk
from customtkintercontrols import App
from customtkintercontrols import FolderSelectionControl
from customtkintercontrols import TextBoxControl
from appconfig import AppConfig
# -----------------------------------------------
# コールバック関数の定義
# -----------------------------------------------
# ウィンドウを閉じる時に呼ばれる関数
def close_window():
# 画面入力値を保存
conf.set("folder",folder_selection.get())
conf.set("urls",textbox.get())
conf.write()
# プログラムの終了
app.quit()
# ダウンロードボタンが押された時に呼ばれる関数
def download():
urls = textbox.get()
folder = folder_selection.get()
man.download(urls.split('\n'),folder)
# 変換ボタンが押された時に呼ばれる関数
def convert():
folder = folder_selection.get()
iswebm2mp4 = switch1.get()
ismovie2mp3 = switch2.get()
man.convert(folder,iswebm2mp4,ismovie2mp3)
# -----------------------------------------------
# メインウインドウの定義
# -----------------------------------------------
# 前回入力値の保存・復元用インスタンスの生成
conf = AppConfig("./config.json")
# メインウィンドウの作成
app = App()
app.minsize(width=500, height=500)
app.geometry(f"800x600")
app.title("YouTubeダウンローダー")
# customtkinterをダークモードに設定
ctk.set_appearance_mode("dark")
# ウィンドウを閉じる時に呼びたい関数を登録
app.protocol("WM_DELETE_WINDOW", close_window)
# -----------------------------------------------
# 画面レイアウト(ウィジェット)の定義
# -----------------------------------------------
# YouTubeダウンロードボタンと動画アドレス入力欄をグループ化
group0 = ctk.CTkFrame(app)
group1 = ctk.CTkFrame(group0)
label1 = ctk.CTkLabel(group1 , text="YouTube動画アドレス一覧")
label1.pack(padx=10,pady=10,side="left")
download_button = ctk.CTkButton(group1 , text="実行",command=download)
download_button.pack(padx=10,pady=10,side="right")
group1.pack(padx=10,pady=10,fill="x")
textbox = TextBoxControl(group0)
textbox.pack(padx=10,pady=10,fill="both", expand=True)
# ダウンロードファイル一括変換のタイトルとボタンのグループ化
group3 = ctk.CTkFrame(app)
label3 = ctk.CTkLabel(group3 , text="ダウンロードファイル一括変換")
label3.pack(padx=10,pady=10,side="left")
convert_button = ctk.CTkButton(group3 , text="変換",command=convert)
convert_button.pack(padx=10,pady=10,side="right")
# mp4,mp3 一括変換のスイッチのウィジェットをグループ化
group4 = ctk.CTkFrame(group3)
switch1 = ctk.CTkSwitch(group4, text="Webm ⇒ mp4一括変換")
switch1.pack(padx=10,pady=10,side="left")
switch2 = ctk.CTkSwitch(group4, text="動画 ⇒ mp3一括変換")
switch2.pack(padx=10,pady=10,side="left")
# グループ0メインウィンドウに配置
group0.pack(padx=10,pady=10,fill="both", expand=True)
# フォルダ選択ダイアログをメインウィンドウに配置
folder_selection = FolderSelectionControl(app)
folder_selection.label.configure(text="保存先フォルダ名")
folder_selection.pack(padx=10,pady=10,fill="x")
# グループ3と4をメインウィンドウに配置
group3.pack(padx=10,pady=10,fill="x")
group4.pack(padx=10,pady=10,fill="x")
# -----------------------------------------------
# 前回実行時の画面入力値を復元
# -----------------------------------------------
# テキストボックスの内容を復元
textbox.set(conf.get("urls",""))
# 保存先フォルダの値を復元
folder_selection.set(conf.get("folder"))
if folder_selection.get() == "":
folder_selection.set(os.getcwd())
# -----------------------------------------------
# CustomTkinterの起動
# -----------------------------------------------
# メインループを開始
app.mainloop()
manager.py
import youtube_dl as ydl
import movie_convert as mvc
import os
import glob
def download(urls,folder):
"""
指定したURLからTueTube動画をダウンロードします
Args:
urls (list): ダウンロードする動画のURLのリスト。
folder (str): 動画ファイルを保存するフォルダのパス。
Returns:
None
"""
for url in urls:
ydl.download(folder,url)
def convert(folder,isconv_mp4,isconv_mp3):
"""
指定したフォルダ内の動画ファイルを変換します。
Args:
folder (str): 動画ファイルを検索するフォルダのパス。
isconv_mp4 (bool): Trueの場合、WebM形式の動画をMP4形式に変換します。
isconv_mp3 (bool): Trueの場合、動画を音声ファイル(MP3)に変換します。
Returns:
None
"""
video_files = glob.glob(os.path.join(folder, f'*.*'))
for file in video_files:
if isconv_mp3:
mvc.movie_to_mp3(file)
if isconv_mp4:
mvc.webm_to_mp4(file)
youtube_dl.py
import os
import yt_dlp
def download(folder, url):
"""
YouTube 動画をダウンロードします。
Args:
folder (str): ダウンロードした動画を保存するフォルダのパス。
url (str): ダウンロードする YouTube 動画の URL。
Returns:
tuple: ダウンロード結果と保存されたファイル名のタプル。
- result (int): ダウンロード結果 (0: 成功, 1: 失敗)
- filename (str): 保存されたファイル名
"""
# オプションを指定(最高画質の動画と最高音質の音声を取り出し結合するためのオプション)
options = {
'outtmpl': os.path.join(folder, '%(title)s.%(ext)s'),
'format': 'bestvideo+bestaudio/best'
}
with yt_dlp.YoutubeDL(options) as ydl:
# 動画情報を取得
info_dict = ydl.extract_info(url, download=False)
# ファイル名を取得
filename = ydl.prepare_filename(info_dict)
# ダウンロードの実行
result = ydl.download([url])
return result, filename
まとめ
今回は、「YouTubeダウンロードツール」について、使い方から環境構築に至るまでの手順を解説しました。また、実際に私がこのツールを作るにあたって、事前に検討した内容も併せて紹介しました。
記事の中にソースコードも張り付けていますし、Chat GPT 君にコメントも追加してもらいましたので、初学者の方でも、どこで何をやっているかの大枠は理解できるのではないかと思います。
プログラムはできだけ再利用できるよう、機能単位で分割していますので、画面だけ別のものに置き換えるのも比較的容易かと思います。
今回の記事を参考に、皆さん独自のYouTubeダウンロードツールを作ってみてはいかがでしょうか。
コメント