UNPKG

shadowsb

Version:

A unofficial discord.js fork for creating selfbots [Based on discord.js v13] (discord.js-selfbot-v13) for true version

146 lines (124 loc) 4.17 kB
'use strict'; const BaseDispatcher = require('./BaseDispatcher'); const Util = require('../../../util/Util'); const Silence = require('../util/Silence'); const VolumeInterface = require('../util/VolumeInterface'); const CHANNELS = 2; /** * @external WritableStream * @see {@link https://nodejs.org/api/stream.html#stream_class_stream_writable} */ /** * The class that sends voice packet data to the voice connection. * ```js * // Obtained using: * client.voice.joinChannel(channel).then(connection => { * // You can play a file or a stream here: * const dispatcher = connection.playAudio('/home/hydrabolt/audio.mp3'); * }); * ``` * @implements {VolumeInterface} * @extends {BaseDispatcher} */ class AudioDispatcher extends BaseDispatcher { constructor(player, { seek = 0, volume = 1, fec, plp, bitrate = 96, highWaterMark = 12 } = {}, streams) { const streamOptions = { seek, volume, fec, plp, bitrate, highWaterMark }; super(player, highWaterMark, Util.getPayloadType('opus'), false, streams); this.streamOptions = streamOptions; this.streams.silence = new Silence(); this.setVolume(volume); this.setBitrate(bitrate); if (typeof fec !== 'undefined') this.setFEC(fec); if (typeof plp !== 'undefined') this.setPLP(plp); } get TIMESTAMP_INC() { return 480 * CHANNELS; } get FRAME_LENGTH() { return 20; } /** * Get the type of the dispatcher * @returns {'audio'} */ getTypeDispatcher() { return 'audio'; } /** * Set the bitrate of the current Opus encoder if using a compatible Opus stream. * @param {number} value New bitrate, in kbps * If set to 'auto', the voice channel's bitrate will be used * @returns {boolean} true if the bitrate has been successfully changed. */ setBitrate(value) { if (!value || !this.bitrateEditable) return false; const bitrate = value === 'auto' ? this.player.voiceConnection.channel.bitrate : value; this.streams.opus.setBitrate(bitrate * 1000); return true; } /** * Sets the expected packet loss percentage if using a compatible Opus stream. * @param {number} value between 0 and 1 * @returns {boolean} Returns true if it was successfully set. */ setPLP(value) { if (!this.bitrateEditable) return false; this.streams.opus.setPLP(value); return true; } /** * Enables or disables forward error correction if using a compatible Opus stream. * @param {boolean} enabled true to enable * @returns {boolean} Returns true if it was successfully set. */ setFEC(enabled) { if (!this.bitrateEditable) return false; this.streams.opus.setFEC(enabled); return true; } get volumeEditable() { return Boolean(this.streams.volume); } /** * Whether or not the Opus bitrate of this stream is editable * @type {boolean} * @readonly */ get bitrateEditable() { return this.streams.opus && this.streams.opus.setBitrate; } // Volume get volume() { return this.streams.volume ? this.streams.volume.volume : 1; } setVolume(value) { if (!this.streams.volume) return false; /** * Emitted when the volume of this dispatcher changes. * @event AudioDispatcher#volumeChange * @param {number} oldVolume The old volume of this dispatcher * @param {number} newVolume The new volume of this dispatcher */ this.emit('volumeChange', this.volume, value); this.streams.volume.setVolume(value); return true; } /** * Sync with another video dispatcher to ensure that the audio and video are played at the same time. * @param {VideoDispatcher} otherDispatcher The video dispatcher to sync with */ setSyncVideoDispatcher(otherDispatcher) { if (otherDispatcher.getTypeDispatcher() !== 'video') { throw new Error('Dispatcher must be a video dispatcher'); } this._syncDispatcher = otherDispatcher; } // Volume stubs for docs /* eslint-disable no-empty-function*/ get volumeDecibels() {} get volumeLogarithmic() {} setVolumeDecibels() {} setVolumeLogarithmic() {} } VolumeInterface.applyToClass(AudioDispatcher); module.exports = AudioDispatcher;