如何用discord.py开发类KDBot的TTS机器人并解决重复调用失效问题
问题核心原因
- 第二次调用指令时,机器人已经加入语音频道,
await channel.connect()会抛出异常走except分支,但你没有在except分支中获取当前已存在的VoiceClient实例,导致后续执行vc.play()时找不到vc变量直接报错。 - 没有判断当前是否有音频正在播放,多次调用会出现播放冲突。
修正方案
你可以通过ctx.voice_client直接获取当前服务器下机器人的语音客户端实例,不需要手动创建或存储实例,修正后代码如下:
@bot.command() async def tts(ctx,*, text:str): language = "es-us" # 先校验用户是否在语音频道 if not ctx.author.voice: await ctx.send("请先加入语音频道") return channel = ctx.author.voice.channel # 获取已有语音客户端,不存在则新建连接 vc = ctx.voice_client if not vc: vc = await channel.connect() else: # 如果机器人在其他频道,先移动到用户当前所在频道 if vc.channel.id != channel.id: await vc.move_to(channel) speech = gTTS(text=text,lang=language,slow=False) speech.save("audio.mp3") # 如果正在播放上一段音频,先停止 if vc.is_playing(): vc.stop() vc.play(discord.FFmpegPCMAudio('audio.mp3'), after=None) # 用自带的播放状态判断代替计数器,逻辑更准确 while vc.is_playing(): await asyncio.sleep(1) # 不需要自动断开就保留注释 #await vc.disconnect()
额外优化建议
- 多服务器使用场景下,建议给生成的音频文件增加服务器ID、时间戳类的唯一标识,避免多个请求同时读写同一个
audio.mp3出现冲突 - 可以注册播放完成回调代替轮询判断播放状态,性能表现更好
- 建议补充异常捕获逻辑,处理FFmpeg未安装、gTTS接口调用失败的异常情况
内容的提问来源于stack exchange,提问作者Alkerg
相关产品推荐
相关产品推荐

