Discord.js V13 Music Bot stops the music in the middle of the song

1.1k views Asked by At

I'm new to the coding scene and i have created a music Bot with Discord.js V13 but I keep getting an error that stops the music while playing. I don't know how to fix it and I didn't find any solutions.

Here's the code:

const { Client, VoiceChannel } = require('discord.js');
const config = require('./config.json');
const ytdl = require('ytdl-core');
const ytSearch = require('yt-search');
const {
    NoSubscriberBehavior,
    createAudioPlayer,
    createAudioResource,
    entersState,
    VoiceConnectionStatus,
    joinVoiceChannel,
    AudioPlayerStatus,
} = require('@discordjs/voice');
const voice = require('@discordjs/voice');

const prefix = '?';
const queue = new Map();

//------------------------------------------------Important----------------------------------------------------------

const player = createAudioPlayer({
    behaviors: {
        noSubscriber: NoSubscriberBehavior.Pause,
    },
});

async function connectToChannel(channel) {
    const connection = joinVoiceChannel({
        channelId: channel.id,
        guildId: channel.guild.id,
        adapterCreator: channel.guild.voiceAdapterCreator,
    });
    try {
        await entersState(connection, VoiceConnectionStatus.Ready, 30_000);
        return connection;
    } catch (error) {
        connection.destroy();
        throw error;
    }
}

const client = new Client({ intents: ['GUILDS', 'GUILD_MESSAGES', 'GUILD_VOICE_STATES'] });

client.on('ready', async () => {
    console.log('Bot is on!');
    //attachRecorder();
});

const videoFinder = async (query) => {
    const videoResult = await ytSearch(query);      
    return (videoResult.videos.length > 1) ? videoResult.videos[0] : null;
}

const validURL = (str) =>{
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
if(!regex.test(str)){
    return false;
} else {
    return true;
}
}

client.on('messageCreate', async (message) => {
    if (!message.guild) return;
    if(!message.content.startsWith(prefix) || message.author.bot) return;

    const args = message.content.slice(prefix.length).split(/ +/);
    const command = args.shift().toLowerCase();
    const channel = message.member?.voice.channel;
    const serverQueue = queue.get(message.guild.id);

    if(channel){
        if(command === 'play'){
            execute(message, serverQueue, args);
            return;
        } else if (command === 'skip') {
            skip(serverQueue);
            return;
        } else if (command === 'stop') {
            stop(serverQueue);
            return;
        }else if(command === 'leave'){
            leave(serverQueue);
            return;
        }else if(command === 'pause'){
            pause(serverQueue);
            return;
        }else if(command === 'resume'){
            resume(serverQueue);
            return;
        }
    }else {
        message.channel.send('Du bist in keinem Kanal!');
    }
});

//------------------------------------------------Important----------------------------------------------------------

//------------------------------------------------Befehle------------------------------------------------------------

async function execute(message, serverQueue, args) {
  
    const voiceChannel = message.member?.voice.channel;
    if (!voiceChannel)
      return message.channel.send("Du must in einem Sprachkanal sein!");
        
    /*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 speak in your voice channel!"
      );
    }*/

    var video;

    if (args[0] === '') {
        message.channel.send("Es ist kein Link/Video-Name eingegeben worden.");
    } else {
        video = await videoFinder(args.join(' '));
    }   

    var url;

            if(validURL(args[0])){  
                try{  
                    url = args[0];
                } catch(err){
                    console.log(err);
                    return message.channel.send(err);
                }
            
            } else if(video){
                url = video.url;
            } else {
                message.channel.send('Kein Video gefunden!');
            }
        
            

    const songinfo = await ytdl.getInfo(url);
    const song = {
          title: songinfo.videoDetails.title,
          url: songinfo.videoDetails.video_url,
     };
  
    if (!serverQueue) {
      const queueContruct = {
        textChannel: message.channel,
        voiceChannel: voiceChannel,
        connection: null,
        songStream: null,
        songs: [],
        volume: 5,
        playing: true
      };
  
      queue.set(message.guild.id, queueContruct);
  
      queueContruct.songs.push(song);
  
      try {
        const connection = await connectToChannel(voiceChannel);
        queueContruct.connection = connection;
        connection.subscribe(player);
        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}** wurde zur Warteschlange hinzugefügt.`);
      //
    }
  }

function leave(serverQueue){
    player.stop();
    serverQueue.songs = [];
    serverQueue.connection.destroy();
}

function pause(serverQueue){
    if (!serverQueue)
      return serverQueue.textChannel.send("Es gibt kein Lied zum Pausen!");
    player.pause();
}

function resume(serverQueue){
    if (!serverQueue)
      return serverQueue.textChannel.send("Es gibt kein Lied zum Entpausen!");
    player.unpause();
}

function skip(serverQueue) {
    if (!serverQueue)
      return serverQueue.textChannel.send("Es gibt kein Lied zum Skippen!");

    player.stop();
  }
  
  function stop(serverQueue) {  
    if (!serverQueue)
      return serverQueue.textChannel.send("Es gibt kein Lied zum Stoppen!");
      
    serverQueue.songs = [];
    player.stop();
  }
  
  function volume(serverQueue) {
    if (!serverQueue)
      return serverQueue.textChannel.send("Es gibt kein Lied zum wo die Lautstärke geändert werden kann!");
    serverQueue.vol
  }

//------------------------------------------------Befehle------------------------------------------------------------

//------------------------------------------------Crab---------------------------------------------------------------

function play(guild, song) {
    const serverQueue = queue.get(guild.id);
    if (!song) {
      serverQueue.connection.disconnect();
      queue.delete(guild.id);
      return;
    }
    
    var songStream;

    try {
        const buffer = ytdl(song.url, { filter: "audioonly" });
        songStream = createAudioResource(buffer, { inlineVolume: true }, {
            'options': '-vn',
            "before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5"
        }); 
    } catch (error) {
        console.log(error);
    }

    player.play(songStream);
    player.on(AudioPlayerStatus.Idle, () => {
        serverQueue.songs.shift();
        play(guild, serverQueue.songs[0])
    });
    player.on("error", error => console.error(error));
    songStream.volume.setVolumeLogarithmic(serverQueue.volume / 5);
    serverQueue.songStream = songStream;
    serverQueue.textChannel.send(`Spielt jetzt: **${song.title}**`);
  }

//------------------------------------------------Crab---------------------------------------------------------------



void client.login(config.token);

and when the music stops i get this error but the bot sill runs :

N [Error]: aborted
    at connResetException (node:internal/errors:691:14)
    at TLSSocket.socketCloseListener (node:_http_client:407:19)
    at TLSSocket.emit (node:events:402:35)
    at node:net:687:12
    at TCP.done (node:_tls_wrap:580:7) {
  resource: j {
    playStream: Encoder {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      encoder: null,
      _options: [Object],
      _required: 3840,
      _buffer: null,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: [Function: bound onwrite]
    },
    edges: [ [Object], [Object], [Object] ],
    metadata: null,
    volume: VolumeTransformer {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _readInt: [Function (anonymous)],
      _writeInt: [Function (anonymous)],
      _bits: 16,
      _bytes: 2,
      _extremum: 32768,
      volume: 1,
      _chunk: null,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: [Function: bound onwrite]
    },
    encoder: Encoder {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      encoder: null,
      _options: [Object],
      _required: 3840,
      _buffer: null,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: [Function: bound onwrite]
    },
    audioPlayer: H {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _state: [Object],
      subscribers: [Array],
      behaviors: [Object],
      debug: [Function (anonymous)],
      [Symbol(kCapture)]: false
    },
    playbackDuration: 56800,
    started: true,
    silencePaddingFrames: 5,
    silenceRemaining: -1
  }
}

How do I fix this?

2

There are 2 answers

2
Shockch4rge On

I have encountered that same issue, so I looked around and eventually found this gem.

import { AudioResource, createAudioResource, demuxProbe } from '@discordjs/voice';
import { raw as ytdl } from 'youtube-dl-exec';


function createAudioResource(url) {
        return new Promise((resolve, reject) => {
            const process = ytdl(
                url,
                {
                    o: '-',
                    q: '',
                    f: 'bestaudio[ext=webm+acodec=opus+asr=48000]/bestaudio',
                    r: '100K',
                },
                { stdio: ['ignore', 'pipe', 'ignore'] },
            );
            if (!process.stdout) {
                reject(new Error('No stdout'));
                return;
            }
            const stream = process.stdout;
            const onError = error => {
                if (!process.killed) process.kill();
                stream.resume();
                reject(error);
            };
            process
                .once('spawn', () => {
                    demuxProbe(stream)
                        .then(probe => resolve(createAudioResource(probe.stream, { metadata: this, inputType: probe.type })))
                        .catch(onError);
                })
                .catch(onError);
        });
    }

This is extracted from discordjs' own implementation of a music bot. Here they override the createAudioResource function with an executable wrapper for ytdl, and you will need to do the same. The npm package required here is youtube-dl-exec.

Audio worked perfectly for me from there, and this seemed to be the only way to fix it as well.

1
Kalle On

As stated here (https://github.com/porridgewithraisins/jam-bot), you should be using a LTS version of node.js.

Furthermore place this line of code on the beginning of your bot and I am pretty sure you would need to install node-abort-controller.

global.AbortController = require("node-abort-controller").AbortController;

I also encountered this problem and I fixed it with this solution.