0
votes

I was wondering if there was a way to make my discord bot leave the voice channel after playing the audio of a youtube video. I tried using sleep(duration of the video), but for getting and downloading the video to play, I used pafy, which gives me the duration of the video, but in the 00:00:00 format, which counts as a string, not an interger. I changed the code to diconnect at the after=lamda e: await vc.disconnect, but it gives me an error saying 'await' outside async function. My code for playing the music is below:

channel = message.author.voice.channel
vc = await channel.connect()
url = contents
url = url.strip("play ")
video = pafy.new(url)
await message.channel.send("Now playing **%s**" % video.title)

audio = video.getbestaudio()
audio.download()
duration = video.duration
player = vc.play(discord.FFmpegPCMAudio('%s.webm' % video.title), after=lambda e: await vc.disconnect)
3

3 Answers

1
votes

Here's a way to disconnect after the song completes (removing the after=).

Add after vc.play()

    while vc.is_playing():
        await sleep(1)
    await vc.disconnect()
0
votes

Code I use in my bot:

stop_event = asyncio.Event()
loop = asyncio.get_event_loop()
def after(error):
    if error:
        logging.error(error)
    def clear():
        stop_event.set()
    loop.call_soon_threadsafe(clear)

audio = PCMVolumeTransformer(discord.FFmpegPCMAudio(file_path), 1)
client.play(audio, after=after)

await stop_event.wait()
await client.disconnect()
0
votes

In this case the vc.disconnect() is a coroutine which must be awaited. The after function of the discord player can't await async functions like this. Instead use something like this:

def my_after(error):
coro = vc.disconnect()
fut = asyncio.run_coroutine_threadsafe(coro, client.loop)
try:
    fut.result()
except:
    # an error happened sending the message
    pass
voice.play(discord.FFmpegPCMAudio(url), after=my_after)

You can also read about it here