YouTube から音声を抽出したいとき、ブラウザのオンラインツールでは「1ファイルずつ」「128kbps MP3のみ」「広告だらけ」という制限に直面することが多いです。Pythonスクリプトでyt-dlpを使えば、プレイリスト一括処理・WAV/FLAC高品質出力・エラー自動リトライが全て自動化できます。
この記事では、yt-dlpのPythonライブラリとしての使い方を実践的にまとめます。コマンドライン基礎から始め、バッチ処理・フォーマット制御・認証動画の取得まで、そのまま使えるコードブロック付きで解説します。
ブラウザやGUIで手軽に済ませたい場合は YouTubeから音声を抽出する方法7選(ブラウザ〜CLI) にまとめています。
yt-dlpとは?なぜ最善の選択か?
結論:yt-dlpはyoutube-dlのアクティブなフォーク版で、2026年現在も活発にメンテナンスされている唯一の信頼できるYouTube音声抽出ライブラリです。
| ライブラリ | 状態(2026年) | 最大品質 | Python API |
|---|---|---|---|
| yt-dlp | ✅ 活発にメンテナンス中 | WAV / FLAC / 320kbps MP3 | ✓ |
| youtube-dl | ⚠️ 更新停滞(非推奨) | MP3 | ✓ |
| pytube / pytubefix | ⚠️ 頻繁に壊れる | MP4のみ(音声別途抽出要) | ✓ |
| moviepy | ❌ ラッパーのみ | MP3 / WAV(低効率) | ✓ |
yt-dlpがyoutube-dl・pytube・moviepyより優れている理由は、YouTube APIの変更に追随するスピードが圧倒的に速いためです。pytube系は数ヶ月に一度「突然動かなくなる」現象が起きますが、yt-dlpは数日以内に修正されます。
インストール
pip install yt-dlp
# ffmpegも必要(フォーマット変換に使用)
# macOS
brew install ffmpeg
# Ubuntu/Debian
sudo apt install ffmpeg
# Windows: https://ffmpeg.org/download.html
バージョン確認:
yt-dlp --version
# 2026.xx.xx
コマンドラインでの基本的な音声抽出(おさらい)
# MP3(320kbps)
yt-dlp -x --audio-format mp3 --audio-quality 0 "URL"
# WAV(可逆)
yt-dlp -x --audio-format wav "URL"
# FLAC(可逆圧縮)
yt-dlp -x --audio-format flac "URL"
--audio-quality 0 は最高ビットレートを指定します(MP3の場合は320kbps)。
次のセクションから、Pythonスクリプトとして組み込む方法を説明します。
PythonスクリプトからYDL(YoutubeDL)クラスを使う
yt-dlpはコマンドラインツールですが、yt_dlp.YoutubeDL クラスを直接インポートしてPythonから制御できます。
シンプルなMP3抽出
import yt_dlp
def extract_audio_mp3(url: str, output_dir: str = ".") -> str:
"""YouTube URLからMP3(320kbps)を抽出してファイルパスを返す。"""
ydl_opts = {
"format": "bestaudio/best",
"outtmpl": f"{output_dir}/%(title)s.%(ext)s",
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
"preferredquality": "320",
}
],
"quiet": True,
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
title = info.get("title", "audio")
return f"{output_dir}/{title}.mp3"
if __name__ == "__main__":
path = extract_audio_mp3("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
print(f"保存先: {path}")
WAV(可逆)抽出
import yt_dlp
from pathlib import Path
def extract_audio_wav(url: str, output_dir: str = ".") -> Path:
"""YouTube URLからWAV(可逆)を抽出してPathを返す。"""
ydl_opts = {
"format": "bestaudio/best",
"outtmpl": f"{output_dir}/%(id)s.%(ext)s",
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "wav",
}
],
"quiet": True,
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
video_id = info["id"]
return Path(output_dir) / f"{video_id}.wav"
YouTubeの音声はOpus(最大160kbps)またはAAC(最大256kbps)でエンコードされています。WAVやFLACで保存しても、元データがそのビットレートのため「可逆」ではなく「再エンコードなし」の意味です。実質的な上限は元ストリームの品質です。
バッチ処理:複数URLを一括抽出
URLリストをファイルから読み込んで一括処理する実装です。
import yt_dlp
from pathlib import Path
def batch_extract(urls: list[str], output_dir: str = "downloads") -> dict[str, str]:
"""
複数URLから音声を一括抽出する。
戻り値: {url: 保存先パス or エラーメッセージ}
"""
Path(output_dir).mkdir(exist_ok=True)
results: dict[str, str] = {}
ydl_opts = {
"format": "bestaudio/best",
"outtmpl": f"{output_dir}/%(id)s.%(ext)s",
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
"preferredquality": "320",
}
],
"quiet": True,
"ignoreerrors": True, # 1本失敗しても続行
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
for url in urls:
try:
info = ydl.extract_info(url, download=True)
if info:
video_id = info["id"]
results[url] = str(Path(output_dir) / f"{video_id}.mp3")
else:
results[url] = "ERROR: extract_info returned None"
except Exception as e:
results[url] = f"ERROR: {e}"
return results
if __name__ == "__main__":
urls = [
"https://www.youtube.com/watch?v=VIDEO_ID_1",
"https://www.youtube.com/watch?v=VIDEO_ID_2",
"https://www.youtube.com/watch?v=VIDEO_ID_3",
]
results = batch_extract(urls, output_dir="my_audio")
for url, result in results.items():
print(f"{url} → {result}")
プレイリスト全曲を一括抽出
import yt_dlp
def extract_playlist(playlist_url: str, output_dir: str = "playlist") -> None:
"""YouTubeプレイリストの全曲を音声抽出する。"""
ydl_opts = {
"format": "bestaudio/best",
"outtmpl": f"{output_dir}/%(playlist_index)02d_%(title)s.%(ext)s",
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
"preferredquality": "320",
}
],
"ignoreerrors": True,
"quiet": False, # プレイリストは進捗を表示
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([playlist_url])
if __name__ == "__main__":
extract_playlist(
"https://www.youtube.com/playlist?list=PLAYLIST_ID",
output_dir="my_playlist"
)
%(playlist_index)02d でゼロパディングしたトラック番号をファイル名に付与します(例:01_曲名.mp3)。
フォーマット指定の詳細設定
yt-dlpのフォーマット指定文字列は非常に柔軟です。
# 利用可能なフォーマット一覧を取得(ダウンロードなし)
import yt_dlp
import json
with yt_dlp.YoutubeDL({"quiet": True}) as ydl:
info = ydl.extract_info("URL", download=False)
for fmt in info.get("formats", []):
if fmt.get("acodec") != "none":
print(f"ID={fmt['format_id']} | codec={fmt.get('acodec')} | abr={fmt.get('abr')}kbps | ext={fmt['ext']}")
よく使うフォーマット指定パターン:
| 目的 |
format 指定 |
|---|---|
| 最高品質音声(自動) | "bestaudio/best" |
| Opusのみ(最軽量) | "bestaudio[ext=webm]" |
| AACのみ | "bestaudio[acodec=mp4a.40.2]" |
| 最大160kbps以下 | "bestaudio[abr<=160]" |
フォーマット指定後に最高音質のOpus → WAVが最高品質ルートになります。Opusは元データに最も近い形式でYouTubeから配信されます。
エラーハンドリングとリトライ
ネットワークエラーや削除済み動画への対処:
import yt_dlp
import time
import logging
logger = logging.getLogger(__name__)
def extract_with_retry(url: str, output_dir: str = ".", max_retries: int = 3) -> str | None:
"""エラー時に最大max_retries回リトライする音声抽出。"""
ydl_opts = {
"format": "bestaudio/best",
"outtmpl": f"{output_dir}/%(id)s.%(ext)s",
"postprocessors": [
{"key": "FFmpegExtractAudio", "preferredcodec": "mp3", "preferredquality": "320"}
],
"retries": 3, # yt-dlp組み込みリトライ
"fragment_retries": 3,
"quiet": True,
}
for attempt in range(1, max_retries + 1):
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
return f"{output_dir}/{info['id']}.mp3"
except yt_dlp.utils.DownloadError as e:
if "Video unavailable" in str(e) or "Private video" in str(e):
logger.warning(f"スキップ(削除/非公開): {url}")
return None # リトライ不要
if attempt < max_retries:
wait = 2 ** attempt # 指数バックオフ
logger.warning(f"試行 {attempt}/{max_retries} 失敗。{wait}秒後にリトライ: {e}")
time.sleep(wait)
else:
logger.error(f"最大リトライ数到達: {url} → {e}")
return None
return None
年齢制限・ログインが必要な動画の取得
cookieをブラウザからエクスポートして使用します:
# Chrome/Firefoxのcookieをエクスポート(ブラウザでYouTubeにログイン済みであること)
yt-dlp --cookies-from-browser chrome -x --audio-format mp3 "URL"
Pythonから:
import yt_dlp
ydl_opts = {
"format": "bestaudio/best",
"cookiesfrombrowser": ("chrome",), # または ("firefox",)
"outtmpl": "%(id)s.%(ext)s",
"postprocessors": [
{"key": "FFmpegExtractAudio", "preferredcodec": "mp3", "preferredquality": "320"}
],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(["URL"])
メタデータのみ取得(ダウンロードなし)
曲タイトル・アーティスト・長さなどのメタデータだけ取得したい場合:
import yt_dlp
def get_metadata(url: str) -> dict:
"""ダウンロードせずにメタデータのみ取得する。"""
with yt_dlp.YoutubeDL({"quiet": True}) as ydl:
info = ydl.extract_info(url, download=False)
return {
"id": info.get("id"),
"title": info.get("title"),
"uploader": info.get("uploader"),
"duration": info.get("duration"), # 秒
"view_count": info.get("view_count"),
"upload_date": info.get("upload_date"),
}
meta = get_metadata("https://www.youtube.com/watch?v=VIDEO_ID")
print(meta)
音声抽出後にAIステム分離を行う場合
抽出した音声からボーカルとインストゥルメンタルを分離したい場合は、以前の記事「yt-dlp + AI音源分離パイプライン」 をご参照ください。Demucs htdemucsを使ったPython実装をそのまま使えます。
ノーコードで手軽に試したい場合は StemSplit YouTube Stem Splitter でURLを貼り付けるだけで音声抽出 → ステム分離が完結します。
比較まとめ
| 方法 | バッチ処理 | 最大品質 | ログイン対応 | Python統合 |
|---|---|---|---|---|
| yt-dlp CLI | ✅ | WAV/FLAC | ✅ | ✓(subprocess) |
| yt-dlp Python API | ✅ | WAV/FLAC | ✅ | ✓(ネイティブ) |
| pytube / pytubefix | △(手動ループ) | MP4音声のみ | ❌ | ✓ |
| moviepy | △ | MP3/WAV | ❌ | ✓ |
| StemSplit API | ✅ | MP3 320kbps | - | ✓(REST) |
yt-dlpのPython APIは最も機能が揃っており、CLIと全く同じ機能をスクリプト内で利用できます。
ブラウザでの手軽な方法や他のツール(VLC、4K Video Downloader、モバイルアプリ等)については YouTubeから音声を抽出する7つの方法まとめ をご覧ください。
よくある質問
yt-dlpのPython APIとCLIは何が違いますか?
結論:機能は同一です。CLIはシェルからの直接実行向けで、Python APIはスクリプト・アプリへの組み込み向けです。同じYoutubeDLクラスをどちらも使用します。
yt-dlpが突然動かなくなった場合は?
結論:まず pip install -U yt-dlp で最新版に更新してください。YouTubeがAPIを変更した際、yt-dlpは数日以内に対応します。古いバージョンを使い続けると動かなくなります。
youtube-dlからyt-dlpへの移行方法は?
結論:インポート名を youtube_dl から yt_dlp に変えるだけでほぼ互換性があります。オプション名はほぼ同じですが、一部に新しいオプションが追加されています。
プレイリストの一部だけダウンロードするには?
結論:playliststart と playlistend、または playlist_items で指定します。
ydl_opts = {
"playlist_items": "1-10", # 1曲目から10曲目
# または
"playliststart": 5,
"playlistend": 15,
}