Speaking 'start'/'end' events trigger continuously - Caused by while loop?
I have two ts at global level:
let startedSpeakingTimestamp;
let stoppedSpeakingTimestamp;
then as part of my VoiceConnection/VoiceReceiver setup, I have my speaking event listeners below:
botConnection.receiver.speaking.on('start', (userId) => {
if (!startedSpeakingTimestamp) {
client.users.fetch(userId)
.then(user => {
startedSpeakingTimestamp = Date.now();
const startedDate = new Date(startedSpeakingTimestamp)
console.log(
${user.displayName} started speaking at ${startedDate});
})
}
});
botConnection.receiver.speaking.on('end', (userId) => {
if ((!stoppedSpeakingTimestamp || Date.now() > stoppedSpeakingTimestamp) && userActive) {
client.users.fetch(userId)
.then(user => {
stoppedSpeakingTimestamp = Date.now();
const stoppedDate = new Date(stoppedSpeakingTimestamp)
console.log(
${user.displayName} finished speaking at ${stoppedDate});
});
}
});
Continued below18 Replies
- What's your exact discord.js
npm list discord.js
and node node -v
version?
- Not a discord.js issue? Check out #other-js-ts.
- Consider reading #how-to-get-help to improve your question!
- Explain what exactly your issue is.
- Post the full error stack trace, not just the top part!
- Show your code!
- Issue solved? Press the button!and I also have an async function that is triggered as part of the core flow, which has a while loop
async function startTimer() {
..........
while (userActive) {
elapsedTime = Date.now() - unmuteTimestamp;
silenceTime =
remainingTime = speakTime - elapsedTime
if (!startedSpeakingTimestamp && elapsedTime >= startedSpeakingLimit) {
console.log("${currentMember.displayName} did not start speaking.");
await muteUser(currentMember);
queue.push(queue.shift());
userActive = false;
} else if (remainingTime < speakTimeAlert && !timeAlert) {
timeAlert = true;
const remainingSecs = Math.round(remainingTime/1000)
const nextMember = queue[1]
const msgText = "${currentMember.displayName} has ${String(remainingSecs)} seconds left. ${nextMember.displayName} is next up to speak."
const channel = client.channels.cache.get(textChannelId);
if (channel && channel.isTextBased) {
await channel.send(msgText);
} else {
console.error('Text channel not found!');
}
} else if (elapsedTime >= speakTime) {
console.log("${currentMember.displayName} reached maximum speak time.");
await muteUser(currentMember);
queue.push(queue.shift());
userActive = false;
timeAlert = false;
}
await new Promise(resolve => setTimeout(resolve, userSwitchInterval));
}
continued below
My logs are showing that I'm constantly triggering the start/end events for speaking:
2024-05-05T22:09:27.857Z
geeks started speaking at Sun May 05 2024 23:09:28 GMT+0100 (British Summer Time)
geeks finished speaking at Sun May 05 2024 23:09:29 GMT+0100 (British Summer Time)
geeks finished speaking at Sun May 05 2024 23:09:29 GMT+0100 (British Summer Time)
geeks finished speaking at Sun May 05 2024 23:09:30 GMT+0100 (British Summer Time)
geeks finished speaking at Sun May 05 2024 23:09:30 GMT+0100 (British Summer Time)
(the started speaking I've handled, but still showing the end speaking triggers continuously)
My question is - Is this due to the while loop I have? Is it likely 'cutting off' the voice stream, thus triggering an 'end' speaking state?
Or could it be due to something else?
ThxUsing a setTimeout and clearing when a user speaks would be easier, no?
I'll see if I can try that code out once I get home
Seems more like an issue with your ifs in start and end event
You should both not use setTimeout to wait for it to get ready -- djs/voice has helpers for that
And not rely on a while loop to listen for changes -- events exist for that
removing those ifs gave the proper results
Thanks for the info, am looking at what happens when I remove the ifs in start and end
regarding the setTimeout/while loop.... are you referring to this block?
async function waitForConnectionStatus(botConnection) {
while (botConnection._state.status !== 'ready') { // Adjust the property and condition as needed
await new Promise(resolve => setTimeout(resolve, 1000)); // Adjust the delay as needed
}
}
Correct
One of them being that one
And the other the biggest while loop
I'm still getting repeated start/end triggers....
geeks started speaking at Wed May 08 2024 02:37:20 GMT+0100 (British Summer Time)
geeks finished speaking at Wed May 08 2024 02:37:21 GMT+0100 (British Summer Time)
geeks started speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks finished speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks started speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks finished speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks started speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
But I still have the while/set timeout loop/block in my startTimer function... (the biggest while loop)
You mentioned events exist that could better handle the requirements to consistently check for changes - how would I modify the below to do that?
https://gist.github.com/lucromano/72456246a763b844776b7111b6919ef4setting a timeout when a user starts to speak
and clear when it stops it
discord.js
discord.js
discord.js is a powerful Node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.
And this
i think this is the state for the VoiceConnection object when it's initialising no?
ie. when it's going through signalling, connecting, ready etc?
Nothing to do with tracking the receiver.speaking events (start or end)
That's for this
The thing is that my while loop is actually checking for Timestamps, not the start/end events.
The start/end events are updating the Timestamps which are then referred to
I'll try without any while loops to see what happens
So, I still get erroneous 'end' events triggering, even without any while loops.
It's nothing to do with my microphone or setup, because it happens with all users. It must be something to do with the configuration of sensitivity or something else regarding listening to the speaking user.
Could you be a little more specific with ettoneous end events?
geeks started speaking at Wed May 08 2024 02:37:20 GMT+0100 (British Summer Time)
geeks finished speaking at Wed May 08 2024 02:37:21 GMT+0100 (British Summer Time)
geeks started speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks finished speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks started speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks finished speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
geeks started speaking at Wed May 08 2024 02:37:23 GMT+0100 (British Summer Time)
But thats genuinely not happening. It's continuous voice... There must be an option to delay the trigger, such that regular speech can be considered ongoing.
Yep, it uses a setTimeout in end basically
But even continuous voice gets little "ends" sometimes