「Unable to extract uploader id」エラーの解決方法
問題
discord.py
で YouTube から音楽を再生する Discord ボットを作成している際に、以下のエラーが発生する問題です:
Error: Unable to extract uploader id
このエラーは youtube_dl
ライブラリを使用した YouTube 動画の取得処理中に発生し、2023年頃から頻繁に報告されるようになった問題です。具体的な特徴は以下の通りです:
- 以前は正常に動作していたコードが突然動作しなくなる
- エラーメッセージには詳細な情報がなく、原因特定が困難
- YouTube のサイト構造変更が根本的な原因
youtube_dl
パッケージをアップデートしても解決しない
エラーが発生する主要なコード部分は、YouTube 動画情報を取得する以下の処理箇所です:
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
この問題が発生すると Discord ボットの音楽再生機能が完全に停止するため、速やかな対応が必要です。
推奨解決策: yt-dlp への移行
youtube_dl
のメンテナンスが不活発な状況に対応するため、積極的に開発が続けられているフォーク版 yt-dlp
への移行が最良の解決策です。
利点
- 95% 以上のコード互換性があるため最小限の修正で対応可能
- 本問題を含むYouTubeの変更に対する迅速な修正が提供される
- パフォーマンスと安定性が向上
移行手順
パッケージの入れ替え:
bashpip uninstall -y youtube_dl pip install yt-dlp
インポート文の変更: コード内の
import youtube_dl
を以下のように変更:pythonimport yt_dlp as youtube_dl # 互換性維持のためエイリアス設定
フォーマット設定の最適化:
pythonytdl_format_options = { 'format': 'bestaudio/best', 'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s', 'restrictfilenames': True, 'noplaylist': True, 'nocheckcertificate': True, 'ignoreerrors': False, 'logtostderr': False, 'quiet': True, 'no_warnings': True, 'default_search': 'auto', 'source_address': '0.0.0.0', # 以下を追加 'extractor_retries': 'auto', # 情報抽出失敗時の自動リトライ 'force-ipv4': True, # IPv4接続を強制 }
完全な動作コード例
import yt_dlp as youtube_dl
import discord
import asyncio
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0',
'extractor_retries': 'auto',
'force-ipv4': True,
}
ffmpeg_options = {'options': '-vn'}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
@classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
# 音楽再生コマンドの使用例
sessionChannel = message.author.voice.channel
await sessionChannel.connect()
url = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' # YouTube URL
player = await YTDLSource.from_url(url, loop=client.loop, stream=True)
sessionChannel.guild.voice_client.play(player)
その他の解決方法
一時的な対処法: ソースコード修正
パッケージ変更が困難な場合、youtube_dl
ソースコードを直接修正することで一時的に回避可能です:
WARNING
この方法は非推奨です。パッケージ更新時に修正が上書きされ、根本解決にならないため、あくまで緊急時の対応として使用してください。
以下のファイルを開く:
/path/to/youtube_dl/extractor/youtube.py
約1794行目を検索し修正:
diff- 'uploader_id': self._search_regex(r'/(?:channel|user)/([^/?&#]+)', owner_profile_url, 'uploader id') if owner_profile_url else None + 'uploader_id': self._search_regex(r'/(?:channel|user)/([^/?&#]+)', owner_profile_url, 'uploader id', fatal=False) if owner_profile_url else None
fatal=False
パラメータを追加することで、ID抽出失敗が致命的エラーではなく警告に変わります。
開発版インストール方法
システム環境に応じた最新版のインストール方法:
# Gitリポジトリから直接インストール
pip uninstall