You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 13:04:59