Discord.js Voice无法播放ytdl流:TypeError报错及音频播放解决方案咨询
解决Discord.js Voice播放音频的报错问题
看起来你在Discord.js语音播放这块踩了个小坑,我来帮你捋清楚问题和解决办法:
核心错误原因
你遇到的TypeError: Cannot read properties of undefined (reading 'subscribe'),本质是conn2变量拿到的是undefined。因为voice.getVoiceConnection()这个方法需要传入服务器ID(guildId),而不是语音频道ID(channelId),你传错参数导致获取不到已建立的连接实例。
快速修复现有代码(Discord.js v14 + ytdl-core)
先修正连接获取的问题,同时还要给ytdl配置正确的音频参数,确保输出Discord支持的流格式:
// 省略前面的权限检查、songInfo获取逻辑... let conn = await voice.joinVoiceChannel({ channelId: voiceChannel.id, guildId: message.guild.id, adapterCreator: message.guild.voiceAdapterCreator, selfDeaf: false, selfMute: false }) // 👇 这里改用guildId获取连接,而不是channelId let conn2 = voice.getVoiceConnection(message.guild.id) console.log(conn2) // 现在应该能输出正常的连接实例了 // 配置ytdl输出纯音频流,且是Discord兼容的格式 const stream = ytdl(song.url, { filter: 'audioonly', // 只拉取音频 quality: 'highestaudio', // 最高音质 dlChunkSize: 0 // 避免分段下载导致的播放卡顿 }) // 订阅流开始播放 conn2.subscribe(stream)
其实更简洁的方式是直接用已经创建好的conn实例订阅,没必要再调用getVoiceConnection:
// 省略连接创建代码... const stream = ytdl(song.url, { filter: 'audioonly', quality: 'highestaudio' }) conn.subscribe(stream)
更稳定的进阶方案:配合opus编码处理流
有时候ytdl直接输出的流会有兼容性问题,推荐搭配@discordjs/opus和prism-media来转换格式,确保Discord能完美识别:
- 先安装依赖:
npm install @discordjs/opus prism-media ytdl-core
- 修改流处理代码:
const { OpusEncoder } = require('@discordjs/opus'); const { Transform } = require('prism-media'); // 创建ytdl纯音频流 const stream = ytdl(song.url, { filter: 'audioonly', quality: 'highestaudio' }); // 转换为Discord要求的48kHz双声道opus格式 const opusStream = new Transform({ transform(chunk, encoding, callback) { const encoder = new OpusEncoder(48000, 2); const opusBuffer = encoder.encode(chunk); callback(null, opusBuffer); }, }); // 订阅转换后的流 conn.subscribe(stream.pipe(opusStream));
多平台支持方案:用play-dl替代ytdl-core
ytdl-core经常会因为YouTube的API更新失效,play-dl是更稳定的替代工具,支持YouTube、Spotify、SoundCloud等多个平台:
- 安装依赖:
npm install play-dl @discordjs/voice
- 播放YouTube音频示例:
const playdl = require('play-dl'); const { createAudioResource, createAudioPlayer } = require('@discordjs/voice'); // 省略前面的语音频道检查、连接创建逻辑... const stream = await playdl.stream(song.url, { quality: 0, filter: 'audioonly' }); const audioResource = createAudioResource(stream.stream, { inputType: stream.type }); const audioPlayer = createAudioPlayer(); audioPlayer.play(audioResource); conn.subscribe(audioPlayer);
额外注意事项
- 确保你的Discord.js版本是v14及以上,因为
@discordjs/voice只兼容v14+ - 要在Discord开发者门户中开启Privileged Gateway Intents里的
GuildVoiceStates权限 - 如果遇到YouTube年龄/地区限制内容,可以给ytdl-core或play-dl配置代理参数
内容的提问来源于stack exchange,提问作者Mattia
相关产品推荐
相关产品推荐

