如何用Python开发可随机播放不同音频的Discord语音机器人
代码调整方案
现有代码仅实现了指令触发的单次音频播放,缺少3个核心逻辑:
- 未处理机器人未加入语音频道时的自动连接逻辑
- 没有播放完成后的自动切歌调度,无法实现循环播放
- 没有定时任务调度逻辑,无法实现间隔10秒播放指定音频的效果
完整修改后代码
import discord from discord.ext import commands import random import asyncio # 配置参数 FFMPEG_PATH = "F:/ffmpeg/bin/ffmpeg.exe" arvaus = [ *替换为你的音频文件路径列表* ] # 全局状态控制 is_looping = False # 随机循环播放开关 last_played = None # 记录上一首播放的音频,避免连续重复 scheduled_audio = None # 定时播放的音频路径 scheduled_task = None # 定时任务句柄 # 按需开启权限,不需要全开可自行调整 intents = discord.Intents.default() intents.message_content = True intents.voice_states = True client = commands.Bot(command_prefix="!", intents=intents) # 播放下一首随机音频的异步函数 async def play_next(voice_client: discord.VoiceClient): global is_looping, last_played if not is_looping: return # 随机选音频,避免和上一首重复 audio_path = random.choice(arvaus) while audio_path == last_played and len(arvaus) > 1: audio_path = random.choice(arvaus) last_played = audio_path audio_source = discord.FFmpegPCMAudio(executable=FFMPEG_PATH, source=audio_path) # 播放完成后的回调,触发下一曲 def after_callback(error): if error: print(f"播放出错: {error}") # 调度下一首播放 if is_looping and not voice_client.is_playing() and not voice_client.is_paused(): asyncio.run_coroutine_threadsafe(play_next(voice_client), client.loop) voice_client.play(audio_source, after=after_callback) # 定时播放指定音频的异步函数 async def scheduled_play_loop(voice_client: discord.VoiceClient): global scheduled_audio while scheduled_audio is not None: await asyncio.sleep(10) # 当前没有播放内容时才播定时音频,要插队播放可删除下方的播放状态判断 if scheduled_audio and not voice_client.is_playing() and not voice_client.is_paused(): audio_source = discord.FFmpegPCMAudio(executable=FFMPEG_PATH, source=scheduled_audio) voice_client.play(audio_source, after=None) # 启动随机循环播放指令 @client.command() async def start_loop(ctx): global is_looping if not ctx.author.voice: return await ctx.send(f"{ctx.author.mention} 你需要先加入一个语音频道") # 获取或创建语音客户端 voice_client = discord.utils.get(client.voice_clients, guild=ctx.guild) if not voice_client: voice_client = await ctx.author.voice.channel.connect() if is_looping: return await ctx.send("随机循环播放已经在运行中") is_looping = True await play_next(voice_client) await ctx.send("已启动随机音频循环播放") # 设置定时播放音频指令 @client.command() async def set_scheduled(ctx, audio_path: str): global scheduled_audio, scheduled_task if not ctx.author.voice: return await ctx.send(f"{ctx.author.mention} 你需要先加入一个语音频道") voice_client = discord.utils.get(client.voice_clients, guild=ctx.guild) if not voice_client: voice_client = await ctx.author.voice.channel.connect() # 停止旧的定时任务 if scheduled_task: scheduled_task.cancel() scheduled_audio = audio_path # 启动新的定时任务 scheduled_task = client.loop.create_task(scheduled_play_loop(voice_client)) await ctx.send(f"已设置定时播放音频:{audio_path},将每隔10秒自动播放") # 停止所有播放任务指令 @client.command() async def stop_all(ctx): global is_looping, scheduled_audio, scheduled_task is_looping = False scheduled_audio = None if scheduled_task: scheduled_task.cancel() scheduled_task = None voice_client = discord.utils.get(client.voice_clients, guild=ctx.guild) if voice_client and (voice_client.is_playing() or voice_client.is_paused()): voice_client.stop() await ctx.send("已停止所有播放任务") # 原单次播放指令保留 @client.command() async def arvaa(ctx): if not ctx.author.voice: return await ctx.send(f"{ctx.author.mention} 你需要先连接到语音频道") voice_client = discord.utils.get(client.voice_clients, guild=ctx.guild) if not voice_client: voice_client = await ctx.author.voice.channel.connect() if voice_client.is_playing(): voice_client.stop() audio_source = discord.FFmpegPCMAudio(executable=FFMPEG_PATH, source=random.choice(arvaus)) voice_client.play(audio_source, after=None) client.run("你的机器人Token")
使用说明
- 随机循环播放:发送
!start_loop指令后,机器人会自动加入你所在的语音频道,持续随机选取列表中的音频播放,上一首播放完成后自动切下一首,无操作时会常驻语音频道 - 定时播放指定音频:发送
!set_scheduled 音频文件完整路径指令后,机器人会每隔10秒检查当前是否空闲,空闲时就播放指定音频 - 停止所有功能:发送
!stop_all即可停止循环播放和定时播放任务 - 原单次播放指令
!arvaa保留,触发后会停止当前正在播放的内容,单次播放随机音频
注意事项
- 确保Discord开发者后台已经开启了
Message Content Intent权限,否则指令不会触发 - 替换代码中的音频列表、机器人Token为你自己的配置,FFmpeg路径和你当前使用的保持一致即可
内容的提问来源于stack exchange,提问作者Waldorf
相关产品推荐
相关产品推荐

