discord.py音乐机器人实现歌曲队列、跳过命令及双渠道搜歌方案
完整修改实现代码
- 队列逻辑直接集成至
.play命令:无播放任务时直接播放歌曲,已有播放任务时自动将新歌曲加入队列 - 新增播放完成自动回调逻辑,当前歌曲播放结束后自动读取队列下一首播放
- 新增
.skip命令,调用后直接跳过当前播放歌曲 - 自动兼容两种输入方式:输入为http/https开头的链接时直接解析,否则作为 YouTube 搜索关键词检索歌曲
- 修复原代码每次调用
.play都会强行终止当前播放的问题
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.ffmpeg_options = { 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn' } self.ydl_options = { 'format': 'bestaudio', 'noplaylist': 'True' } async def play_next(self, ctx): if len(self.music_queue) > 0: self.is_playing = True song_info = self.music_queue.pop(0) url2 = song_info['formats'][0]['url'] source = await discord.FFmpegOpusAudio.from_probe(url2, **self.ffmpeg_options) ctx.voice_client.play(source, after=lambda e: asyncio.run_coroutine_threadsafe(self.play_next(ctx), self.client.loop)) await ctx.send(f"现在播放:{song_info['title']}") else: self.is_playing = False await ctx.send("队列已空,播放结束") @commands.command() async def disconnect(self, ctx): self.music_queue.clear() self.is_playing = False await ctx.voice_client.disconnect() @commands.command() async def play(self, ctx, *, query): # 检查用户是否在语音频道 if ctx.author.voice is None: await ctx.send("你当前不在语音频道中!") return 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) # 解析歌曲信息 with youtube_dl.YoutubeDL(self.ydl_options) as ydl: # 判断是链接还是搜索关键词 if query.startswith("http"): info = ydl.extract_info(query, download=False) else: info = ydl.extract_info(f"ytsearch:{query}", download=False)['entries'][0] # 判断是否正在播放 if not self.is_playing: self.is_playing = True url2 = info['formats'][0]['url'] source = await discord.FFmpegOpusAudio.from_probe(url2, **self.ffmpeg_options) ctx.voice_client.play(source, after=lambda e: asyncio.run_coroutine_threadsafe(self.play_next(ctx), self.client.loop)) await ctx.send(f"现在播放:{info['title']}") else: self.music_queue.append(info) await ctx.send(f"已加入队列:{info['title']},当前队列长度:{len(self.music_queue)}") @commands.command() async def skip(self, ctx): if ctx.voice_client.is_playing(): ctx.voice_client.stop() await ctx.send("已跳过当前歌曲") else: await ctx.send("当前没有正在播放的歌曲") @commands.command() async def pause(self, ctx): if ctx.voice_client.is_playing(): ctx.voice_client.pause() embed = discord.Embed( title="", description="***已暂停播放***", color=0x2f3136 ) await ctx.send(embed=embed) else: await ctx.send("当前没有正在播放的歌曲") @commands.command() async def resume(self, ctx): if ctx.voice_client.is_paused(): ctx.voice_client.resume() embed = discord.Embed( title="", description="***已恢复播放***", color=0x2f3136 ) await ctx.send(embed=embed) else: await ctx.send("当前没有暂停的播放任务") def setup(client): client.add_cog(Music(client))
内容的提问来源于stack exchange,提问作者Witalik Zarscikov
相关产品推荐
相关产品推荐

