dizquetv/src/offline-player.js
2022-08-27 18:33:19 -04:00

96 lines
3.4 KiB
JavaScript

/******************
* Offline player is for special screens, like the error
* screen or the Flex Fallback screen.
*
* This module has to follow the program-player contract.
* Asynchronous call to return a stream. Then the stream
* can be used to play the program.
**/
const EventEmitter = require('events');
const FFMPEG = require('./ffmpeg')
class OfflinePlayer {
constructor(error, context) {
this.context = context;
this.error = error;
if (context.isLoading === true) {
context.channel = JSON.parse( JSON.stringify(context.channel) );
context.channel.offlinePicture = `http://localhost:${process.env.PORT}/images/loading-screen.png`;
context.channel.offlineSoundtrack = undefined;
}
if (context.isInterlude === true) {
context.channel = JSON.parse( JSON.stringify(context.channel) );
context.channel.offlinePicture = `http://localhost:${process.env.PORT}/images/black.png`;
context.channel.offlineSoundtrack = undefined;
}
this.ffmpeg = new FFMPEG(context.ffmpegSettings, context.channel);
this.ffmpeg.setAudioOnly(this.context.audioOnly);
}
cleanUp() {
this.ffmpeg.kill();
}
async play(outStream) {
try {
let emitter = new EventEmitter();
let ffmpeg = this.ffmpeg;
let lineupItem = this.context.lineupItem;
let duration = lineupItem.streamDuration - lineupItem.start;
let ff;
if (this.error) {
ff = await ffmpeg.spawnError(duration);
} else {
ff = await ffmpeg.spawnOffline(duration);
}
ff.pipe(outStream, {'end':false} );
ffmpeg.on('end', () => {
emitter.emit('end');
});
ffmpeg.on('close', () => {
emitter.emit('close');
});
ffmpeg.on('error', async (err) => {
//wish this code wasn't repeated.
if (! this.error ) {
console.log("Replacing failed stream with error stream");
ff.unpipe(outStream);
ffmpeg.removeAllListeners('data');
ffmpeg.removeAllListeners('end');
ffmpeg.removeAllListeners('error');
ffmpeg.removeAllListeners('close');
ffmpeg = new FFMPEG(this.context.ffmpegSettings, this.context.channel); // Set the transcoder options
ffmpeg.setAudioOnly(this.context.audioOnly);
ffmpeg.on('close', () => {
emitter.emit('close');
});
ffmpeg.on('end', () => {
emitter.emit('end');
});
ffmpeg.on('error', (err) => {
emitter.emit('error', err );
});
ff = await ffmpeg.spawnError('oops', 'oops', Math.min(duration, 60000) );
ff.pipe(outStream);
} else {
emitter.emit('error', err);
}
});
return emitter;
} catch(err) {
if (err instanceof Error) {
throw err;
} else {
throw Error("Error when attempting to play offline screen: " + JSON.stringify(err) );
}
}
}
}
module.exports = OfflinePlayer;