nuda
nuda

Reputation: 19

How to build a autoplay music bot, Discord.py

I want to build an autoplay music bot. I have a queue of songs, and I want the bot will autoplay the next song after the current song ends. How can I do that?

    async def play(self, ctx, input: str):
        YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist': 'True'}
        voice = discord.utils.get(self.client.voice_clients, guild=ctx.guild)
        print(type(voice))
        # input = input.strip("<>")
        with YoutubeDL(YDL_OPTIONS) as ydl:
            info = ydl.extract_info(input, download=False)
        description = ""
        count = 0
        if "entries" in info.keys():
            for id, ent in enumerate(info["entries"]):
                count += 1
                self.queue.add(ent)
                description += f"{id}.  {str(ent['title'])[:70].rjust(80)}" + \
                               ("..." if len(ent['title'][70:]) else "") + \
                               f"`{ent['duration'] // 60}:{ent['duration'] % 60}`\n" if count < 4 else ""
        else:
            URL = info['formats'][0]['url']
            self.queue.add(info)
            description += f"1. {str(info['title'])[:70].rjust(80)}" + \
                           ("..." if len(info['title'][70:]) else "") + \
                           f"`{info['duration'] // 60}:{info['duration'] % 60}`\n"

        if not voice.is_playing() and re.match(URL_REGEX, input):
            voice.play(FFmpegPCMAudio(executable="ffmpeg.exe", source=self.queue._queue[self.queue.position]['url'],
                                      **Music.FFMPEG_OPTIONS))
            await ctx.send(embed=self.get_embed(ctx, self.queue._queue, [self.queue.position + 1, self.queue.length]))
        elif voice.is_playing():
            pass # some staff here

Upvotes: 0

Views: 668

Answers (2)

user12299392
user12299392

Reputation:

I can't directly respond to Vibby's answer because I don't have a >50 reputation score.

But Vibby's solution does work. While it's actually quite ingenious, it is not even close to the most optimal solution. But for simpletons like me, it's a very clever option.

To reiterate what they said: Build an autocheck function where the bot checks whether or not it is playing audio. If it isn't, play the next song.

However, checking whether the bot is playing audio every clock cycle (or whatever the rate is it checks) will absolutely destroy your CPU. I managed to fix this with a work around, adding this line of code:

while True:
    if voice.is_playing():
        #do nothing
        await asyncio.sleep(10)
        pass
    else:
        #play next song in front of queue

The await asyncio.sleep(10) line is very important, as the bot will check once every ten seconds now. (If you feel comfortable setting the sleep value lower, go ahead)

Be weary though, if no songs are playing and no songs are queued, it will continue to check, infinitely. So, you should probably handle that.

Upvotes: 1

Vibby
Vibby

Reputation: 11

One thing you could do is you could have an async function that has a while True and constantly checks if the bot is playing nothing and if it isn't, advance the queue.

async def check(self, guild):
    while True:
        voice = discord.utils.get(self.client.voice_clients, guild=ctx.guild)
        if not voice.is_playing:
            self.queueIndex += 1
            await self.playNext()

Then make a playNext function that uses self.queueIndex to play songs. Sorry if this doesn't work, I haven't used Ydl to make a discord music bot.

Upvotes: 1

Related Questions