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

如何为基于youtube-dl的Discord Python机器人实现播放队列?

解决Discord机器人的YouTube播放队列问题

我来帮你搞定播放队列的功能!你的原代码里存在几个关键问题(比如异步回调处理不当、没有正确维护队列状态),导致队列功能无法正常工作。下面是修复后的完整代码,我会逐一解释核心改进点:

修复后的完整代码

import discord
import asyncio
from discord.ext import commands

class BOT(object):
    def __init__(self, client):
        self.client = client
        self.player = None
        self.vc = None
        self.play_queue = asyncio.Queue()  # 初始化异步播放队列

    async def play(self, url):
        # 如果当前没有播放器,先加入语音频道并初始化播放器
        if self.player is None:
            channel = self.client.get_channel("你的语音频道ID")  # 替换成实际频道ID
            self.vc = await self.client.join_voice_channel(channel)
            # 开始播放当前URL,播放结束后调用play_next
            self.player = await self.vc.create_ytdl_player(
                url,
                after=lambda: asyncio.run_coroutine_threadsafe(self.play_next(), self.client.loop)
            )
            self.player.start()
        else:
            # 如果正在播放,把URL加入队列
            await self.play_queue.put(url)
            print(f"已将URL加入播放队列:{url}")

    async def play_next(self):
        # 清理当前播放器
        self.player = None
        # 检查队列是否有等待的URL
        if not self.play_queue.empty():
            next_url = await self.play_queue.get()
            await self.play(next_url)
        else:
            # 队列为空,断开语音连接
            await self.vc.disconnect()
            self.vc = None
            print("播放队列已空,断开语音连接")

# 原代码里用discord.Client加commands_prefix是错误的,改用commands.Bot
client = commands.Bot(command_prefix="!")

def run_bot():
    client.run("你的Bot Token")  # 替换成实际的Bot Token

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

bot = BOT(client)

@client.event
async def on_message(message):
    # 示例:当用户发送!play指令时添加视频到队列
    if message.content.startswith("!play"):
        # 可以从消息中提取用户输入的URL,比如message.content.split()[1]
        await bot.play("https://www.youtube.com/watch?v=bpOSxM0rNPM")
    # 必须加上这行,否则机器人无法处理命令
    await client.process_commands(message)

run_bot()

核心改进说明

  • 使用异步队列:用asyncio.Queue替代普通的同步队列,因为Discord.py是基于异步事件循环的框架,同步队列会阻塞事件循环导致机器人无响应,这大概率是你之前用Queue失败的原因。
  • 正确维护状态:把player和vc作为类的实例属性,避免全局变量带来的状态混乱问题。
  • 异步回调处理:在create_ytdl_player的after回调中,用asyncio.run_coroutine_threadsafe调度异步的play_next方法,确保回调在异步环境中正确执行。
  • 队列逻辑完善:
    • 调用play时,若当前无播放任务则直接启动;若正在播放则将URL加入队列等待。
    • 当前视频播放结束后,play_next会自动从队列取取下一个URL继续播放,队列为空时自动断开语音连接。
  • 修复命令初始化问题:原代码中discord.Client不支持commands_prefix参数,改用commands.Bot才能正确创建带命令前缀的机器人实例。

额外扩展建议

  • 可以修改on_message事件,让用户通过!play [视频URL]的方式手动添加自定义播放链接。
  • 新增!queue命令查看当前队列内容,!skip命令跳过当前播放的视频,提升机器人的交互性。

内容的提问来源于stack exchange,提问作者Jack Eagles

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:44:29