Pausing, queuing, and looping songs with discord.py

Viewed 1926

I've got this code which plays a song in a voice channel and works fine, but how do I generate code that allows queuing, pausing and looping?

@client.command(pass_context=True)
async def play(ctx, url):

    if not ctx.message.author.voice:
        await ctx.send('Please enter the voice channel')
        return

    else:
        channel = ctx.message.author.voice.channel

    voice_client = await channel.connect()

    guild = ctx.message.guild

    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        file = ydl.extract_info(url, download=True)
        path = str(file['title']) + "-" + str(file['id'] + ".mp3")

    voice_client.play(discord.FFmpegPCMAudio(path), after=lambda x: endSong(guild, path))
    voice_client.source = discord.PCMVolumeTransformer(voice_client.source, 1)

    await ctx.send(f'**NOW MUSIC: **{url}')

    while voice_client.is_playing():
        await asyncio.sleep(1)
    else:
        await voice_client.disconnect()
        print("Disconnected")
2 Answers

https://discordpy.readthedocs.io/en/latest/api.html#voice

You can see the Voice object stored in your voice_client has a pause() and resume() method : pausing is simple enough.

For queuing and looping, the heavy lifting will have to be done by you. You'll have to call play() again when the song is over, and then have it play the same song again (looping) or play the next song you'll have stored somewhere in an array or other (queuing).

The good news is that discord.py allows you to avoid doing an annoying technique to know when the song is over: calling is_playing() repeatedly until it returns False. As you've written in your code, play() also takes into argument a callable named after that's called when the song is over (or when there's an error!).

In your case, that means your endSong() function called after a song will have to know if you should queue up the same song or another song, and call play() to start it. If you have trouble understanding how to do this, please show your attempt so we can give you more specific advice.

Example of pause command:

@client.command
async def pause(ctx):
    server = ctx.message.guild
    voice_channel = server.voice_client                
    voice_channel.pause()
    print('pause')

About queue, you can create list of queued songs. Check if song playing you will append song to queue, after playing current song you need to play queue[0] song. Sorry for my english

Related