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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 04:39:03