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

Discord语音机器人无法播放音频文件问题求助

Discord语音机器人连接后断开且无声音问题排查思路

问题描述

我编写了一款Discord语音机器人,预期它会在20:00加入语音频道并播放音频。目前机器人能成功加入频道,但随即断开连接且无任何声音输出,日志显示ffmpeg进程异常终止等信息。已确认ffmpeg安装正常,附上代码求解决思路。

日志信息

2023-04-07 17:58:01 INFO     discord.player ffmpeg process 18258 has not terminated. Waiting to terminate... 
2023-04-07 17:58:01 INFO     discord.player ffmpeg process 18258 should have terminated with a return code of -9. 
2023-04-07 17:58:01 INFO     discord.voice_client The voice handshake is being terminated for Channel ID 1093533451778523241 (Guild ID 1093533451778523237) 
2023-04-07 17:58:01 INFO     discord.voice_client Disconnecting from voice normally, close code 1000. 
Audio file loaded: <discord.player.FFmpegPCMAudio object at 0x1021cca30> 
Audio could not be played: 

代码实现

import discord
import asyncio
import datetime

TOKEN = 'TOKEN HERE' 
CHANNEL_ID = CHANNEL ID HERE

client = discord.Client(intents=discord.Intents.all())

async def play_sound(voice_client):
    try:
        source = discord.FFmpegPCMAudio('audio.mp3')
        print(f"Audio file loaded: {source}")
        voice_client.play(source)
        while voice_client.is_playing():
            await asyncio.sleep(1)
    except Exception as e:
        print(f"Audio could not be played: {e}")

@client.event
async def on_ready():
    print('Bot is ready')
    now = datetime.datetime.now()
    target_time = datetime.time(hour=20, minute=00)
    if now.time() >= target_time:
        print(f"Current time: {now.time()}. Bot did not join channel.")
        return
    else:
        print(f"Current time: {now.time()}. Bot has joined at {target_time}.")
        await asyncio.sleep((datetime.datetime.combine(datetime.date.today(), target_time) - now).total_seconds())
        channel = client.get_channel(CHANNEL_ID)
        if channel is not None:
            try:
                voice_client = await channel.connect()
                print(f'{client.user} joined voice chat.')
                await asyncio.sleep(1)
                await play_sound(voice_client)
                await voice_client.disconnect()
                print(f'{client.user} left voice chat.')
            except Exception as e:
                print(f"Error during joining channel : {e}")
        else:
            print(f"Did not find a channel of ID {CHANNEL_ID}.")

client.run(TOKEN)

解决思路

  • 确认音频文件有效性:检查audio.mp3的路径是否正确(建议使用绝对路径避免相对路径问题),验证文件未损坏、编码为Discord支持的格式(如MP3、WAV),可以尝试用本地播放器播放确认文件正常。
  • 调整FFmpeg参数与路径:
    • 若系统无法自动找到FFmpeg,可指定其完整执行路径:
      source = discord.FFmpegPCMAudio('audio.mp3', executable="/usr/bin/ffmpeg")  # 根据系统环境替换路径
      
    • 添加FFmpeg参数提升稳定性,比如加入重连配置:
      source = discord.FFmpegPCMAudio(
          'audio.mp3',
          before_options="-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5",
          options="-vn"
      )
      
  • 修正播放等待逻辑:原代码的while循环可能存在判断误差,改用Discord.py内置的wait_until_done()方法等待音频播放完成:
    async def play_sound(voice_client):
        try:
            source = discord.FFmpegPCMAudio('audio.mp3')
            print(f"Audio file loaded: {source}")
            voice_client.play(source)
            await voice_client.wait_until_done()  # 等待播放结束
        except Exception as e:
            print(f"Audio could not be played: {e}")
    
  • 确保权限与时序正确性:
    • 确认机器人角色拥有连接语音频道和语音发言的权限;
    • 缩短或移除await asyncio.sleep(1),改用判断voice_client.is_connected()确认连接就绪后再播放音频,避免时序问题。
  • 捕获详细FFmpeg错误:通过获取FFmpeg的stderr输出排查具体错误:
    import subprocess
    from discord import FFmpegPCMAudio
    
    source = FFmpegPCMAudio('audio.mp3', stderr=subprocess.PIPE)
    # 在播放后读取stderr查看错误
    stderr = source.process.stderr.read().decode()
    if stderr:
        print(f"FFmpeg错误信息: {stderr}")
    

内容的提问来源于stack exchange,提问作者Jakub Nawrocki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:55:40