切り抜き動画などの二次創作物を作ったりトレーニング中のBGMにしたりと、様々なシーンでyoutube上の動画をダウンロードしてローカルで利用したいな~って方も多いと思いますんで、pythonを使って簡単にyoutube上の動画をダウンロードする方法を調べてみました。
仕上がりはこんな感じ
めっちゃ早くて快適!
yt-dlp自体に違法性はなし(たぶん)
yt-dlpの前身である「youtube-dl」ライブラリは版権ビジネスを展開する企業から差し止め要求を受けるなど、利便性と違法性の間に挟まれ議論が続いているのが現状です。経緯をまとめると、
- youtubeの動画を簡単にダウンロードできる「youtube-dl」がgitに公開される
- 音楽・映画・アニメなどの商業コンテンツがyoutube上からユーザーにダウンロードされる
- 権利保有者がキレて、youtube-dlを公開するgitに削除を要求(DMCA第1201条違反だろ!)
- git側が一旦youtube-dlを削除。(ちょっと検証します)
- 有識者や弁護団からの支援を受けyoutube-dlが復活!(DMCA第1201条に違反してない!)
- 権利者再燃、youtube-dlが利用するホスティング会社に狙いを変え訴訟を起こす
- デジタル著作権に詳しいニュースメディア「netzpolitik.org」がyoutube-dlを支援
- 泥沼化へ…
この通り、技術的・法律的な視点だとyoutube-dlが規制される理由は無さそうですが、とはいえ権利保有者側からすると実害が出てるんだから公開やめろや!という、いたちごっこになっているという状況ですね。
僕の個人的な見解だとyt-dlpのようなyoutube動画をダウンロードするライブラリ自体に違法性は無いと僕も思います。ただし、ライブラリうんぬんとか方法はどうでもよくて権利保有者の許諾なくコンテンツをコピーするのは法律上もyoutube規約上も基本アウトなので誤解しないように気を付けましょ。
ルール上アウトではあるが、一般人が自分の家で楽しむ目的であったりtiwtterのアイコンに商業キャラクターの画像使ったりするなどは、社会通念上個人で楽しむ範囲に限って権利者の温情で見逃して貰っているだけというのは理解しておいた方がいいでしょうね。
使い方
yt-dlpはとんでもない数の動画サイトのダウンロードに対応していますが、今回はyoutube動画のダウンロードにフォーカスしてコピペコードをご紹介します。
コマンドラインから呼び出す
yt-dlpを用いたCLIアプリの作り方は解説しているブログがたくさんあるので、「yt-dlp cli」とかで検索して上位の記事をいくつか読めばOKだと思います。
基本的なpythonの読み書きはできる事を前提に解説していきますんで、初心者の方は手元に入門書を用意しながら読み進めると理解しやすいと思います。
スクリプトに組み込む
うちのブログではpythonスクリプトでの組み込みをメインに解説してみます、まずはyt-dlpをインストールします。
pip install yt-dlp
後は最短3行でyoutube動画をダウンロード可能です。
from yt_dlp import YoutubeDL
with YoutubeDL() as ydl:
result = ydl.download(['https://www.youtube.com/watch?v=jQkdpQdVa7w'])
サンプル動画は最近ハマっているvtuberの大代真白さんのライブ配信動画をダウンロードしてみましょ。ちなみに所属事務所の「あおぎり高校」はファン活動に限り申請不要で動画の二次利用を認めるという太っ腹な方針です。
こんな感じで動画のダウンロード自体は簡単にできました、さらにオプションを指定する事でyt-dlpの動作を細かく指定する事ができます。
指定可能なオプション
yt-dlpでは指定できるオプションがアホみたいに多く400個近くあります。全部見てたら胸焼けをしちゃうんで、youtubeのダウンロードに便利そうな物だけを抜き出して、利用シーン別にコピペコードとしてまとめました。
アプリやサービスを開発する目的であれば一度は全部目を通して損はないです。tipsを翻訳して記事にしてくれているブログもありますんでこれなら勉強しやすいと思います。
利用シーン別コピペコード
この通り膨大なオプション値を組み合わせる事で動作をコントロールできるyt-dlpですが、選択肢が多過ぎて狙った動作をさせるためには結構勉強が必要です。
なので、ここではyoutube動画をダウンロードしたい人にニーズがありそうなケースをまとめて、そのアンサーとなるコピペスクリプトを用意しました。自分のやりたい事と近いスクリプトを下記から選んで肉付けしていけば自作アプリもスムーズに作れると思います。
動画をダウンロードする
まずは上記でも紹介したシンプル3行コード、オプションで何も指定しないでデフォルト設定で動作します。
from yt_dlp import YoutubeDL
with YoutubeDL() as ydl:
result = ydl.download(['https://www.youtube.com/watch?v=7lcKuz9clpM'])
動画URLは普通にyoutubeのURLをコピペでOK。

動画を一括ダウンロードする
動画URLの指定は配列に対応しているんで単純にカンマで区切って複数入力可能。
from yt_dlp import YoutubeDL
with YoutubeDL() as ydl:
result = ydl.download([
'https://www.youtube.com/watch?v=jQkdpQdVa7w',
'https://www.youtube.com/watch?v=jlgiFlUV63I',
'https://www.youtube.com/watch?v=7lcKuz9clpM'
])
再生リストに含まれる動画を一括ダウンロードする
再生リストのURLを指定すればごっそり動画をダウンロードする事も可能。
from yt_dlp import YoutubeDL
with YoutubeDL() as ydl:
result = ydl.download([
'https://www.youtube.com/playlist?list=PLEqTlNbeNYhpLn8ebAHA9OW91zi8WtUsh'
])
再生リストのURLはアカウントのチャンネルページからたどり着けます。


特定のアカウントが投稿した動画を一括ダウンロードする
ダウンロードはアカウントのURLにも対応しているんで、投稿されている動画を全部丸ごとダウンロードする事も可能。当然ですが数百本とか動画を投稿しているアカウントの場合、全部ダウンロードするまでに数日かかる事もあるのでご利用は計画的に。
from yt_dlp import YoutubeDL
with YoutubeDL() as ydl:
result = ydl.download([
'https://www.youtube.com/channel/UChS3C3UYjnNN2gN1IjUQTCg'
])

指定した件数だけダウンロードする
max_downloadsで指定した件数に達するとエラーが出て止まる。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl' : '%(id)s'+'_.mp4',
'format' : 'best',
'max_downloads' : '1'
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/playlist?list=PLEqTlNbeNYhpLn8ebAHA9OW91zi8WtUsh'
])
期間を指定してダウンロードする
DateRangeを使うと投稿日のからまでを指定できます。
from yt_dlp import YoutubeDL
from yt_dlp.utils import DateRange
ydl_video_opts = {
'outtmpl' : '%(id)s'+'_.mp4',
'format' : 'best',
'daterange':DateRange('20210201', '20210228')
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/playlist?list=PLEqTlNbeNYhpLn8ebAHA9OW91zi8WtUsh'
])
古い順にダウンロードする
playlistreverseにTrueを設定すると古い順に取得される。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl' : '%(id)s'+'_.mp4',
'format' : 'best',
'max_downloads' : '1',
'playlistreverse':True
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/playlist?list=PLEqTlNbeNYhpLn8ebAHA9OW91zi8WtUsh'
])
再生回数を指定してダウンロードする
再生回数はmin_viewsで以上、max_viewsで以下を指定できる。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl':'%(id)s'+'_.mp4',
'format':'best',
'min_views':100000,
'max_views':200000
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/playlist?list=PLEqTlNbeNYhpLn8ebAHA9OW91zi8WtUsh'
])
ファイルサイズを指定してダウンロードする
ファイルサイズはmin_filesizeで以上、max_filesizeで以下を指定できる。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl':'%(id)s'+'_.mp4',
'format':'best',
'min_filesize':100000,
'max_filesize':10000000
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/playlist?list=PLEqTlNbeNYhpLn8ebAHA9OW91zi8WtUsh'
])
映像のみダウンロードする
動画素材として使いたいけどちょっとでもファイルを軽くしたい時に使えるかも、複数動画の一括DLも可能。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl': '%(id)s'+'_.mp4',
'format': 'bestvideo'
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/watch?v=jQkdpQdVa7w',
'https://www.youtube.com/watch?v=jlgiFlUV63I',
'https://www.youtube.com/watch?v=7lcKuz9clpM'
])
音声のみダウンロードする
動画のみとほぼ一緒。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl': '%(id)s'+'_.mp3',
'format': 'bestaudio'
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/watch?v=jQkdpQdVa7w',
'https://www.youtube.com/watch?v=jlgiFlUV63I',
'https://www.youtube.com/watch?v=7lcKuz9clpM'
])
最高品質でダウンロードする
最高品質の動画と最高品質の音声は別々に管理されているパターンが多いのでそれぞれダウンロードして後で合体させる。なので、デフォルトのダウンロードスクリプトに比べて結構遅い。けど高品質。
from yt_dlp import YoutubeDL
from moviepy.editor import *
import os
urls = [
'https://www.youtube.com/watch?v=jQkdpQdVa7w',
'https://www.youtube.com/watch?v=jlgiFlUV63I',
'https://www.youtube.com/watch?v=7lcKuz9clpM'
]
for url in urls:
#メタデータ取得
with YoutubeDL() as ydl:
res = ydl.extract_info(url, download=False)
#動画取得
ydl_video_opts = {
'outtmpl': 'video.mp4',
'format': 'bestvideo/best'
}
with YoutubeDL(ydl_video_opts) as ydl:
ydl.download([url])
#音声取得
ydl_audio_opts = {
'outtmpl': 'audio.mp3',
'format': 'bestaudio/best'
}
with YoutubeDL(ydl_audio_opts) as ydl:
ydl.download([url])
#動画・音声結合&出力
videoclip = VideoFileClip("video.mp4")
audioclip = AudioFileClip("audio.mp3")
output_video = videoclip.set_audio(audioclip)
output_video.write_videofile(res['id'] + ".mp4")
#一時ファイルの削除
os.remove('video.mp4')
os.remove('audio.mp3')
チャットを取得する
ライブ配信動画(アーカイブでもOK)であればチャットも取得できる。けど、ファイルの中身は分かりづらい。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl' : '%(id)s'+'_.mp4',
'format' : 'best',
'writesubtitles' : True,
'skip_download' : True
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/watch?v=r5T79dPDgM8'
])
分かりやすいチャットデータの取得方法は下記の記事で解説しています。
メタデータを取得する
メタデータを取得するextract_infoは配列に対応していない(なんでやねん)ので、複数動画を一括で処理するにはforとかで繰り返す必要あり。
from yt_dlp import YoutubeDL
url = 'https://www.youtube.com/watch?v=tHZY15gQ65o'
#メタデータ取得
with YoutubeDL() as ydl:
res = ydl.extract_info(url, download=False)
#下記一覧の名称をキーに指定
print(res['id'])
:
:
:
print(res['audio_channels'])
メタデータに含まれる要素は下記の通り。わからん要素も多いですが原因はおそらくyt-dlpが複数の動画サイトに対応しているのでそれぞれ入ってくる値が違うんだと思います。今回youtubeでしか試していないので、中身が重複してたりブランクだったりする要素も多かったです。
名称 | 内容 |
id | 動画ID |
title | 動画タイトル |
formats | 動画のフォーマットが配列でいっぱい入っている |
thumbnails | デフォのサムネ・カスタムサムネがサイズ別で複数 |
thumbnail | 現在設定されているサムネ |
description | 動画概要欄 |
uploader | 投稿者名 |
uploader_id | 投稿者ID |
uploader_url | 投稿者URL |
channel_id | チャンネルID |
channel_url | チャンネルURL |
duration | 再生時間(秒) |
view_count | 再生回数 |
average_rating | 機能していない?(平均評価のハズ) |
age_limit | 年齢制限:0でなし、18なら18以上? |
webpage_url | 動画URL |
categories | 動画カテゴリ |
tags | 動画タグのリスト |
playable_in_embed | 埋め込み可否:True or False |
live_status | not_live(配信じゃない), is_live(配信中), was_live(アーカイブ) |
release_timestamp | 配信開始日時(ライブのみ) |
automatic_captions | 自動生成字幕のタイムテーブル、[‘ja’]とかで言語を指定できる |
subtitles | 謎。 |
comment_count | コメント数 |
chapters | チャプター情報 |
like_count | いいね |
channel | チャンネル名 |
channel_follower_count | チャンネル登録者数 |
upload_date | アップロードした日 |
availability | 動画の公開状態:private、premium_only、subscriber_only、needs_auth、unlisted、public |
original_url | 動画ページのURL、webpage_urlとの違いは分からん。誰か教えて。 |
webpage_url_basename | 動画ページのディレクトリ名(たぶん) |
webpage_url_domain | 動画サイトのドメイン |
extractor | 動画サイトのドメイン名 |
extractor_key | 動画サイトの識別子(わからん) |
playlist | プレイリスト名(未検証) |
playlist_index | プレイリスト内動画のインデックス番号(未検証) |
display_id | 動画ID、idとの違いがわからん |
fulltitle | 動画タイトル、titleとの違いわからん |
duration_string | 再生時間(時分秒) |
is_live | ライブ配信中か、True or False |
was_live | アーカイブか、True or False |
requested_subtitles | 謎。 |
_has_drm | 謎。 |
requested_formats | 動画のフォーマット |
format | デフォルトの動画フォーマット |
format_id | デフォルトの動画フォーマット、IDだけ |
ext | 動画ファイルの拡張子 |
protocol | ダウンロード時のプロトコル |
language | 言語、noneしか出ないけど |
format_note | 画質 |
filesize_approx | ファイルサイズ |
tbr | 平均ビットレート |
width | 横サイズ |
height | 縦サイズ |
resolution | 解像度 |
fps | フレームレート |
dynamic_range | 動画のダイナミックレンジ、SDR/HDR |
vcodec | ビデオコーデック |
vbr | 映像ビットレート |
stretched_ratio | 動画の幅、高さ(アスペクト比かも) |
acodec | 音声コーデック |
abr | 音声ビットレート |
asr | 音声のサンプリングレート |
audio_channels | 音声のチャンネル数 |
年齢制限・メンバー限定動画ダウンロードする
ログインする事でアカウント内での動作になる。メンバーシップ限定動画をダウンロードするとか?僕はどこにもメンバーシップに加入してないしテストのためにお金払うの勿体ないので未検証、すみませぬ。
from yt_dlp import YoutubeDL
ydl_video_opts = {
'outtmpl' : '%(id)s'+'_.mp4',
'format' : 'best',
'username' : 'ユーザー名',
'password' : 'パスワード'
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download([
'https://www.youtube.com/watch?v=1rn6wf-wALQ'
])
まとめ
とりあえず使えそうなコピペコードをだーっと用意してみました、重要なのは動画のダウンロード部分だと思うのでメタデータの取得とは限定的な利用になる気がします。youtubeAPIでもメタデータは取得できるので、動画の情報が必要な場合はどっちがいいか検討してみていいかもしれませんね。
個人開発プログラマーを応援するメンバーシップを始めました('ω')ノ
質問・要望・共同作業など、みんなのやりたい事をスマイルがお手伝いします。立ち上げたばかりでよく分かってないので、とりあえず何でもありやってみます。
コメント