FFMpeg Discordjs Music Bot 在随机时间后随机停止播放音乐

Posted

技术标签:

【中文标题】FFMpeg Discordjs Music Bot 在随机时间后随机停止播放音乐【英文标题】:FFMpeg Discordjs Music Bot Randomly stops playing music after a random amount of time 【发布时间】:2021-12-20 19:26:17 【问题描述】:

我的音乐机器人会随机停止播放音乐并转到队列中的下一首歌曲。我该如何阻止这种情况发生?我已经提供了我的代码以及发生这种情况时在控制台中出现的错误。我试过改变 ffmpeg_options (我不确定我是否做错了)。我只是想让这个错误在理想情况下停止发生 - 我非常感谢任何帮助!

编辑:我正在使用节点 v16.13.0

这是我的代码:

const ytdl = require('ytdl-core');
const ytSearch = require('yt-search');
const  joinVoiceChannel, createAudioPlayer, createAudioResource  = require('@discordjs/voice');
const  leaveVoiceChannel  = require('@discordjs/voice');
const  execute  = require('./togglepeenie');
const voice = require('@discordjs/voice');
const  MessageEmbed  = require('discord.js');

const queue = new Map();
var player;
var thumbnail;
var link;
var songName;
let song = ;
let connection;
var date;
var startTime;

ffmpeg_options = 
    'options': '-vn',
    "before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5"


//queue(message.guild.id, queue_constructor object voice channel, text channel, connection, song[]);
module.exports = 
    name: 'play',
    aliases: ['p', 'skip', 's', 'stop', 'pause', 'state', 'nowplaying', 'np'],
    description: 'Handles all music bot commands.',
    
    async execute(message, args, cmd, client, Discord) 

        const voice_channel = message.member.voice.channel;
        if (!voice_channel) return message.channel.send('You need to be in a channel to execute this command!');
        const permissions = voice_channel.permissionsFor(message.client.user);
        if (!permissions.has('CONNECT')) return message.channel.send('You don\'t have the correct permissions. :(');
        if (!permissions.has('SPEAK')) return message.channel.send('You don\'t have the correct permissions. :(');

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

        if (cmd === 'play' || cmd === 'p') 
            if (!args.length) 
                //if no args, try to play paused song
                if (!player || player.state.status === 'idle') return message.channel.send(`<:x2:906412004632326154> **Nothing is playing** <:peeposad:875207109703262258>`);
                if (player.state.status === 'playing') return message.channel.send(`<:x2:906412004632326154> **The player is not paused** <:peeposad:875207109703262258>`);

                player.unpause();
                return message.channel.send(`:play_pause: **Resuming** :thumbsup:`);
            
            //let song = ;

            //if url, search the url
            if (ytdl.validateURL(args[0])) 
                const song_info = await ytdl.getInfo(args[0]);
                song =  title: song_info.videoDetails.title, url: song_info.videoDetails.video_url, image: song_info.videoDetails.thumbnail, seconds: song_info.videoDetails.timestamp, duration: song_info.videoDetails.duration
                //thumbnail = song.image;
                //songName = song.title;
                //link = song.url;
             
            //if keywords, search video with keywords
            else 
                const videoFinder = async (query) => 
                    const videoResult = await ytSearch(query);
                    return (videoResult.videos.length > 1) ? videoResult.videos[0] : null;
                

                const video = await videoFinder(args.join(' '));
                if (video) 
                    song =  title: video.title, url: video.url, image: video.thumbnail, seconds: video.timestamp, duration: video.duration 
                    //thumbnail = song.image;
                    //songName = song.title;
                    //link = song.url;
                 else 
                    return message.reply('No video results found. :(');
                
            //END OF KEYWORD SEARCH

            //If there isn't a queue, start a queue. message can be like "now playing".
        if (!server_queue) 
            const queue_constructor = 
                voice_channel: voice_channel,
                text_channel: message.channel,
                connection: null,
                songs: []
            

            queue.set(message.guild.id, queue_constructor);
            queue_constructor.songs.push(song);

            try 
                connection = await joinVoiceChannel(
                    channelId: voice_channel.id,
                    guildId: message.guild.id,
                    adapterCreator: message.guild.voiceAdapterCreator
                );
                queue_constructor.connection = connection;
                video_player(message.guild, queue_constructor.songs[0]);
             catch (err) 
                queue.delete(message.guild.id);
                message.channel.send('There was an error connecting!');
                throw err;
            

            //if there IS a queue, add to the queue. Message can be something like "added to queue."
         else 
            server_queue.songs.push(song);
            return message.reply(`:thumbsup: **$song.title added to queue!**`);
        

        //====================================
        //END OF PLAY COMMAND / P ALIAS

        else if(cmd === 'pause') 
            if (!player || player.state.status === 'idle') 
                return message.channel.send(`<:x2:906412004632326154> **Nothing is currently playing** <:peeposad:875207109703262258>`);
            
            if (player.state.status === 'paused') return message.channel.send(`<:x2:906412004632326154> **The player is already paused** <:peeposad:875207109703262258>`);
            player.pause();
            message.channel.send(`**Paused** :pause_button:`);
        
        else if(cmd === 'state') 
            if(!player) return console.log('No player.');
            console.log(player.state.status);
        
        else if(cmd === 'skip' || cmd === 's') 
            if (!server_queue)
                return message.channel.send(`<:x2:906412004632326154> **Nothing is currently playing** <:peeposad:875207109703262258>`);
            
            message.channel.send(`:fast_forward: ***Skipped*** :thumbsup:`);
            skip_song(message, server_queue);
        
        else if(cmd === 'np' || cmd === 'nowplaying') 
            if(!player || player.state.status === 'idle' || player.state.status === 'buffering') return message.channel.send(`<:x2:906412004632326154> **Nothing is currently playing** <:peeposad:875207109703262258>`);
            var currentTime;
            console.log(player.state.status);
            date = new Date();
            var rawTime = date.valueOf() - startTime;
            var time = getReadableTime(rawTime);
            var totalDuration = song.seconds;
            const embed = new MessageEmbed()
            .setColor('#edc937')
            .setAuthor('Now Playing ♪', `https://i.imgur.com/CXQGtpF.png`)
            .setDescription(`$songName`, link)
            .setThumbnail(`$thumbnail`)
            .addFields(
                 name: `$time / $totalDuration`, value: '\u200b' ,
            )
            .setTimestamp()
            .setFooter('`Requested by: `' + `$message.author.id`);
        message.channel.send(embeds: [embed])
        //END OF NOW PLAYING

        

    //END OF EXECUTE ON CMD RUN
    
    

var song_queue;
const video_player = async (guild, song) => 
    song_queue = queue.get(guild.id);

    if (!song) 
        player.stop();
        //player.delete();
        await voice.getVoiceConnection(guild.id).disconnect();
        queue.delete(guild.id);
        return;
    
    thumbnail = song_queue.songs[0].image;
    link = song_queue.songs[0].url;
    songName = song_queue.songs[0].title;

    const stream = ytdl(song.url, filter: 'audioonly');
    
    player = createAudioPlayer();
    const resource = createAudioResource(stream);
    

    player.play(resource);
    song_queue.connection.subscribe(player);
    var currentState = player.state;
    //console.log(currentState);

    date = new Date();
    startTime = date.valueOf();

    player.on('idle', () => 
    song_queue.songs.shift(),
    video_player(guild, song_queue.songs[0])
    );

    //setTimeout(() => song_queue.songs.shift(), video_player(guild, song_queue.songs[0]),  10000);

    
    await song_queue.text_channel.send(`Now playing **$song.title**`)
   


const skip_song = (message, server_queue) => 
    if (!message.member.voice.channel) return message.channel.send('You need to be in a channel to execute this command!');
    
    song_queue.songs.shift();
    video_player(message.guild, song_queue.songs[0]);
    


const getReadableTime = (rawTime) => 
    var totalSeconds = Math.floor(rawTime / 1000) - 1;
    var totalMinutes = Math.floor(totalSeconds / 60);
    var hours = Math.floor(totalMinutes / 60);
    var minutes = totalMinutes % 60;
    var seconds = totalSeconds % 60;
    if (seconds < 10) 
        seconds = `0$seconds`;
    
    if (hours == 0) 
        hours = '';
     else if (hours < 10) 
        hours = `0$hours:`;
     else 
        hours = `$hours:`;
    

    return `$hours$minutes:$seconds`;

这是每次中断时我得到的错误:

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: OggDemuxer 
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _remainder: null,
      _head: null,
      _bitstream: null,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: [Function: bound onwrite]
    ,
    edges: [ [Object], [Object] ],
    metadata: null,
    volume: undefined,
    encoder: undefined,
    audioPlayer: H 
      _events: [Object: null prototype],
      _eventsCount: 1,
      _maxListeners: undefined,
      _state: [Object],
      subscribers: [Array],
      behaviors: [Object],
      debug: [Function (anonymous)],
      [Symbol(kCapture)]: false
    ,
    playbackDuration: 563720,
    started: true,
    silencePaddingFrames: 5,
    silenceRemaining: -1
  
```

【问题讨论】:

你用的是什么版本的Node?​​span> 我正在使用节点 v16.13.0 这是ytdl-core 包的常见问题,您可以在this similar question 中阅读。你可以尝试降级这个包,看看这个错误是否一直发生。 如何降级软件包? 【参考方案1】:

如果您不想降级节点版本,请尝试使用play-dl 而不是ytdl-core

【讨论】:

play-dl 是否一样好,只是没有这些问题? 至少对我来说是的

以上是关于FFMpeg Discordjs Music Bot 在随机时间后随机停止播放音乐的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg转换增加比特率

如何安装 FFmpeg 让我的机器人播放音乐?

Music discord.js bot:“url”参数必须是字符串类型

尝试安装 discordjs/opus 时不断遇到这些错误

DiscordJS 获取用户不正确

DiscordJS / Canvas - 图像未从 URL 加载