Reputation: 19
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
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
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