node-ytdl-core: 'write EPIPE -4047' error with some videos

My friends tried to play this video on my Discord bot and it threw a write EPIPE (warning, it is loud): https://youtu.be/ihmDR7W1P1o

This video also throws a write EPIPE error but not immediately: https://www.youtube.com/watch?v=thW6YPgJm2U It happens on both Windows and Linux hosts, I could not find the culprit for this issue but it only happens with a few videos, there is a couple of examples above. Is it something to do with the format of the videos?

Error: write EPIPE
    at afterWriteDispatched (node:internal/stream_base_commons:162:15)
    at writeGeneric (node:internal/stream_base_commons:153:3)
    at Socket._writeGeneric (node:net:764:11)
    at Socket._write (node:net:776:8)
    at writeOrBuffer (node:internal/streams/writable:382:12)
    at Socket.Writable.write (node:internal/streams/writable:333:10)
    at PassThrough.ondata (node:internal/streams/readable:715:22)
    at PassThrough.emit (node:events:327:20)
    at PassThrough.Readable.read (node:internal/streams/readable:515:10)
    at flow (node:internal/streams/readable:988:34) {
  errno: -4047,
  code: 'EPIPE',
  syscall: 'write'
}

Sample of my code:

client.on("message", message => {
    
  var ismusicCommand = message.content.toLowerCase().startsWith(config.prefix + "play") || message.content.toLowerCase().startsWith(config.prefix + "skip") || message.content.toLowerCase().startsWith(config.prefix + "stop");
    
  if (message.author.bot) return;
  
  if (!message.channel.guild) {
      if (ismusicCommand == true) {
      message.react("723607808255197244");
      message.channel.send("Music functionality can only be used while in a guild!");
    return;
      }
      return;
  }

  const serverQueue = queue.get(message.guild.id);

  if (message.content.toLowerCase().startsWith(config.prefix + `play`)) {
    message.react("723607808062390363");
    execute(message, serverQueue);
    return;
  } else if (message.content.toLowerCase().startsWith(config.prefix + `skip`)) {
    message.react("723607808062390363");
    skip(message, serverQueue);
    return;
  } else if (message.content.toLowerCase().startsWith(config.prefix + `stop`)) {
    message.react("723607808062390363");
    stop(message, serverQueue);
    return;
  }
});

async function execute(message, serverQueue) {
  const args = message.content.split(" ");

  const voiceChannel = message.member.voice.channel;
  if (!voiceChannel)
    return message.channel.send("You need to be in a voice channel to play audio!");
  const permissions = voiceChannel.permissionsFor(message.client.user);
  if (!permissions.has("CONNECT") || !permissions.has("SPEAK")) {
    return message.channel.send("I need the permissions to join and play audio in your voice channel!");
  }

  const songInfo = await ytdl.getInfo(args[1]);
  const song = {
    title: songInfo.videoDetails.title,
    author: songInfo.videoDetails.author.name,
    url: songInfo.videoDetails.video_url
  };

  if (!serverQueue) {
    const queueContruct = {
      textChannel: message.channel,
      voiceChannel: voiceChannel,
      connection: null,
      songs: [],
      volume: 5,
      playing: true
    };

    queue.set(message.guild.id, queueContruct);

    queueContruct.songs.push(song);

    try {
      var connection = await voiceChannel.join();
      queueContruct.connection = connection;
      play(message.guild, queueContruct.songs[0]);
    } catch (err) {
      console.log(err);
      queue.delete(message.guild.id);
      return message.channel.send(err);
    }
  } else {
    serverQueue.songs.push(song);
    return message.channel.send(`${song.title} **by** ${song.author} has been added to the queue!`);
  }
}

function skip(message, serverQueue) {
  if (!message.member.voice.channel)
    return message.channel.send("You have to be in a voice channel to skip audio!");
  if (!serverQueue)
    return message.channel.send("There is no audio that I could skip!");
  serverQueue.connection.dispatcher.end();
}

function stop(message, serverQueue) {
  if (!message.member.voice.channel)
    return message.channel.send("You have to be in a voice channel to stop audio playback!");
  serverQueue.songs = [];
  serverQueue.connection.dispatcher.end();
  message.channel.send("Successfully stopped audio playback and left voice channel.")
}

function play(guild, song) {
  const serverQueue = queue.get(guild.id);
  if (!song) {
    serverQueue.voiceChannel.leave();
    queue.delete(guild.id);
    return;
  }

  const dispatcher = serverQueue.connection
    .play(ytdl(song.url), {bitrate: 192000 /* 192kbps */})
    .on("finish", () => {
      serverQueue.songs.shift();
      play(guild, serverQueue.songs[0]);
    })
    .on("error", error => console.error(error));
  dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
  serverQueue.textChannel.send(`Started playing: ${song.title} **by** ${song.author}`);
}

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Comments: 22 (3 by maintainers)

Most upvoted comments

Hi, I recently made a similar implementation and found a way to prevent this error. I am not sure I works 100% of the time, but so far it worked for me.

Here is the code I used :

let stream = ytdl(song.url, {
        filter : "audioonly",
        opusEncoded : false,
        fmt : "mp3",
        encoderArgs: ['-af', 'bass=g=10,dynaudnorm=f=200'] 
});

const dispatcher = serverQueue.connection
        .play(stream, {type : "unknown"})
        .on("finish", () => {
                //do finish step
        })
        .on("error", error => console.error(error));

I did not tried this code with the ffmpeg example but with my own discord bot

I’m unable to reproduce the error on either version with your code. I’ll leave this open in case someone else can help.