Reputation: 530
I'm trying to download and play an audio file fetched from youtube using ytdl and discord.js:
ytdl(url)
.pipe(fs.createWriteStream('./music/downloads/music.mp3'));
var voiceChannel = message.member.voiceChannel;
voiceChannel.join().then(connection => {
console.log("joined channel");
const dispatcher = connection.playFile('./music/downloads/music.mp3');
dispatcher.on("end", end => {
console.log("left channel");
voiceChannel.leave();
});
}).catch(err => console.log(err));
isReady = true
I successfully manage to play the mp3 file in ./music/downloads/ without the ytdl part (ytdl(url).pipe(fs.createWriteStream('./music/downloads/music.mp3'));
). But when that part is in the code, the bot just joins and leaves.
Here is the output with the ytdl part:
Bot has started, with 107 users, in 43 channels of 3 guilds.
joined channel
left channel
And here is the output without the ytdl part:
Bot has started, with 107 users, in 43 channels of 3 guilds.
joined channel
[plays mp3 file]
left channel
Why is that and how can i solve it?
Upvotes: 2
Views: 27172
Reputation:
You're doing it in an inefficient way. There's no synchronization between reading and writing.
Wait for the file to be written to the filesystem, then read it!
Redirect YTDL's video output to dispatcher, which would be converted to opus
audio data packets first, then streamed from your computer to Discord.
message.member.voiceChannel.join()
.then(connection => {
console.log('joined channel');
connection.playStream(ytdl(url))
// When no packets left to send, leave the channel.
.on('end', () => {
console.log('left channel');
connection.channel.leave();
})
// Handle error without crashing the app.
.catch(console.error);
})
.catch(console.error);
The approach you used wass pretty close to success, but the failure is when you don't synchronize read/write.
var stream = ytdl(url);
// Wait until writing is finished
stream.pipe(fs.createWriteStream('tmp_buf_audio.mp3'))
.on('end', () => {
message.member.voiceChannel.join()
.then(connection => {
console.log('joined channel');
connection.playStream(fs.createReadStream('tmp_buf_audio.mp3'))
// When no packets left to send, leave the channel.
.on('end', () => {
console.log('left channel');
connection.channel.leave();
})
// Handle error without crashing the app.
.catch(console.error);
})
.catch(console.error);
});
Upvotes: 1
Reputation: 2600
Use playStream instead of playFile when you need to play a audio stream.
const streamOptions = { seek: 0, volume: 1 };
var voiceChannel = message.member.voiceChannel;
voiceChannel.join().then(connection => {
console.log("joined channel");
const stream = ytdl('https://www.youtube.com/watch?v=gOMhN-hfMtY', { filter : 'audioonly' });
const dispatcher = connection.playStream(stream, streamOptions);
dispatcher.on("end", end => {
console.log("left channel");
voiceChannel.leave();
});
}).catch(err => console.log(err));
Upvotes: 6