Discord.Net无法接收语音数据:TryReadFrame始终返回false求助
问题排查与解决方案
针对你遇到的Discord机器人无法读取语音帧的问题,以下是具体的排查方向和修复建议:
1. 修正握手数据包格式
你发送的10字节空数据不符合Discord语音协议要求。Discord采用Opus编码,PCM流需满足48kHz采样率、16位深度、单声道,且每帧为20ms时长(对应1920字节)。应发送完整的静音帧作为握手包:
// 生成符合规格的静音帧:48000Hz * 0.02s * 2字节/采样 = 1920字节 byte[] silenceFrame = new byte[1920]; await outputStream.WriteAsync(silenceFrame, 0, silenceFrame.Length); await outputStream.FlushAsync();
2. 检查语音流的获取逻辑
确保AudioStream是从IAudioClient的有效接收流中获取的。在Discord.NET中,需通过订阅AudioClient.UserSpeaking事件关联说话用户的语音流,而非直接使用未初始化或错误的流对象。
3. 优化循环判断逻辑
AudioStream.CanRead无法可靠反映异步场景下的流状态,建议改用取消令牌控制循环,并添加短延迟避免空循环占用资源:
private async Task ReadAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { if (AudioStream.TryReadFrame(default, out var frame)) { Log.Debug("Frame read from user {User}", User.Username); // 处理语音帧逻辑 } else { await _writer!.StandardInput.BaseStream.WriteAsync(_silenceBuffer); await _writer!.StandardInput.BaseStream.FlushAsync(); // 20ms延迟匹配语音帧间隔 await Task.Delay(20, cancellationToken); } } Log.Debug("Reading voice data of {User} finished.", User.Username); }
4. 确认权限与网关意图
- 确保机器人拥有
Voice Receive服务器权限,邀请机器人时需勾选该权限; - 在Discord开发者门户的Bot设置中,启用
Privileged Gateway Intents下的GuildVoiceStates意图,否则机器人无法获取语音状态数据。
5. 验证语音客户端连接状态
在循环中添加连接状态检查,避免在连接异常时无效读取:
if (_audioClient.ConnectionState != ConnectionState.Connected) { Log.Warning("Audio client is not connected, skipping frame read."); await Task.Delay(1000); continue; }
内容的提问来源于stack exchange,提问作者Bohdan Petrenko
相关产品推荐
相关产品推荐

