首页 > 解决方案 > 带有歌曲队列的 Python 不和谐音乐机器人

问题描述

我正在用 Python 制作一个不和谐的音乐机器人,到目前为止它还在播放音乐。我想添加一个队列功能,以便如果此刻正在播放歌曲,则输入的歌曲将在播放完毕后播放。机器人下载歌曲,它是从请求中获得的(不在下面的代码中),并将其重命名为“song.mp3”。然后它开始播放歌曲,完成后删除歌曲,以便可以下载新歌曲,也可以称为“song.mp3”。我对队列系统的想法是,机器人会遍历 song_queue 中的所有 url,当第一个完成后,下载第二个,依此类推。机器人在玩的时候,while voice.is_playing


song_queue = []

@commands.command()
    async def play(self, ctx, *, url: str):
        if ctx.author.voice and ctx.author.voice.channel:
            channel = ctx.author.voice.channel

            if not self.bot_is_connected(ctx):
                await channel.connect()
        else:
            await ctx.send("`You are not connected to a voice channel.`")

        if ctx.author.voice and ctx.author.voice.channel:

            voice = discord.utils.get(self.client.voice_clients, guild=ctx.guild)

            video = get_url(f"{url}")
            song_queue.append(video)

            song_there = os.path.isfile("song.mp3")
            try:
                if song_there:
                    os.remove("song.mp3")
            except PermissionError:

            ydl_opts = {
                'format': 'bestaudio/best',
                'postprocessors': [{
                    'key': 'FFmpegExtractAudio',
                    'preferredcodec': 'mp3',
                    'preferredquality': '192',
                }],
            }

            for song in song_queue:

                with youtube_dl.YoutubeDL(ydl_opts) as ydl:
                    ydl.download([song])
                    meta = ydl.extract_info(song, download=False)
                    song_name = (meta["title"])

                for file in os.listdir("./"):
                    if file.endswith(".mp3"):
                        os.rename(file, "song.mp3")
                voice.play(discord.FFmpegPCMAudio("song.mp3"))

                while voice.is_playing(): #Makes other commands no longer work
                    print("playing...")
                    time.sleep(5)

                else:
                    song_queue.remove(song)
                    song_there = os.path.isfile("song.mp3")
                    if song_there:
                        os.remove("song.mp3")

标签: pythonbotsdiscord.py

解决方案


导致其他命令停止工作的原因是使用time.sleep(). discord.py是一个异步库,这意味着它可以同时执行多个功能,以确保机器人在使用过程中不会被阻塞,但是添加一个同步调用time.sleep()会使其停止操作。

当您使用异步库时,最好同时查找其他实用程序的异步版本,这样您就不会陷入在异步操作中使用阻塞同步调用的诱惑。在这种情况下,我建议您将其asyncio.sleep(5)用于您的目的。您还需要import asyncio使用该功能。

参考:


推荐阅读