javascript - 使用 discord.js 和 ytdl API 通过机器人播放音乐时的性能问题
问题描述
我正在使用discord.js api 制作音乐机器人,但我在播放音乐命令中遇到了性能问题。例如,如果机器人正在通话中播放某些东西,而我使用添加音乐命令,机器人会滞后几秒钟。我认为很多问题出在我用来获取音乐的 api 中,但我不确定。如果错误编写的代码通常会降低性能,如果您能帮助我,我将不胜感激。我正在使用ytdl api 来获取普通视频和ytpl来获取播放列表。这是整个命令:
const timelabel = require('timelabel')
const ytdl = require('ytdl-core')
const { Client, StreamDispatcher } = require('discord.js');
const client = new Client();
const ytpl = require('ytpl');
const Discord = require("discord.js")
const queue = new Map(); // Cada server vai ter um map (queue) diferente
//(message, guild.id, queue_constructor { voice channel, text channel, connection, song[]})
module.exports = {
commands: ['play', 'p '],
expectedArgs: '<url do video>',
permissionError: '',
minArgs: 1,
maxArgs: null,
callback: async (message, arguments, text) => {
if (message.channel.id === '753413520606887967') return;
const serverQueue = await queue.get(message.guild.id);
const voice_channel = await message.member.voice.channel;
const bot_channel = await message.guild.me.voice.channel;
if(!voice_channel) return message.channel.send('Voce precisa estar em uma call pra usar esse comando troxa')
if (bot_channel && bot_channel !== voice_channel) return message.channel.send(
"Você precisa estar na mesma call que o bot para usar esse comando burro")
const videoFinder = async (arguments) => {
const videoResult = await ytSearch(`${arguments}`);
// Se tiver mais de um resultado pro video, vai retornar o primeiro
return (videoResult.videos.length > 1) ? videoResult.videos[0] : null
}
const videoFinderPlaylist = async (arguments) => {
const playlistResult = await ytpl(`${arguments}`);
return (playlistResult) ? playlistResult : null
}
const video = await videoFinder(arguments.join(' '));
if (!video) {
try {
var playlist = await videoFinderPlaylist(arguments.join(' '));
} catch (err) {
return message.channel.send("Houve algum erro procurando esse link. Sugiro retirar **&ab_channel...** do link caso tiver algum.");
}
}
if (video) {
song =
{
title: video.title,
url: video.url,
videoLength: video.duration.timestamp,
seconds: video.duration.seconds,
thumbnail: video.thumbnail,
author: video.author.name,
userRequested: message.author.toString()
}
} else if (playlist) {
song = [];
for (let i = 0; playlist.items.length > i; i++) {
playlistSongs =
{
index: playlist.items[i].index,
title: playlist.items[i].title,
url: playlist.items[i].shortUrl,
videoLength: playlist.items[i].duration,
seconds: playlist.items[i].durationSec,
thumbnail: playlist.items[i].thumbnails[0].url,
author: playlist.items[i].author.name,
userRequested: message.author.toString()
}
song.push(playlistSongs);
}
}
if (!serverQueue) {
const queueConstructor =
{
voice_channel: voice_channel,
text_channel: message.channel,
connection: null,
songs: []
}
queueConstructor.songs = queueConstructor.songs.concat(song);
queue.set(message.guild.id, queueConstructor);
try {
const connection = await voice_channel.join();
queueConstructor.connection = connection;
videoPlay(message.guild, queueConstructor.songs[0].url);
} catch (err) {
queue.delete(message.guild.id);
message.channel.send('Houve um erro ao tentar se conectar à call');
console.log(err);
}
} else {
// get last element from the array
last = serverQueue.songs.length
serverQueue.songs = serverQueue.songs.concat(song);
let embed = new Discord.MessageEmbed()
.setColor("#73ffdc")
.setTitle("Adicionado á fila ♪")
.setThumbnail(serverQueue.songs[last].thumbnail)
.setDescription(`[${serverQueue.songs[last].title}](${serverQueue.songs[last].url})`)
.addFields(
{"name": "Canal", "value": serverQueue.songs[last].author, inline: true},
{"name": "Duração", "value": serverQueue.songs[last].videoLength, inline: true},
{"name": "\u200B","value": "`Requested by: `" + `${serverQueue.songs[last].userRequested}`});
EmbedMsg = serverQueue.text_channel.send(embed)
}
},
permissions: '',
requiredRoles: [],
}
const videoPlay = async (guild, song) => {
const songQueue = queue.get(guild.id)
module.exports.songQueue = queue.get(guild.id)
let embed = new Discord.MessageEmbed();
// Se a queue ta vazia
if (!song) {
return queue.delete(guild.id)
}
//console.log(songQueue.connection)
const stream = ytdl(song, { filter: 'audioonly' });
const dispatcher = await songQueue.connection.play(stream, { seek: 0, volume: 0.5, filter: "audioonly"})
.on('speaking', () =>{
module.exports.tempo = dispatcher.streamTime
})
.on ('finish', () => {
// Quando acaba a musica da shift para proxima da queue
try {
embedMsgID.delete();
} catch (err) {
console.log(err)
}
songQueue.songs.shift();
return (songQueue.songs.length > 0) ? videoPlay(guild, songQueue.songs[0].url) : videoPlay(guild, false);
})
.on('error', err => {
songQueue.text_channel.send(`Houve um erro enquanto tocava **${songQueue.songs[0].title}**`);
songQueue.songs.shift();
return (songQueue.songs.length > 0) ? videoPlay(guild, songQueue.songs[0].url) : videoPlay(guild, false)
})
if (songQueue.songs.length > 0) {
embed
.setColor("#73ffdc")
.setTitle("Tocando agora ♪")
.setThumbnail(songQueue.songs[0].thumbnail)
.setDescription(`[${songQueue.songs[0].title}](${songQueue.songs[0].url})`)
.addFields(
{"name": "Canal", "value": songQueue.songs[0].author, inline: true},
{"name": "Duração", "value": songQueue.songs[0].videoLength, inline: true},
{"name": "\u200B","value": "`Requested by: `" + `${songQueue.songs[0].userRequested}`});
embedMsg = await songQueue.text_channel.send(embed)
embedMsgID = embedMsg;
} else {
return;
}
}
解决方案
推荐阅读
- r - 如何删除字符串中的空字符串(“”)
- node.js - Koa 在发送 postgresql 查询数据时发送“Not Found”
- ajax - 设置数据端点以接收来自 API 的推送数据
- javascript - 如何在 javascript 中将十六进制(缓冲区)转换为 IPv6
- html - 想在 div 元素中居中一个 href 元素
- xcode11 - iOS 13 中的 ATS 策略是否已更改并且允许任意加载现在不起作用?
- java - JDBC 事务未回滚 - setAutoCommit(false)
- delphi - Delphi 数组构造函数替代
- python - Pyinstaller 缺少引导加载程序
- c# - 如何使用带有 FakeConnectionFactory 类的 AsyncEventingBasicConsumer (rabbitmq - c#) 对消费者应用单元测试?