discord.js机器人在Discord语音频道固定频率丢包致音频卡顿问题求助
我在下载流并回放到Discord语音频道的过程中,发现机器人的音频每间隔20-22秒就会出现卡顿/断续的情况。经过多日测试,确认问题根源为发送丢包,但始终无法找到丢包的诱因。
已排查项
- 代码:100%确认问题与代码无关,两个运行逻辑完全不同的机器人都出现了完全相同的问题
- discord.js版本:v12和v13版本均复现相同问题
- CPU、磁盘、内存占用:无异常,服务器完全没有负载压力
opus/ffmpeg-static/fluent-ffmpeg包版本:均为最新版本- 服务器带宽:使用Ookla Speedtest和
speedtestnpm包测试均显示带宽充足,排除网速问题
补充环境信息
- node.js:v14.18.0(同版本node.js在本地电脑运行机器人完全无该问题)
- discord.js:v13.2.0
- 操作系统:Ubuntu 20.04.3 LTS

注:顶部数值偏高是因为拼接了两张截图,为播放音乐2分钟以上的Discord机器人连接统计数据。
相关代码
Discord.js v13 语音连接简化代码
var connectToChannel = async function (channel) { const connection = joinVoiceChannel({ channelId: channel.id, guildId: channel.guild.id, adapterCreator: channel.guild.voiceAdapterCreator, }); connection.resource = null; connection.play = function(resource) { connection.on = function(eventType, cb) { player.player.on(eventType, cb); return connection; }; connection.resource = createAudioResource(resource, { inlineVolume: true }); player.player.play(connection.resource); connection.subscribe(player.player); return connection; } return connection; }; // 其他位置调用代码 const connection = connectToChannel(member.voice.channel).then(async connection => { connection.play(ytdl(yturl)); }
注:使用的是无需设置highwatermark参数的
discord-ytdl-core,也测试过ytdl-core,甚至直接读取本地文件流播放,都出现完全相同的问题。
Discord.js v12 语音连接代码(本地文件播放测试场景)
var voiceChannel = message.member.voice.channel; voiceChannel.join().then(connection => { console.log("preparing to start"); const dispatcher = connection.play('./_.ogg', { highWaterMark: 50 }); }).catch(err => console.log(err));
注:调整highWaterMark参数哪怕到10MB,对丢包问题也完全没有改善。
可排查方向
- 检查云服务商UDP限制:Discord语音走UDP协议,部分云服务商默认对UDP小包有频率限制、流量整形规则,20秒左右的周期卡顿符合限速触发后缓存打满、丢包重置的特征,可临时关闭服务器防火墙、安全组规则测试,或联系服务商确认UDP相关限制。
- 测试到Discord语音节点的UDP链路质量:普通Speedtest测试的是通用下行带宽,不代表到Discord专属语音节点的UDP链路质量,可使用mtr工具做定向UDP链路丢包测试,排查路由节点是否存在周期性丢包。
- 调整系统UDP缓冲区配置:Ubuntu默认的UDP收发缓冲区参数偏小,高并发小包场景下容易出现内核层面丢包,可通过
sysctl net.core.rmem_max、sysctl net.core.wmem_max查看当前配置,适当调大参数测试。 - 验证系统级libopus版本:确认服务器安装的系统级libopus依赖版本和本地正常运行的环境版本一致,避免不同编译版本的opus编码出现间隔帧错误。
- 检查服务器时间同步状态:Discord语音链路对时间偏移敏感,服务器时间和标准时间偏差超过500ms时可能出现周期性会话重连、丢包,可运行
timedatectl status查看NTP时间同步状态。
内容的提问来源于stack exchange,提问作者PDKnight
相关产品推荐
相关产品推荐

