带有youtube dl的discord bot音乐不会卡在网页下载中

discord bot music with youtube dl not stuck at webpage downloading

所以我正在尝试制作一个音乐机器人,它可以加入、播放、停止和恢复音乐。但是,我的机器人可以正常加入和离开语音频道,但是当我执行 /play 命令时,它会卡在 [youtube] oCveByMXd_0: Downloading webpage 上(这是 vscode 中的输出),然后什么都不做。我放了一些打印语句(您可以在下面的代码中看到它打印 1 和 2 但不打印 3)。有人遇到过这个问题吗?

音乐机器人文件

import discord
from discord.ext import commands
import youtube_dl

class music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        
    @commands.command()
    async def join(self, ctx):
        if(ctx.author.voice is None):
            await ctx.reply("*You're not in a voice channel.*")
        voiceChannel = ctx.author.voice.channel
        if(ctx.voice_client is None): # if bot is not in voice channel
            await voiceChannel.connect()
        else: # bot is in voice channel move it to new one
            await ctx.voice_client.move_to(voiceChannel)

    @commands.command()
    async def leave(self, ctx):
        await ctx.voice_client.disconnect()
        
    @commands.command()
    async def play(self,ctx, url:str = None):
        if(url == None):
            await ctx.reply("*Check your arguments!*\n```/play VIDEO_URL```")
        else:
            ctx.voice_client.stop() # stop current song
            
            # FFMPEG handle streaming in discord, and has some standard options we need to include
            FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
            YTDL_OPTIONS = {"format":"bestaudio"}
            vc = ctx.voice_client
            
            # Create stream to play audio and then stream directly into vc
            with youtube_dl.YoutubeDL(YTDL_OPTIONS) as ydl:
                info = ydl.extract_info(url, download=False)
                print("1")
                url2 = info["formats"][0]["url"]
                print("2")
                source = await discord.FFmpegOpusAudio.from_probe(url2,FFMPEG_OPTIONS)
                print("3")
                vc.play(source) # play the audio
                await ctx.send(f"*Playing {info['title']} -* ")
    
    @commands.command()
    async def pause(self, ctx):
        await ctx.voice_client.pause()
        await ctx.reply("*Paused -* ⏸️")
    
    @commands.command()
    async def resume(self, ctx):
        await ctx.voice_client.resume()
        await ctx.reply("*Resuming -* ▶️")
      
            
def setup(bot):
    bot.add_cog(music(bot))

主文件

from discord.ext import commands
from dotenv import load_dotenv
from lxml import html
import youtube_dl
import requests
import random
import discord
import requests
import os
import music

# Load .env file
load_dotenv()

COGS = [music]
PREFIX = "/"

bot = commands.Bot(command_prefix=PREFIX, intents=discord.Intents.all())

for x in range(len(COGS)):
    COGS[x].setup(bot)
    

# EVENTS #
@bot.event
async def on_ready():
    await bot.get_channel(888736019590053898).send(f"We back online! All thanks to *sploosh* :D")

@bot.event
async def on_command_error(ctx, error):
    if isinstance(error, commands.CommandNotFound):
        replies = ["Err is that even a command?", "Can you type bro?", "Yeah... thats not a command buddy.", "Sorry forgot you can't spell"]
        await ctx.send(random.choice(replies))
        
@bot.event
async def on_message(message):
    if str(message.channel) == "images-videos" and message.content != "":
        await message.delete()
    await bot.process_commands(message)
    

# COMMANDS #
@bot.command()
async def hello(ctx):
    # Get a random fact
    url = 'http://randomfactgenerator.net/'
    page = requests.get(url)
    tree = html.fromstring(page.content)
    hr = str(tree.xpath('/html/body/div/div[4]/div[2]/text()'))
    
    await ctx.reply("**Hello Bozo!**\n" + "*Random Fact : *" + hr[:-9]+"]")
    
@bot.command()
async def randomNum(ctx, start:int = None, end:int = None):
    if(start == None or end == None):
        await ctx.reply("*Check your arguments!*\n```/randomNum START_NUMBER END_NUMBER```")
    else:
        randNum = random.randint(start, end)
        await ctx.reply(f"*{randNum}*")

@bot.command()
@commands.is_owner()
async def kick(ctx, member:discord.Member = None, *, reason="You smell bozo."):
    if(member == None):
        await ctx.reply("*Check your arguments!*\n```/kick @MEMBER REASON(optional)```")
    elif ctx.author.id in (member.id, bot.user.id):
        await ctx.reply("*You cant kick yourself/me you silly.*")
    else:
        await member.kick(reason=reason)

@bot.command()
@commands.is_owner()
async def ban(ctx, member:discord.Member = None, *, reason="Bye Bye! :D."):
    if(member == None):
        await ctx.reply("*Check your arguments!*\n```/kick @MEMBER REASON(optional)```")
    elif ctx.author.id in (member.id, bot.user.id):
        await ctx.reply("*You cant ban yourself/me you silly.*")
    else:
        await member.ban(reason=reason)
        
@bot.command()
@commands.is_owner()
async def close_bot(ctx):
    replies = ["Well bye!", "Guess I go now?", "Please let me stay..."]
    await ctx.send(random.choice(replies))
    await bot.close()

    
if __name__ == "__main__":
    bot.run(os.getenv("BOT_TOKEN"))
    

这就是我的播放音乐命令的设置方式,我确信它可以正常工作,而且看起来它也应该适合你。

@commands.command()
    async def play(self, ctx, *, song=None):
            commandd = "play"
            print(f"{ctx.author.name}, {ctx.author.id} used command "+commandd+" used at ")
            print(x)
            print(" ")
            if song is None:
                return await ctx.send("You must include a song to play.")

            if ctx.voice_client is None:
                return await ctx.send("I must be in a voice channel to play a song.")

            # handle song where song isn't url
            if not ("youtube.com/watch?" in song or "https://youtu.be/" in song):
                await ctx.send("Searching for song, this may take a few seconds.")

                result = await self.search_song(1, song, get_url=True)

                if result is None:
                    return await ctx.send("Sorry, I could not find the given song, try using my search command.")

                song = result[0]

            if ctx.voice_client.source is not None:
                queue_len = len(self.song_queue[ctx.guild.id])

                if queue_len < 10:
                    self.song_queue[ctx.guild.id].append(song)
                    return await ctx.send(f"I am currently playing a song, this song has been added to the queue at position: {queue_len+1}.")

                else:
                    return await ctx.send("Sorry, I can only queue up to 10 songs, please wait for the current song to finish.")

            await self.play_song(ctx, song)
            await ctx.send(f"Now playing: {song}")

这是您可能需要的其他一些东西

import discord
from discord.ext import commands
from random import choice
import string
from discord.ext.commands.cooldowns import BucketType
import asyncio
import youtube_dl
import pafy
import datetime
from discord_slash import cog_ext, SlashContext
x = datetime.datetime.now()
from ult import *
class music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.song_queue = {}

        self.setup()

    def setup(self):
        for guild in self.bot.guilds:
            self.song_queue[guild.id] = []

    async def check_queue(self, ctx):
        if len(self.song_queue[ctx.guild.id]) > 0:
            ctx.voice_client.stop()
            await self.play_song(ctx, self.song_queue[ctx.guild.id][0])
            self.song_queue[ctx.guild.id].pop(0)

    async def search_song(self, amount, song, get_url=False):
        info = await self.bot.loop.run_in_executor(None, lambda: youtube_dl.YoutubeDL({"format" : "bestaudio", "quiet" : True}).extract_info(f"ytsearch{amount}:{song}", download=False, ie_key="YoutubeSearch"))
        if len(info["entries"]) == 0: return None

        return [entry["webpage_url"] for entry in info["entries"]] if get_url else info

    async def play_song(self, ctx, song):
        url = pafy.new(song).getbestaudio().url
        ctx.voice_client.play(discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(url)), after=lambda error: self.bot.loop.create_task(self.check_queue(ctx)))
        ctx.voice_client.source.volume = 0.5