我正在用 Python 制作一个不和谐的音乐机器人,到目前为止它可以播放音乐。我想添加一个队列功能,以便如果当前正在播放歌曲,则输入的歌曲将在播放完毕后播放。机器人下载从请求中获取的歌曲(不在下面的代码中),并将其重命名为“song.mp3”。然后它开始播放歌曲,完成后它会删除歌曲,以便可以下载新歌曲,也称为“song.mp3”。我对这里的队列系统的想法是,机器人会遍历 Song_queue 中的所有 url,当第一个完成后,下载第二个,依此类推。当机器人正在播放时,我需要检查它何时可以移动到下一个文件,为此我使用了 while voice.is_playing
并且导致问题的原因是其他命令不再有效。
song_queue = []
@commands.command()
async def play(self, ctx, *, url: str):
if ctx.author.voice and ctx.author.voice.channel:
channel = ctx.author.voice.channel
if not self.bot_is_connected(ctx):
await channel.connect()
else:
await ctx.send("`You are not connected to a voice channel.`")
if ctx.author.voice and ctx.author.voice.channel:
voice = discord.utils.get(self.client.voice_clients, guild=ctx.guild)
video = get_url(f"{url}")
song_queue.append(video)
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
except PermissionError:
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
for song in song_queue:
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([song])
meta = ydl.extract_info(song, download=False)
song_name = (meta["title"])
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, "song.mp3")
voice.play(discord.FFmpegPCMAudio("song.mp3"))
while voice.is_playing(): #Makes other commands no longer work
print("playing...")
time.sleep(5)
else:
song_queue.remove(song)
song_there = os.path.isfile("song.mp3")
if song_there:
os.remove("song.mp3")
答案 0 :(得分:0)
导致您的其他命令停止工作的原因是使用了 time.sleep()
。 discord.py 是一个异步库,这意味着它处理能够同时执行多个功能以确保机器人在使用过程中不被阻止,但是添加像 time.sleep()
这样的同步调用使其停止操作。
当您使用异步库时,最好也寻找其他实用程序的异步版本,这样您就不会陷入在异步操作中使用阻塞同步调用的诱惑。在这种情况下,我建议您使用 asyncio.sleep(5)
。您还需要 import asyncio
才能使用该功能。
参考文献: