BasePlayer.js (2752B)
1 'use strict'; 2 3 const EventEmitter = require('events'); 4 const { Readable: ReadableStream } = require('stream'); 5 const prism = require('prism-media'); 6 const StreamDispatcher = require('../dispatcher/StreamDispatcher'); 7 8 const FFMPEG_ARGUMENTS = ['-analyzeduration', '0', '-loglevel', '0', '-f', 's16le', '-ar', '48000', '-ac', '2']; 9 10 /** 11 * An Audio Player for a Voice Connection. 12 * @private 13 * @extends {EventEmitter} 14 */ 15 class BasePlayer extends EventEmitter { 16 constructor() { 17 super(); 18 19 this.dispatcher = null; 20 21 this.streamingData = { 22 channels: 2, 23 sequence: 0, 24 timestamp: 0, 25 }; 26 } 27 28 destroy() { 29 this.destroyDispatcher(); 30 } 31 32 destroyDispatcher() { 33 if (this.dispatcher) { 34 this.dispatcher.destroy(); 35 this.dispatcher = null; 36 } 37 } 38 39 playUnknown(input, options) { 40 this.destroyDispatcher(); 41 42 const isStream = input instanceof ReadableStream; 43 44 const args = isStream ? FFMPEG_ARGUMENTS.slice() : ['-i', input, ...FFMPEG_ARGUMENTS]; 45 if (options.seek) args.unshift('-ss', String(options.seek)); 46 47 const ffmpeg = new prism.FFmpeg({ args }); 48 const streams = { ffmpeg }; 49 if (isStream) { 50 streams.input = input; 51 input.pipe(ffmpeg); 52 } 53 return this.playPCMStream(ffmpeg, options, streams); 54 } 55 56 playPCMStream(stream, options, streams = {}) { 57 this.destroyDispatcher(); 58 const opus = (streams.opus = new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 })); 59 if (options && options.volume === false) { 60 stream.pipe(opus); 61 return this.playOpusStream(opus, options, streams); 62 } 63 streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 }); 64 stream.pipe(streams.volume).pipe(opus); 65 return this.playOpusStream(opus, options, streams); 66 } 67 68 playOpusStream(stream, options, streams = {}) { 69 this.destroyDispatcher(); 70 streams.opus = stream; 71 if (options.volume !== false && !streams.input) { 72 streams.input = stream; 73 const decoder = new prism.opus.Decoder({ channels: 2, rate: 48000, frameSize: 960 }); 74 streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 }); 75 streams.opus = stream 76 .pipe(decoder) 77 .pipe(streams.volume) 78 .pipe(new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 })); 79 } 80 const dispatcher = this.createDispatcher(options, streams); 81 streams.opus.pipe(dispatcher); 82 return dispatcher; 83 } 84 85 createDispatcher(options, streams, broadcast) { 86 this.destroyDispatcher(); 87 const dispatcher = (this.dispatcher = new StreamDispatcher(this, options, streams, broadcast)); 88 return dispatcher; 89 } 90 } 91 92 module.exports = BasePlayer;