【发布时间】:2021-12-12 09:21:37
【问题描述】:
我正在用 JavaScript 构建一个不和谐的音乐机器人(我昨天刚开始学习,所以代码可能有点乱)。到目前为止,我已经将歌曲添加到队列中,播放歌曲,然后在当前歌曲完成后移至下一首歌曲。但是,我遇到了一个小问题:每次我将一首歌曲添加到队列中时,机器人的音乐都会暂停一秒钟,而一首歌曲已经在播放。我发现这是因为 yt-search,这是我用来在 youtube 上搜索特定视频的模块。
这是 main.js 中的相关代码,通过 Node 运行的实际文件。
else if (cmd === 'play') {
const connection = getVoiceConnection(msg.guildId);
if (!connection) {
const join = await client.modules.backend.join(msg);
if (!join) return console.log('Unable to join');
}
if (!qMap.get(msg.guildId)) {
console.log('No queue for this server, creating a new one');
await client.modules.queue.construct(qMap, msg.guildId, msg.member.voice.channel, connection);
}
client.modules.queue.add(msg, qMap.get(msg.guildId), args, player);
有人使用“播放”命令播放歌曲;他们的搜索词与其他一些变量一起作为 args 传递给 queue.add。 queue.add 是从另一个模块导入的;这是代码:
async function queueAddSong(msg, queue, terms, player) {
song = searchForVideo(msg, terms);
console.log(`Adding to queue: ${song.title}`);
queue.songs.push(song);
if (player.state.status === 'idle') startQueue(queue, player);
}
这里是searchForVideo(),它会进行实际搜索:
async function searchForVideo(msg, query) {
let song = {};
// Was a valid URL passed? If yes, use ytdl. Otherwise, search.
if (ytdl.validateURL(query[0])) {
songInfo = await ytdl.getInfo(query[0]);
song = {
title: songInfo.videoDetails.title,
url: songInfo.videoDetails.video_url
};
} else {
// Search
const vidResults = await ytSearch(query.join(' '));
if (vidResults.videos.length > 1) {
song = {
title: vidResults.videos[0].title,
url: vidResults.videos[0].url
};
} else {
msg.reply(':x: No results found');
return null;
}
}
return song;
}
这里是startQueue(),它将歌曲转换为可用的流并播放它
function startQueue(queue, player) {
console.log(`Starting a new queue with song: ${queue.songs[0].title}`);
// Start a queue. Behavior is different from just switching songs, so I've made this a separate function.
const connection = getVoiceConnection(queue.voiceChannel.guildId);
const stream = ytdl(queue.songs[0].url, {
filter: 'audioonly'
});
const resource = createAudioResource(stream, {
inputType: StreamType.Arbitrary
});
// Play first song
player.play(resource);
connection.subscribe(player);
// Add event listener to play next song
player.on(AudioPlayerStatus.Idle, () => {
if (queue.songs.length > 1) {
console.log(`Song finished. Moving to: ${queue.songs[1].title}`);
queue.songs.shift();
playInQueue(queue, 0, player);
} else {
console.log(`Queue finished.`);
}
});
}
似乎ytsearch 的强度足以让整个线程停止足够长的时间以引起注意。如何独立于主线程运行搜索,以便无论搜索花费多少时间或处理能力,音乐在搜索时继续播放?
【问题讨论】:
-
您从引起问题的调用
ytsearch()中获得了多少结果?是不是数据量很大?机器人如何播放音乐?那个代码在哪里?使用正确编写的代码,我认为您不需要将 workerThread 仅用于网络搜索,除非您或库花费大量周期来处理结果。 -
没那么多;大约15-20。我对
ytsearch()不是很熟悉,所以我不确定每个结果返回多少数据,但它看起来像很多字符串。我实际上错了,不是 await 而是ytsearch()的实际处理导致了口吃。我最终用 workerThread 解决了这个问题,我对此很满意,因为这是一个小规模的个人项目。要回答其他所有问题,请使用 discord.js 中的voiceConnection、audioResource和audioPlayer。为简洁起见,我没有包含该代码,但我现在将用它来编辑问题。 -
似乎
song = searchForVideo(msg, terms);缺少await关键字? -
playInQueue是做什么的? -
@Bergi 是的,你是对的,那是缺少
await。playInQueue()与startQueue()所做的基本相同,但没有添加新的事件侦听器。它只是使用ytdl用指定的歌曲创建一个新流,用该流创建一个新资源,然后使用player.play(resource)。
标签: javascript node.js discord.js