Skip to content

Commit

Permalink
fix(Voice*): filter out silent audio from video users (#5035)
Browse files Browse the repository at this point in the history
  • Loading branch information
amishshah committed Nov 25, 2020
1 parent 53529bd commit 4fcb9eb
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 11 deletions.
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;

0 comments on commit 4fcb9eb

Please sign in to comment.