start work with broadcast streams

This commit is contained in:
Amish Shah
2016-12-29 21:22:13 +00:00
parent e9af3f0a1f
commit 72a99f9582
6 changed files with 153 additions and 10 deletions

View File

@@ -0,0 +1,85 @@
const EventEmitter = require('events').EventEmitter;
const Prism = require('prism-media');
const ffmpegArguments = [
'-analyzeduration', '0',
'-loglevel', '0',
'-f', 's16le',
'-ar', '48000',
'-ac', '2',
];
class VoiceBroadcast extends EventEmitter {
constructor(client) {
super();
this.client = client;
this.dispatchers = [];
this.prism = new Prism();
this.currentTranscoder = null;
}
get _playableStream() {
if (!this.currentTranscoder) return null;
return this.currentTranscoder.transcoder.output || this.currentTranscoder.options.stream;
}
registerDispatcher(dispatcher) {
if (!this.dispatchers.includes(dispatcher)) this.dispatchers.push(dispatcher);
}
killCurrentTranscoder() {
if (this.currentTranscoder) {
if (this.currentTranscoder.transcoder) this.currentTranscoder.transcoder.kill();
this.currentTranscoder = null;
}
}
playStream(stream, { seek = 0, volume = 1, passes = 1 } = {}) {
const options = { seek, volume, passes };
options.stream = stream;
return this._playTranscodable(stream, options);
}
playFile(file, { seek = 0, volume = 1, passes = 1 } = {}) {
const options = { seek, volume, passes };
return this._playTranscodable(file, options);
}
_playTranscodable(media, options) {
this.killCurrentTranscoder();
const transcoder = this.prism.transcode({
type: 'ffmpeg',
media,
ffmpegArguments: ffmpegArguments.concat(['-ss', String(options.seek)]),
});
transcoder.once('error', e => this.emit('error', e));
transcoder.once('end', () => this.killCurrentTranscoder());
this.currentTranscoder = {
transcoder,
options,
};
transcoder.output.once('readable', () => this._startPlaying());
return this;
}
playConvertedStream(stream, { seek = 0, volume = 1, passes = 1 } = {}) {
this.killCurrentTranscoder();
const options = { seek, volume, passes, stream };
this.currentTranscoder = { options };
stream.once('readable', () => this._startPlaying());
return this;
}
_startPlaying() {
if (!this._playableStream) return;
const stream = this._playableStream;
const buffer = stream.read(1920 * 2);
for (const dispatcher of this.dispatchers) {
setImmediate(() => dispatcher.process(buffer, true));
}
setTimeout(this._startPlaying.bind(this), 20);
}
}
module.exports = VoiceBroadcast;