Discord 音乐机器人,当我跳过一首曲目时,机器人会立即跳过 2 首曲目

问题描述 投票:0回答:1

情况及问题: 我播放一首歌曲并创建一个将要播放的歌曲列表。之后我使用>跳过,进入play_music,进入self.vc.play,在那里我开始after=,当上一首歌曲由于我>跳过而结束时。 (需要注意的是,在我来到self.vc.play之前,我再次上传了曲目,它后面减去了一首歌) 继续 after=,我到达 play_next,在那里我将再次加载歌曲,结果我丢失了 1 首歌曲。 那么问题来了,如何编写代码让歌曲能够正常>跳过

这是我得到的一个简单的例子

class Music(commands.Cog):

    def __init__(self, bot):
        self.bot = bot
        self.client = Client(token_yandex_music).init()
        # all the music related stuff
        self.is_playing = False
        self.is_paused = False

        # 2d array containing [song, channel]
        self.music_queue = []
        self.vc = None

    def play_next(self):
        if len(self.music_queue) > 0:
            self.vc.stop()
            self.music_queue[0][0]['source'].download('song.mp3')
            self.music_queue.pop(0)
            self.vc.play(discord.FFmpegPCMAudio('song.mp3'), after=lambda e: self.play_next())
            self.is_playing = True
        else:
            self.is_playing = False

    async def play_music(self, ctx):
        if len(self.music_queue) > 0:
            self.is_playing = True

            self.music_queue[0][0]['source'].download('song.mp3')
            # try to connect to voice channel if you are not already connected
            if self.vc is None or not self.vc.is_connected():
                self.vc = await self.music_queue[0][1].connect()
                # in case we fail to connect
                if self.vc is None:
                    await ctx.send("Вы не подключены к гс каналу")
                    return
            else:
                await self.vc.move_to(self.music_queue[0][1])
            # remove the first element as you are currently playing it
            self.music_queue.pop(0)
            self.vc.play(discord.FFmpegPCMAudio('song.mp3'), after=lambda e: self.play_next())
        else:
            self.is_playing = False

    @commands.command(name="play", aliases=["p", "playing"], help="Plays a selected song from ym")
    async def play(self, ctx, *args):
        query = " ".join(args)

        voice_channel = ctx.author.voice.channel
        if voice_channel is None:
            # you need to be connected so that the bot knows where to go
            await ctx.send('Вы не подключены к гс каналу')
        elif self.is_paused:
            self.vc.resume()
        else:
            song = await self.search_yt(ctx, query)
            if type(True) == type(song):
                await ctx.send(
                    "Не удалось загрузить песню")
            else:
                await ctx.send("Песня добавлена в плейлист")
                self.music_queue.append([song, voice_channel])
                if not self.is_playing:
                    await self.play_music(ctx)

    @commands.command(name="skip", aliases=["s"], help="Skips the current song being played")
    async def skip(self, ctx):
        if self.vc is not None and self.vc:
            self.vc.stop()
            # try to play next in the queue if it exists
            await self.play_music(ctx)
python discord discord.py bots
1个回答
0
投票

我的机器人也遇到了同样的问题,我花了几个小时阅读文档并进行故障排除(我希望能为您节省几个小时)。

事情是:

  • 当语音客户端已为您的服务器实例化时,它将播放您分配给它的 FFmpeg 播放器。无论出于何种原因它遇到错误或者如果您停止它,它都会引发错误
  • 引发的错误将触发您在“vc.play()”函数的“after”参数中定义的函数
  • “vc.stop()”会在播放器中触发错误,因为您正在停止它(理想情况下,它应该一直流式传输到歌曲结束)
  • 因此:通过执行 vc.stop(),您已经“跳过”了一首歌。然后,通过调用“await self.play_music(ctx)”,您将再次跳过一首歌曲(因为在“play_music”方法中您再次调用“vc.stop()”)。然后,无限循环开始..

因此,通过定义“vc.play()”方法并定义“after”参数,您已经实现了跳过功能。

请注意不要过度使用“await self.play_next(ctx)”函数。乍一看似乎有点违反直觉,但后来就明白了。

来源:

  1. https://discordpy.readthedocs.io/en/latest/api.html?highlight=player#discord.VoiceClient.play
© www.soinside.com 2019 - 2024. All rights reserved.