Discord.js机器人触发命令加入语音频道后仅高播放量YouTube视频可正常播放
故障核心原因
- 当前代码使用
ytdl-core默认配置拉取最高画质的音视频混合流,这类高码率流只有高播放量的热门视频才会被提前缓存到YouTube全球CDN边缘节点。机器人拉取低播放量、未列出视频的流地址时,会直接出现超时、返回无效资源的问题,根本无法启动音频推流。 - 现有代码仅监听了流播放完成的事件,没有补全错误捕获逻辑,一旦拉流出错,未捕获的异常会直接触发语音连接断开,表现就是机器人进了频道没发声就直接退出。
- 未列出/非公开视频如果设置了嵌入限制,
ytdl-core默认无鉴权的拉流请求会被YouTube直接拦截,拿不到合法的流地址。
对应修复方案
- 调整ytdl拉流参数,强制仅拉取音频流,优先选择最低码率的可用音频源,减少CDN拉取失败、转码损耗的问题,避免拉取高码率视频流。
- 给播放器补全错误捕获逻辑,把拉流、播放阶段的所有异常都捕获下来,异常触发时再主动断连,不要让未处理的错误直接掐断连接。
- 如果要播放自己上传的未列出视频,记得在YouTube视频设置里关闭嵌入限制,不然第三方工具拉流会被403拦截。
- 定期升级
ytdl-core到最新稳定版。YouTube会频繁调整前端签名校验逻辑,旧版本的ytdl会频繁出现接口失效问题,往往只有还没被下线的热门视频流地址能正常拉取,冷门视频的旧流地址早就被回收了。
修复后的参考代码:
if (message.content == "!sodium") { if (!message.member.voice.channel) return message.reply("You have to be in a voice channel"); message.member.voice.channel.join().then(VoiceConnection => { // 强制拉取低码率纯音频流 const audioStream = ytdl("https://youtu.be/30p-iRH9z2c", { filter: "audioonly", quality: "lowestaudio", highWaterMark: 1 << 25 // 扩大缓冲区避免中途断流 }); const audioDispatcher = VoiceConnection.play(audioStream, { type: "opus", // 直接使用Discord原生Opus编码减少转码开销 bitrate: "auto" }); // 补全错误捕获,避免未处理异常直接断开连接 audioDispatcher.on("error", err => { console.error("播放异常:", err); VoiceConnection.disconnect(); message.reply("音频流加载失败"); }); // 正常播放结束后断开连接 audioDispatcher.on("finish", () => { VoiceConnection.disconnect(); }); message.reply("started..."); }).catch(e => console.log(e)) };
内容的提问来源于stack exchange,提问作者OliverTnr
相关产品推荐
相关产品推荐

