Discord机器人on_voice_state_update事件语音连接状态检测故障排查
Fixing Voice Connection Detection & Preventing Duplicate Actions in Your Discord Bot
Let's break down what's going wrong with your current code and how to fix it, step by step:
Key Issues in Your Original Code
- Incorrect ID Comparison: You're comparing
member.id(an integer) to a string like'id of member'—this will never evaluate to true, so the core logic inside that condition never runs. - Misplaced Sleep & Condition Check: You're sleeping before verifying if the event is relevant to your target member, leading to unnecessary delays and timing mismatches.
- No Concurrency Control: Without a lock, rapid-fire events (like multiple users entering AFK quickly) can trigger duplicate voice connections.
- Redundant Channel Lookup: You convert
before.channel.idto an integer just to fetch the channel again—you can usebefore.channeldirectly.
Corrected Code with Explanations
First, add an async lock to your cog's initialization to prevent concurrent voice operations:
import asyncio import discord from discord.ext import commands class YourCog(commands.Cog): def __init__(self, bot): self.bot = bot self.voice_lock = asyncio.Lock() # Prevents overlapping voice actions async def on_voice_state_update(self, member, before, after): # Configuration - replace these with your actual values (use integers for IDs!) TARGET_MEMBER_ID = 123456789012345678 # ID of the member you want to monitor MP3_FILE_PATH = '/full/path/to/your/audio.mp3' # Early exit if this isn't the event we care about if ( member.id != TARGET_MEMBER_ID or not after.afk or before.afk ): return # Ensure only one voice operation runs at a time async with self.voice_lock: # Reliably check if the bot is connected to any voice channel in this guild bot_member = member.guild.get_member(self.bot.user.id) if bot_member.voice and bot_member.voice.channel: # Bot is currently busy - skip this event (wait for lock to release if needed) return # Get the previous channel the member was in prev_channel = before.channel if not prev_channel: return # Member wasn't in a channel before, nothing to do # Execute the voice action with proper cleanup voice_client = None try: voice_client = await prev_channel.connect() # Play the audio file audio_source = discord.FFmpegPCMAudio(MP3_FILE_PATH) voice_client.play(audio_source) # Wait until the audio finishes playing (instead of fixed sleep) while voice_client.is_playing(): await asyncio.sleep(0.5) except Exception as e: print(f"Error during voice action: {str(e)}") finally: # Always disconnect, even if an error occurs if voice_client and voice_client.is_connected(): await voice_client.disconnect()
What Changed & Why
- Async Lock: The
self.voice_lockensures that only one instance of the voice playback logic runs at a time. If multiple events trigger quickly, they'll wait until the lock is released (after the bot disconnects). - Early Event Filtering: We first check if the event is relevant to our target member before doing any heavy lifting, avoiding unnecessary processing.
- Reliable Connection Check: Using
bot_member.voicedirectly checks if the bot is present in any voice channel in the guild—this is more reliable than checkingvoice_clientsalone. - Audio Completion Wait: Instead of a fixed 5-second sleep, we wait until the audio stops playing, ensuring the full track is heard before disconnecting.
- Proper Error Handling: The try/finally block guarantees the bot disconnects even if an error occurs during playback.
- Fixed ID Comparison: Using integer IDs for the target member matches Discord's internal ID format.
Why Your Original is_connected Function Failed
Your nested is_connected function was technically correct, but it was being called before checking if the event was relevant. This meant you were sleeping 9 seconds for every voice state change (even unrelated ones), leading to confusion about whether it was working. Additionally, the string ID comparison meant the core logic inside the condition never executed, making it seem like the connection check was broken.
内容的提问来源于stack exchange,提问作者nxfi777
相关产品推荐
相关产品推荐

