Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Voice*): filter out silent audio from video users #5035

Merged
merged 3 commits into from Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/client/voice/VoiceConnection.js
Expand Up @@ -473,7 +473,11 @@ class VoiceConnection extends EventEmitter {
}

onStartSpeaking({ user_id, ssrc, speaking }) {
this.ssrcMap.set(+ssrc, { userID: user_id, speaking: speaking });
this.ssrcMap.set(+ssrc, {
...(this.ssrcMap.get(+ssrc) || {}),
userID: user_id,
speaking: speaking,
});
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/client/voice/networking/VoiceWebSocket.js
Expand Up @@ -189,7 +189,11 @@ class VoiceWebSocket extends EventEmitter {
this.emit('sessionDescription', packet.d);
break;
case VoiceOPCodes.CLIENT_CONNECT:
this.connection.ssrcMap.set(+packet.d.audio_ssrc, { userID: packet.d.user_id, speaking: 0 });
this.connection.ssrcMap.set(+packet.d.audio_ssrc, {
userID: packet.d.user_id,
speaking: 0,
hasVideo: Boolean(packet.d.video_ssrc),
});
break;
case VoiceOPCodes.CLIENT_DISCONNECT:
const streamInfo = this.connection.receiver && this.connection.receiver.packets.streams.get(packet.d.user_id);
Expand Down
40 changes: 31 additions & 9 deletions src/client/voice/receiver/PacketHandler.js
@@ -1,7 +1,9 @@
'use strict';

const EventEmitter = require('events');
const Speaking = require('../../../util/Speaking');
const secretbox = require('../util/Secretbox');
const { SILENCE_FRAME } = require('../util/Silence');

// The delay between packets when a user is considered to have stopped speaking
// https://github.com/discordjs/discord.js/issues/3524#issuecomment-540373200
Expand Down Expand Up @@ -84,12 +86,30 @@ class PacketHandler extends EventEmitter {
const userStat = this.connection.ssrcMap.get(ssrc);
if (!userStat) return;

let opusPacket;
const streamInfo = this.streams.get(userStat.userID);
// If the user is in video, we need to check if the packet is just silence
if (userStat.hasVideo) {
opusPacket = this.parseBuffer(buffer);
if (opusPacket instanceof Error) {
// Only emit an error if we were actively receiving packets from this user
if (streamInfo) {
this.emit('error', opusPacket);
return;
}
}
if (SILENCE_FRAME.equals(opusPacket)) {
// If this is a silence frame, pretend we never received it
return;
}
}

let speakingTimeout = this.speakingTimeouts.get(ssrc);
if (typeof speakingTimeout === 'undefined') {
// Ensure at least the speaking bit is set.
// As the object is by reference, it's only needed once per client re-connect.
if (userStat.speaking === 0) {
userStat.speaking = 1;
userStat.speaking = Speaking.FLAGS.SPEAKING;
}
this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: userStat.speaking });
speakingTimeout = this.receiver.connection.client.setTimeout(() => {
Expand All @@ -106,15 +126,17 @@ class PacketHandler extends EventEmitter {
speakingTimeout.refresh();
}

let stream = this.streams.get(userStat.userID);
if (!stream) return;
stream = stream.stream;
const opusPacket = this.parseBuffer(buffer);
if (opusPacket instanceof Error) {
this.emit('error', opusPacket);
return;
if (streamInfo) {
const { stream } = streamInfo;
if (!opusPacket) {
opusPacket = this.parseBuffer(buffer);
if (opusPacket instanceof Error) {
this.emit('error', opusPacket);
return;
}
}
stream.push(opusPacket);
}
stream.push(opusPacket);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/client/voice/util/Silence.js
Expand Up @@ -10,4 +10,6 @@ class Silence extends Readable {
}
}

Silence.SILENCE_FRAME = SILENCE_FRAME;

module.exports = Silence;