Discord机器人可连接语音频道但无法播放YouTube音乐求助
Discord音乐机器人无法播放YouTube音乐问题修复
问题概述
开发Discord音乐机器人时,机器人可正常连接用户所在语音频道,但执行!play <YouTube链接>指令时无法播放音乐,核心错误为Unable to extract uploader id,已尝试添加verbose: True参数、指定FFmpeg路径,均未解决。
用户代码
#MODULES----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| import asyncio import discord import youtube_dl from discord.ext import commands #MAIN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| class MusicCommands(commands.Cog): def __init__(self, client): self.client = client self.is_playing = False self.is_paused = False self.music_queue = [] self.YDL_OPTIONS = {'format': 'bestaudio/best', 'verbose': True} self.FFMPEG_OPTIONS = {'options': '-vn'} self.vc = None self.ytdl = youtube_dl.YoutubeDL(self.YDL_OPTIONS) async def play_music(self, ctx): if self.music_queue: self.is_playing = True url = self.music_queue.pop(0) self.vc.play(discord.FFmpegPCMAudio(url, **self.FFMPEG_OPTIONS), after = lambda e: self.play_next(ctx)) async def play_next(self, ctx): if self.music_queue: url = self.music_queue.pop(0) self.vc.play(discord.FFmpegPCMAudio(url, **self.FFMPEG_OPTIONS), after = lambda e: self.play_next(ctx)) else: self.is_playing = False asyncio.run_coroutine_threadsafe(self.vc.disconnect(), self.client.loop) # (1) Play command. @commands.command( name = 'play', aliases = ['Play', 'PLAY'], description = 'Plays a song in the voice channel the user is currently in.' ) async def play(self, ctx, *, url = None): try: if not ctx.author.voice: embed = discord.Embed( title = '__Error__', description = f'{ctx.author.mention}, You are not connected to a voice channel.', color = discord.Color.red() ) await ctx.reply(embed = embed) return if not url: embed = discord.Embed( title = '__Error__', description = f'{ctx.author.mention}, Please provide a valid YouTube URL.', color = discord.Color.red() ) await ctx.reply(embed = embed) return channel = ctx.author.voice.channel if self.vc is None or not self.vc.is_connected(): self.vc = await channel.connect() else: await self.vc.move_to(channel) song_info = self.ytdl.extract_info(url, download = False) song_url = song_info['formats'][0]['url'] song_title = song_info['title'] self.music_queue.append(song_url) if not self.is_playing: await self.play_music(ctx) embed = discord.Embed( title = '__Music__', description = f''' 🎵 Playing Music... 🎷 Playing: {song_title} 🎧 Requested By: {ctx.author.mention} ''', color = discord.Color.dark_orange() ) await ctx.reply(embed = embed) except Exception as e: print(f'An error occurred in play command: {e}') #FUCNTION TO ADD COG TO THE BOT-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| async def setup(client): await client.add_cog(MusicCommands(client))
错误日志
[debug] Encodings: locale cp1252, fs utf-8, out utf-8, pref cp1252 [debug] youtube-dl version 2021.12.17 [debug] Python version 3.12.1 (CPython) - Windows-11-10.0.22631-SP0 [debug] exe versions: ffmpeg N-55702-g920046a, ffprobe N-55702-g920046a [debug] Proxy map: {} 2024-04-05 17:36:46 INFO discord.voice_client Connecting to voice... 2024-04-05 17:36:46 INFO discord.voice_client Starting voice handshake... (connection attempt 1) 2024-04-05 17:36:46 INFO discord.voice_client Voice handshake complete. Endpoint found india9259.discord.media [youtube] q4_aISHkMPg: Downloading webpage ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see https://yt-dl.org/update on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output. Traceback (most recent call last): File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\youtube_dl\YoutubeDL.py", line 815, in wrapper return func(self, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\youtube_dl\YoutubeDL.py", line 836, in __extract_info ie_result = ie.extract(url) ^^^^^^^^^^^^^^^ File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\youtube_dl\extractor\common.py", line 534, in extract ie_result = self._real_extract(url) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\youtube_dl\extractor\youtube.py", line 1794, in _real_extract 'uploader_id': self._search_regex(r'/(?:channel|user)/([^/?&#]+)', owner_profile_url, 'uploader id') if owner_profile_url else None, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\youtube_dl\extractor\common.py", line 1012, in _search_regex raise RegexNotFoundError('Unable to extract %s' % _name) youtube_dl.utils.RegexNotFoundError: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see https://yt-dl.org/update on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output. An error occurred in play command: ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see https://yt-dl.org/update on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.
修复方案
1. 替换youtube-dl为yt-dlp
youtube-dl已停止维护,YouTube页面结构更新导致其正则匹配逻辑失效,需替换为活跃维护的yt-dlp:
- 卸载旧库:执行
pip uninstall youtube-dl - 安装yt-dlp:执行
pip install yt-dlp - 代码中替换导入:将
import youtube_dl改为import yt_dlp as youtube_dl,无需修改其他调用逻辑
2. 更新YDL_OPTIONS配置
适配yt-dlp的同时,确保正确提取音频链接:
self.YDL_OPTIONS = { 'format': 'bestaudio/best', 'verbose': True, 'extract_flat': False, 'noplaylist': True # 无需支持播放列表时可添加,避免解析列表内容 }
3. 修复play_next函数的线程安全问题
原代码中asyncio.run_coroutine_threadsafe使用不当,导致异步调用异常,修改为:
def _play_next_callback(self, ctx, error): if error: print(f"播放错误: {error}") # 将异步任务加入事件循环 asyncio.run_coroutine_threadsafe(self._play_next(ctx), self.client.loop) async def _play_next(self, ctx): if self.music_queue: url = self.music_queue.pop(0) self.vc.play( discord.FFmpegPCMAudio(url, **self.FFMPEG_OPTIONS), after=lambda e: self._play_next_callback(ctx, e) ) else: self.is_playing = False await self.vc.disconnect() # 同步修改play_music函数 async def play_music(self, ctx): if self.music_queue: self.is_playing = True url = self.music_queue.pop(0) self.vc.play( discord.FFmpegPCMAudio(url, **self.FFMPEG_OPTIONS), after=lambda e: self._play_next_callback(ctx, e) )
4. 确保FFmpeg路径正确(可选)
若仍存在FFmpeg相关错误,在FFMPEG_OPTIONS中指定可执行文件路径:
self.FFMPEG_OPTIONS = { 'options': '-vn', 'executable': 'C:/your/path/to/ffmpeg.exe' # 替换为本地FFmpeg实际路径 }
内容的提问来源于stack exchange,提问作者Xeschoz
相关产品推荐
相关产品推荐

