discord.io icon indicating copy to clipboard operation
discord.io copied to clipboard

Stopping Audio Playback

Open rGunti opened this issue 7 years ago • 18 comments

I used the example here to send Audio files. Now I wanted to implement a Skip command which stops the current playback and starts the next one. But I don't really know how to do that with the methods provided.

I tried stopping the stream but then the socket closes and the app crashes with this error:

Debugger attached.
events.js:182
      throw er; // Unhandled 'error' event
      ^

Error: This socket is closed
    at Socket._writeGeneric (net.js:721:18)
    at Socket._write (net.js:781:8)
    at doWrite (_stream_writable.js:371:12)
    at clearBuffer (_stream_writable.js:497:7)
    at onwrite (_stream_writable.js:423:7)
    at WriteWrap.afterWrite [as oncomplete] (net.js:863:12)

rGunti avatar Aug 05 '17 13:08 rGunti

What's your code for doing this?

izy521 avatar Aug 05 '17 16:08 izy521

bot.getAudioContext(voiceChannel, function(err, stream){ stream.stop(); });

jorenvandeweyer avatar Aug 16 '17 16:08 jorenvandeweyer

I'm not sure PR #186 fixes this issue. It sounds like he's not keeping the stream open, but he hasn't posted his code, so I can't proceed until then.

izy521 avatar Aug 17 '17 02:08 izy521

I'm having a similar issue of trying to stop. #186 doesn't fix it. When the bot leaves the channel or stops the stream while an audio file is playing, I get that same error. I'm not sure how to go about safely stopping the file stream before exiting the voice channel.

var startAudio = function ()
{
	bot.getAudioContext(VCID, function (error, stream) {
		//Once again, check to see if any errors exist
		if (error) return console.error(error);
		//filePath is just the js's path + "/"
		currentlyPlaying = fs.createReadStream(filePath + "Music/" + fs.readdirSync(filePath + "Music")[SongChoice])
		//Without {end: false}, it would close up the stream, so make sure to include that.
		currentlyPlaying.pipe(stream, { end: false });
		if (error) return console.error(error);
		
		//The stream fires `done` when it's got nothing else to send to Discord.
		stream.on('done', function () {
			bot.leaveVoiceChannel(VCID); //this exits fine with no crashes 
		});                        			
	});
}
  
var StopAudio = function()
{
	bot.leaveVoiceChannel(VCID); //method call caused socket to close and crash the bot if stream is still playing
}

Jays2Kings avatar Sep 04 '17 05:09 Jays2Kings

Your issue is just because you're leaving the channel without .stop()ing the stream. His issue sounds like he's not keeping the stream open, yet trying to send more data after its closed.

izy521 avatar Sep 04 '17 05:09 izy521

I've tried both leaving the channel and only stopping the stream without leaving the channel via bot.getAudioContext(VCID, function (err, stream) { stream.stop(); }); but the socket gets closed either way.

Jays2Kings avatar Sep 04 '17 05:09 Jays2Kings

What do you mean the socket gets closed?

izy521 avatar Sep 04 '17 06:09 izy521

I mean that the socket is closed when I stop the stream, resulting in a crash. I get a similar error to rGunti

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: This socket is closed
    at Socket._writeGeneric (net.js:679:19)
    at Socket._write (net.js:730:8)
    at doWrite (_stream_writable.js:331:12)
    at clearBuffer (_stream_writable.js:438:7)
    at onwrite (_stream_writable.js:370:7)
    at Socket.WritableState.onwrite (_stream_writable.js:90:5)
    at WriteWrap.afterWrite (net.js:812:12)

Jays2Kings avatar Sep 04 '17 06:09 Jays2Kings

What's your code? I'm heading to sleep, I'll check in the morning.

izy521 avatar Sep 04 '17 06:09 izy521

I've redacted the userIDs and voice channel id, but aside from that this is the same code that crashes when I stop the stream.

var Discord = require('discord.io');
var bot = new Discord.Client({
    autorun: true,
    token: ""
});

var filePath = "";
var fs = require("fs"), path = require('path'), util = require('util');
var firstrun = true;
var currentlyPlaying;
var danZoneStarterIDs = ["", "", "", ""];
var danZoneTime = false;
var danZoneTimeRunning = false;
var danZoneSongChoice = 0;
var VCID = '';
bot.on('ready', function (event) {
    console.log('Logged in as %s - %s\n', bot.username, bot.id);
    if (firstrun) { 
        filePath = __dirname + "/";
        firstrun = false;
    }
});

// Automatically reconnect if the bot disconnects due to inactivity
bot.on('disconnect', function (erMsg, code) {
    console.log(bot.userName + ' disconnected from Discord with code ' + code + ' for reason: ' + erMsg);
    bot.connect();
});

bot.on('message', function (user, userID, channelID, text, event) {
    if (userID != bot.id) {        
        if (danZoneStarterIDs.indexOf(userID) > -1) {
            if (!danZoneTime && text.toLowerCase() == "!join") {
                danZoneTime = true;
                var files = fs.readdirSync(filePath + "Dan Zone Music");
                danZoneSongChoice = Math.floor(Math.random() * files.length);
                bot.sendMessage({ to: channelID, message: "Joining Channel" });
                bot.joinVoiceChannel(VCID, function (error, events) {
                    //Check to see if any errors happen while joining.
                    if (error) return console.error(error);
                });
            }
            else if (!danZoneTimeRunning && danZoneTime && text.toLowerCase().indexOf("!start") == 0) {
                danZoneTimeRunning = true;
                //Then get the audio context
                bot.getAudioContext(VCID, function (error, stream) {
                    //Once again, check to see if any errors exist
                    if (error) return console.error(error);
                    bot.sendMessage({ to: channelID, message: "Now Playing: \"" + fs.readdirSync(filePath + "Dan Zone Music")[danZoneSongChoice].split('.')[0] + "\"" });
                    currentlyPlaying = fs.createReadStream(filePath + "Dan Zone Music/" + fs.readdirSync(filePath + "Dan Zone Music")[danZoneSongChoice])
                    //Without {end: false}, it would close up the stream, so make sure to include that.
                    currentlyPlaying.pipe(stream, { end: false });
                    if (error) return console.error(error);

                    //The stream fires `done` when it's got nothing else to send to Discord.
                    stream.on('done', function () {
                        if (danZoneTime) {
                            bot.leaveVoiceChannel(VCID);
                            danZoneTimeRunning = false;
                            danZoneTime = false;
                            bot.sendMessage({ to: channelID, message: "Finished Playing" });
                        }
                        //Handle
                    });
                    if (error) return console.error(error);
                });
            }
            else if (danZoneTimeRunning && text.toLowerCase() == "!stop") {
                danZoneTime = false;
                danZoneTimeRunning = false;
                bot.getAudioContext(VCID, function (err, stream) {
                    stream.stop();
                }); //causes crash if stream is playing something
                bot.sendMessage({ to: channelID, message: "Stopped" });
            }
            else if (text.toLowerCase() == "!leave") {
                bot.leaveVoiceChannel(VCID);
            }
        }
    }
});

Jays2Kings avatar Sep 04 '17 06:09 Jays2Kings

Try making the stream variable public after your first getAudioContext then referring to it again, instead of calling getAudioContext twice.

izy521 avatar Sep 04 '17 15:09 izy521

Still no luck, same error. when creating a var currentStream; setting it to currentStream = stream; the first time i call getAudioContext() in "!start" and in my "!stop" command i removed the getAudioContext() with

 currentlyPlaying.unpipe(currentStream);
  setTimeout(function () {
       currentStream.stop();
  }, 2000);

I've tried without the setTimeout, setting currentStream to null afterward, not unpiping the filestream, all results in the same crash.

Jays2Kings avatar Sep 04 '17 17:09 Jays2Kings

Alright, that's weird, I'll check it out later on today when I have the time, but I wish Node error's weren't so generic at times. Sounds like it's a clear issue in the back-end due to some change on Discord's side, but I'm not sure where.

izy521 avatar Sep 04 '17 18:09 izy521

Have you tried adding an error handler to the stream?

...
bot.getAudioContext(VCID, function (error, stream) {
    //Once again, check to see if any errors exist
    if (error) return console.error(error);
    stream.on('error',function(err){console.log("AudioContext Error:",err)});
...

DecibillyJoel avatar Sep 21 '17 16:09 DecibillyJoel

I know i have when i was using it. Didn't get any error from it though | Didn't stop it from crashing. Socket closed error anyways. Only happened when the bot left.

googleboy360 avatar Nov 26 '17 23:11 googleboy360

Still no update on this ?

tymmesyde avatar Mar 06 '18 16:03 tymmesyde

Any update on this?

Kyuraa avatar Aug 27 '18 14:08 Kyuraa

@rGunti i solve by like this : i create a start.js https://github.com/DeliDoktoru/FenomenDiscordBot/blob/master/start.js this js is a parent process. when discord bot died, calls again

YunusEmrahDursun avatar Nov 25 '18 12:11 YunusEmrahDursun