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

使用Pycord开发音频录制Bot时遇sink参数缺失错误求助

问题分析与解决方案

错误根源

你遇到的MissingRequiredArgument: sink is a required argument that is missing错误,本质有两个核心问题:

  1. 调用.start命令时未指定音频格式参数(比如mp3/wav);
  2. 代码本身存在几个关键问题:前缀命令错误使用了斜杠命令专用的ApplicationContext、自定义Enum无法被Pycord命令转换器识别、未开启语音相关Intents。

修正后的完整代码

import discord
from enum import Enum
import os
from discord.ext import commands

# 开启必要的Intents,包括语音状态和消息内容
intents = discord.Intents.default()
intents.message_content = True
intents.voice_states = True  # 必须开启,否则无法获取用户语音频道信息

bot = commands.Bot(command_prefix=".", case_insensitive=True, intents=intents)

connections = {}

# 重新定义Sinks Enum,存储Sink类而非直接实例化
class Sinks(Enum):
    mp3 = discord.sinks.MP3Sink
    wav = discord.sinks.WaveSink
    pcm = discord.sinks.PCMSink
    ogg = discord.sinks.OGGSink
    mka = discord.sinks.MKASink
    mkv = discord.sinks.MKVSink
    mp4 = discord.sinks.MP4Sink
    m4a = discord.sinks.M4ASink

async def finished_callback(sink, channel: discord.TextChannel, *args):
    recorded_users = [f"<@{user_id}>" for user_id, audio in sink.audio_data.items()]
    await sink.vc.disconnect()
    files = [
        discord.File(audio.file, f"{user_id}.{sink.encoding}")
        for user_id, audio in sink.audio_data.items()
    ]
    await channel.send(
        f"录制完成!已录制以下用户的音频:{', '.join(recorded_users)}", files=files
    )

@bot.command()
async def start(ctx: commands.Context, sink_type: str):
    """开始录制语音,需指定格式,例如:.start mp3"""
    # 检查用户是否在语音频道
    if not ctx.author.voice:
        return await ctx.reply("你现在不在语音频道里!")
    
    # 验证传入的格式是否合法
    try:
        sink_cls = getattr(Sinks, sink_type.lower()).value
    except AttributeError:
        valid_formats = [member.name for member in Sinks]
        return await ctx.reply(f"不支持的格式!可选格式:{', '.join(valid_formats)}")
    
    # 连接到用户所在的语音频道
    vc = await ctx.author.voice.channel.connect()
    connections[ctx.guild.id] = vc
    
    # 实例化Sink并开始录制
    sink = sink_cls()
    vc.start_recording(
        sink,
        finished_callback,
        ctx.channel
    )
    
    await ctx.reply(f"已开始录制,格式为{sink_type}!")

@bot.command()
async def stop(ctx: commands.Context):
    """停止当前录制"""
    if ctx.guild.id in connections:
        vc = connections[ctx.guild.id]
        vc.stop_recording()
        del connections[ctx.guild.id]
        await ctx.reply("已停止录制,正在处理音频...")
    else:
        await ctx.reply("当前服务器没有正在进行的录制!")

@bot.event
async def on_ready():
    print(f"Bot已上线:{bot.user}")

bot.run(os.getenv('TOKEN'))

关键修改说明

  1. 修正上下文类:将ApplicationContext替换为commands.Context,前缀命令必须使用该上下文类,才能正常调用ctx.reply、ctx.author.voice等方法;
  2. 重构Enum定义:原Enum直接实例化Sink对象,改为存储Sink类,避免复用实例导致的异常,同时方便参数验证;
  3. 优化参数处理:将sink: Sinks改为sink_type: str,手动验证格式合法性,解决Pycord转换器无法识别自定义Enum的问题;
  4. 开启语音Intents:添加intents.voice_states = True,这是Bot获取用户语音状态的必要权限,缺失会导致ctx.author.voice返回None;
  5. 修复stop命令逻辑:将await ctx.delete()改为回复提示,避免因用户消息已删除导致的报错;
  6. 增强用户提示:添加格式验证反馈,让用户清楚知道支持的音频格式。

使用方法

  • 开始录制:.start mp3(可替换为wav、ogg等支持的格式)
  • 停止录制:.stop

内容的提问来源于stack exchange,提问作者Shweta K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:15:25