Skip to content

「Unable to extract uploader id」エラーの解決方法

問題

discord.py で YouTube から音楽を再生する Discord ボットを作成している際に、以下のエラーが発生する問題です:

Error: Unable to extract uploader id

このエラーは youtube_dl ライブラリを使用した YouTube 動画の取得処理中に発生し、2023年頃から頻繁に報告されるようになった問題です。具体的な特徴は以下の通りです:

  • 以前は正常に動作していたコードが突然動作しなくなる
  • エラーメッセージには詳細な情報がなく、原因特定が困難
  • YouTube のサイト構造変更が根本的な原因
  • youtube_dl パッケージをアップデートしても解決しない

エラーが発生する主要なコード部分は、YouTube 動画情報を取得する以下の処理箇所です:

python
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))

この問題が発生すると Discord ボットの音楽再生機能が完全に停止するため、速やかな対応が必要です。

推奨解決策: yt-dlp への移行

youtube_dl のメンテナンスが不活発な状況に対応するため、積極的に開発が続けられているフォーク版 yt-dlp への移行が最良の解決策です。

利点

  • 95% 以上のコード互換性があるため最小限の修正で対応可能
  • 本問題を含むYouTubeの変更に対する迅速な修正が提供される
  • パフォーマンスと安定性が向上

移行手順

  1. パッケージの入れ替え:

    bash
    pip uninstall -y youtube_dl
    pip install yt-dlp
  2. インポート文の変更: コード内の import youtube_dl を以下のように変更:

    python
    import yt_dlp as youtube_dl  # 互換性維持のためエイリアス設定
  3. フォーマット設定の最適化:

    python
    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,           # IPv4接続を強制
    }

完全な動作コード例

python
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

この方法は非推奨です。パッケージ更新時に修正が上書きされ、根本解決にならないため、あくまで緊急時の対応として使用してください。

  1. 以下のファイルを開く:

    /path/to/youtube_dl/extractor/youtube.py
  2. 約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抽出失敗が致命的エラーではなく警告に変わります。

開発版インストール方法

システム環境に応じた最新版のインストール方法:

bash
# Gitリポジトリから直接インストール
pip uninstall