Как добавить список треков

Делаю музыкального бота, столкнулся с проблемой добавления музыки в список и последующем воспроизведении. Чтобы можно было во время проигрывания видео в боте ещё раз прописать команду play и поставить в очередь видео, которое воспроизведётся после окончания предыдущего. Мой код:

YDL_OPTIONS = {'format': 'worstaudio/best', 'noplaylist': 'False', 'simulate': 'True',
               'preferredquality': '192', 'preferredcodec': 'mp3', 'key': 'FFmpegExtractAudio'}
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}

client = commands.Bot( command_prefix ='!', intents = intents)

#Музыка

@client.command()
async def join(ctx):
    await ctx.message.author.voice.channel.connect()


@client.command()
async def leave(ctx):
        await ctx.guild.voice_client.disconnect()


@client.command()
async def play(ctx, *, arg):
    if not ctx.message.author.voice:
        await ctx.send('Ты не в голосовом канале')
        return

    try:
        voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
        with YoutubeDL(YDL_OPTIONS) as ydl:
            if 'https://' in arg:
                info = ydl.extract_info(arg, download=False)
            else:
                info = ydl.extract_info(f"ytsearch:{arg}", download=False)['entries'][0]
        url = info['formats'][0]['url']
        voice.play(discord.FFmpegPCMAudio(executable ="ffmpeg\\ffmpeg.exe", source=url, **FFMPEG_OPTIONS))
        info = str(info)
        await ctx.send('https://www.youtube.com/watch?v='+info[8:19])

    except:
        await ctx.message.author.voice.channel.connect()
        voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
        with YoutubeDL(YDL_OPTIONS) as ydl:
            if 'https://' in arg:
                info = ydl.extract_info(arg, download=False)
            else:
                info = ydl.extract_info(f"ytsearch:{arg}", download=False)['entries'][0]
        url = info['formats'][0]['url']
        voice.play(discord.FFmpegPCMAudio(executable="ffmpeg\\ffmpeg.exe", source=url, **FFMPEG_OPTIONS))
        info = str(info)
        await ctx.send('https://www.youtube.com/watch?v=' + info[8:19])

Ответы (1 шт):

Автор решения: Universall

Я использовал костыль. Просто цикл while в параллельном потоке, который крутится пока играет музыка, а когда трек заканчивается - заканчивается while и запускается новый трек.

from threading import Thread


class Player(Thread):  # Создание потока
    def __init__(self, ctx, queue):
        super(Player, self).__init__()
        self.daemon = True
        self.active = True
        self.ctx = ctx
        self.queue = queue
        self.YDL_OPTIONS = {'format': 'worstaudio/best', 'noplaylist': 'False', 'simulate': 'True','preferredquality': '192', 'preferredcodec': 'mp3', 'key': 'FFmpegExtractAudio'}
        self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}

    def run(self):
        while self.active and self.queue:
            arg = self.queue.pop(0)  # Взять элемент из очереди, обработать его и запустить музыку

            with YoutubeDL(self.YDL_OPTIONS) as ydl:  # Поиск
                if 'https://' in arg:
                    info = ydl.extract_info(arg, download=False)
                else:
                    info = ydl.extract_info(f"ytsearch:{arg}", download=False)['entries'][0]
            url = str(info['formats'][0]['url'])
            voice = discord.utils.get(client.voice_clients, guild=self.ctx.guild)
            voice.play(discord.FFmpegPCMAudio(executable="ffmpeg\\ffmpeg.exe", source=url, **self.FFMPEG_OPTIONS))
            
            while (connection.is_playing() or connection.is_paused()) and connection.is_connected():  # Ждём пока музыка кончится
                if not self.active:
                    return
                time.sleep(0.5)

            await self.ctx.send('https://www.youtube.com/watch?v=' + info[8:19])

    def close(self):
        self.active = False

Но этот поток должен быть у каждого сервера свой, так что его нужно записывать

players = {}

И затем им можно управлять

player = players.get(ctx.guild)
if not player or not player.is_alive():
    player = Player(ctx, server_queue)
    player.start()
    players[ctx.guild] = player
else:
    await ctx.send("Музыка уже играет!")
    player.ctx = ctx

Очередь можно хранить так же в словаре

queue = {}
for guild in self.bot.guilds:
    queue[guild] = []
server_queue = queue.get(ctx.guild)
server_queue.append(arg)

Это то, что использовал я. Может есть решение лучше, но я о нём не знаю ¯\_(ツ)_/¯

→ Ссылка