You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Discord音乐机器人添加播放队列、切歌及清空队列功能

需求背景

Rhythm和Groovy两款Discord音乐机器人下架后,我决定开发适配自己所在Discord服务器的自用音乐机器人。参考了Youtuber的教程代码后,已经实现了加入语音频道、播放、暂停、恢复播放、断开连接的功能,现在需要添加播放队列、切歌、清空队列的功能,原有代码如下:

原有代码

main.py

import discord
from discord.ext import commands
import music

cogs = [music]

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

for i in range(len(cogs)):
    cogs[i].setup(client)


client.run('TOKEN')

原有music.py

import discord
from discord.ext import commands
import youtube_dl

class music(commands.Cog):
    def __init__(self, client):
        self.client = client

    @commands.command()
    async def join(self,ctx):
        if ctx.author.voice is None:
          await ctx.send("Get in a voice channel idiot!")
        voice_channel = ctx.author.voice.channel
        if ctx.voice_client is None:
            await voice_channel.connect()
        else:
            await ctx.voice_client.move_to(voice_channel)

    @commands.command()
    async def disconnect(self,ctx):
        await ctx.voice_client.disconnect()

    @commands.command()
    async def play(self,ctx,url):
        ctx.voice_client.stop()
        FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
        YDL_OPTIONS = {'format':"bestaudio"}
        vc = ctx.voice_client
        self.music_queue = []

        with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl:
            info = ydl.extract_info(url,download=False)
            url2 = info['formats'][0]['url']
            source = await discord.FFmpegOpusAudio.from_probe(url2,**FFMPEG_OPTIONS)
            vc.play(source)

    @commands.command()
    async def pause(self, ctx):
        await ctx.voice_client.pause()
        await ctx.send("Paused ⏸️")

    @commands.command()
    async def resume(self, ctx):
        await ctx.voice_client.resume()
        await ctx.send("Resumed ⏯️ ")

def setup(client):
    client.add_cog(music(client))

实现方案

直接替换原有music.py的内容即可,新增了队列管理、自动播放下一首、切歌、查看队列、清空队列功能,命令规则:

  • !play <URL> 无播放任务时直接播放,已有播放任务时自动加入队列
  • !skip 切换到下一首歌曲
  • !queue 查看当前队列的所有待播放歌曲
  • !clearqueue 清空所有队列内容

修改后的music.py代码:

import discord
from discord.ext import commands
import youtube_dl
import asyncio

class music(commands.Cog):
    def __init__(self, client):
        self.client = client
        # 队列存储格式:(音频源对象, 歌曲标题)
        self.music_queue = []
        self.is_playing = False
        self.vc = None
        self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
        self.YDL_OPTIONS = {'format':"bestaudio", 'quiet': True}

    # 播放下一首的回调函数
    def play_next(self, ctx):
        if len(self.music_queue) > 0:
            self.is_playing = True
            source, title = self.music_queue.pop(0)
            self.vc.play(source, after=lambda e: self.play_next(ctx))
            asyncio.run_coroutine_threadsafe(ctx.send(f"现在播放: {title}"), self.client.loop)
        else:
            self.is_playing = False

    @commands.command()
    async def join(self,ctx):
        if ctx.author.voice is None:
          await ctx.send("你得先加入一个语音频道!")
        voice_channel = ctx.author.voice.channel
        if ctx.voice_client is None:
            self.vc = await voice_channel.connect()
        else:
            await ctx.voice_client.move_to(voice_channel)
            self.vc = ctx.voice_client

    @commands.command()
    async def disconnect(self,ctx):
        self.music_queue = []
        self.is_playing = False
        await ctx.voice_client.disconnect()

    @commands.command()
    async def play(self,ctx,url):
        # 自动检查加入语音频道
        if ctx.voice_client is None:
            if ctx.author.voice:
                self.vc = await ctx.author.voice.channel.connect()
            else:
                await ctx.send("你得先加入一个语音频道!")
                return

        # 解析音频链接
        with youtube_dl.YoutubeDL(self.YDL_OPTIONS) as ydl:
            try:
                info = ydl.extract_info(url, download=False)
            except:
                await ctx.send("链接解析失败,请检查URL是否正确")
                return
            url2 = info['formats'][0]['url']
            source = await discord.FFmpegOpusAudio.from_probe(url2, **self.FFMPEG_OPTIONS)
            title = info.get('title', '未知歌曲')

        # 判断是直接播放还是加入队列
        if not self.is_playing:
            self.is_playing = True
            self.vc.play(source, after=lambda e: self.play_next(ctx))
            await ctx.send(f"现在播放: {title}")
        else:
            self.music_queue.append((source, title))
            await ctx.send(f"已加入队列: {title} | 当前队列长度: {len(self.music_queue)}")

    @commands.command()
    async def pause(self, ctx):
        if self.vc and self.vc.is_playing():
            await self.vc.pause()
            await ctx.send("已暂停 ⏸️")
        else:
            await ctx.send("当前没有正在播放的内容")

    @commands.command()
    async def resume(self, ctx):
        if self.vc and self.vc.is_paused():
            await self.vc.resume()
            await ctx.send("已恢复播放 ⏯️ ")
        else:
            await ctx.send("当前没有暂停的内容")

    @commands.command()
    async def skip(self, ctx):
        if self.vc and self.vc.is_playing():
            self.vc.stop()
            await ctx.send("已切歌 ⏭️")
        else:
            await ctx.send("当前没有正在播放的内容")

    @commands.command()
    async def queue(self, ctx):
        if len(self.music_queue) == 0:
            await ctx.send("当前队列为空")
            return
        queue_str = "当前队列:\n"
        for i, (_, title) in enumerate(self.music_queue):
            queue_str += f"{i+1}. {title}\n"
        await ctx.send(queue_str)

    @commands.command()
    async def clearqueue(self, ctx):
        self.music_queue = []
        await ctx.send("已清空队列 🗑️")

def setup(client):
    client.add_cog(music(client))

注意事项

  1. 本地需要提前安装ffmpeg,否则音频无法正常解码播放
  2. 如果youtube_dl解析新版YouTube链接失效,可以换成yt-dlp,仅需把import youtube_dl改成import yt_dlp as youtube_dl即可,其余代码无需修改
  3. main.py无需修改,直接沿用原有代码即可

内容的提问来源于stack exchange,提问作者Jordan Amo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:06:02