提问者:小点点

有没有办法检查机器人是否正在播放音频,如果没有,则自动播放下一首歌?


我目前正在创建一个不和谐的机器人,使用discord.py,播放音乐。

使用“-play”命令时,机器人应该播放指定的歌曲。如果在机器人当前播放时播放了一首歌曲,则它会将其添加到队列中,一旦歌曲完成,就会播放该歌曲。

如果一首指定的歌曲在另一首完成后被请求,那么它应该简单地播放指定的歌曲。

然而,目前机器人只实现了两者中的第一个。虽然如果在另一首歌中排队,歌曲确实会播放……当另一首歌结束后使用“-play”命令时,它仍然会将歌曲添加到队列中。播放歌曲的唯一方法是“跳过”当前正在播放的歌曲,即使没有听到任何声音。

相关代码如下:

class Player(commands.Cog):
    def __init__(self,bot):
        self.bot = bot
        self.song_queue = {}

        self.setup()

    def setup(self):
        for guild in self.bot.guilds:
            self.song_queue[guild.id] = []
    
    async def check_queue(self,ctx):
        if len(self.song_queue[ctx.guild.id]) > 0:
            ctx.voice_client.stop()
            await self.play_song(ctx, self.song_queue[ctx.guild.id][0])
            self.song_queue[ctx.guild.id].pop(0)

    async def play_song(self, ctx, song):
        url = pafy.new(song).getbestaudio().url
        ctx.voice_client.play(discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(url)), after=lambda error: self.bot.loop.create_task(self.check_queue(ctx)))
        ctx.voice_client.source.volume = 0.5 

#other code...

@commands.command()
    async def play(self, ctx, *, song=None):
        if song is None:
            return await ctx.send("Gotta tell me what to play before I can bust out the music")
        
        if ctx.voice_client is None:
            return await ctx.send("Come on bud, why would I sing my tunes if you're not even listening!?")

        if not("youtube.com/watch?" in song or "https:youtu.be/" in song):
            await ctx.send("Searching for song, gonna have to wait a sec")
            
            result = await self.search_song(1, song, get_url=True)

            if result is None:
                return await ctx.send("Are you sure this is really a song? Maybe try search for it with my command, =play insert song name here")

            song = result[0]
            
        if ctx.voice_client.source is not None:
            queue_len = len(self.song_queue[ctx.guild.id])

            self.song_queue[ctx.guild.id].append(song)
            return await ctx.send(f"The song's been added to your queue, position {queue_len+1}.")

        await self.play_song(ctx, song) 
        await ctx.send(f"Tonight I'll be listening to {song}")


共1个答案

匿名用户

我已经解决了这个问题,或者至少想出了解决它的方法。我仍然不确定为什么它会在一首歌结束后添加到队列中,但是我用一个try除条件解决了这个问题。我没有使用ctx. voice.client.status,而是利用了一个错误,如果另一首歌已经在播放,程序在尝试播放一首歌时会返回这个错误。

只需替换您的ctx. Voice.client.statusif语句和

await self.play_song(ctx, song) 
await ctx.send(f"Tonight I'll be listening to {song}")

try:
    await self.play_song(ctx, song)
except ClientException:
    queue_len = len(self.song_queue[ctx.guild.id])
    self.song_queue[ctx.guild.id].append(song)
    return await ctx.send(f"I don't think you can listen to two songs at once. The 
    song's been added to your queue, position {queue_len+1}.")

当一首歌已经在播放时,程序会引发ClientException,因此监听此错误可以让我们访问队列,如果一首歌没有播放,那么它将简单地播放这首歌。