From c495a5ae3623abb7f639fd69aab60e6663f388cb Mon Sep 17 00:00:00 2001 From: vexorian Date: Sun, 17 Jan 2021 12:31:46 -0400 Subject: [PATCH 1/3] Fix typo in logs. --- src/plex-player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plex-player.js b/src/plex-player.js index 9bde669..a6bce79 100644 --- a/src/plex-player.js +++ b/src/plex-player.js @@ -97,7 +97,7 @@ class PlexPlayer { emitter.emit('close'); }); ffmpeg.on('error', async (err) => { - console.log("Replacing failed stream with error streram"); + console.log("Replacing failed stream with error stream"); ff.unpipe(outStream); ffmpeg.removeAllListeners('data'); ffmpeg.removeAllListeners('end'); From 4c3e8f8d83e8c9955fc7a5981dd59927c3bce310 Mon Sep 17 00:00:00 2001 From: vexorian Date: Sun, 17 Jan 2021 12:29:14 -0400 Subject: [PATCH 2/3] Use correct input file indexes in offline filters. Fix white noise, beep sometimes not making a sound at all. --- src/ffmpeg.js | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/ffmpeg.js b/src/ffmpeg.js index b884c1c..b05238c 100644 --- a/src/ffmpeg.js +++ b/src/ffmpeg.js @@ -110,8 +110,8 @@ class FFMPEG extends events.EventEmitter { if (limitRead === true) ffmpegArgs.push(`-re`) + - if (typeof startTime !== 'undefined') ffmpegArgs.push(`-ss`, startTime) @@ -186,18 +186,20 @@ class FFMPEG extends events.EventEmitter { '-loop', '1', '-i', `${this.channel.offlinePicture}`, ); - videoComplex = `;[0:0]loop=loop=-1:size=1:start=0[looped];[looped]scale=${iW}:${iH}[videoy];[videoy]realtime[videox]`; + videoComplex = `;[${inputFiles++}:0]loop=loop=-1:size=1:start=0[looped];[looped]scale=${iW}:${iH}[videoy];[videoy]realtime[videox]`; } else if (this.opts.errorScreen == 'static') { ffmpegArgs.push( '-f', 'lavfi', '-i', `nullsrc=s=64x36`); videoComplex = `;geq=random(1)*255:128:128[videoz];[videoz]scale=${iW}:${iH}[videoy];[videoy]realtime[videox]`; + inputFiles++; } else if (this.opts.errorScreen == 'testsrc') { ffmpegArgs.push( '-f', 'lavfi', '-i', `testsrc=size=${iW}x${iH}`, ); videoComplex = `;realtime[videox]`; + inputFiles++; } else if (this.opts.errorScreen == 'text') { var sz2 = Math.ceil( (iH) / 33.0); var sz1 = Math.ceil( sz2 * 3. / 2. ); @@ -207,6 +209,7 @@ class FFMPEG extends events.EventEmitter { '-f', 'lavfi', '-i', `color=c=black:s=${iW}x${iH}` ); + inputFiles++; videoComplex = `;drawtext=fontfile=${process.env.DATABASE}/font.ttf:fontsize=${sz1}:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:text='${streamUrl.errorTitle}',drawtext=fontfile=${process.env.DATABASE}/font.ttf:fontsize=${sz2}:fontcolor=white:x=(w-text_w)/2:y=(h+text_h+${sz3})/2:text='${streamUrl.subtitle}'[videoy];[videoy]realtime[videox]`; } else if (this.opts.errorScreen == 'blank') { @@ -214,13 +217,15 @@ class FFMPEG extends events.EventEmitter { '-f', 'lavfi', '-i', `color=c=black:s=${iW}x${iH}` ); + inputFiles++; videoComplex = `;realtime[videox]`; } else {//'pic' ffmpegArgs.push( '-loop', '1', '-i', `${this.errorPicturePath}`, ); - videoComplex = `;[0:0]scale=${iW}:${iH}[videoy];[videoy]realtime[videox]`; + inputFiles++; + videoComplex = `;[${videoFile+1}:0]scale=${iW}:${iH}[videoy];[videoy]realtime[videox]`; } let durstr = `duration=${streamStats.duration}ms`; //silent @@ -233,12 +238,14 @@ class FFMPEG extends events.EventEmitter { ffmpegArgs.push('-i', `${this.channel.offlineSoundtrack}`); // I don't really understand why, but you need to use this // 'size' in order to make the soundtrack actually loop - audioComplex = `;[1:a]aloop=loop=-1:size=2147483647[audioy]`; + audioComplex = `;[${inputFiles++}:a]aloop=loop=-1:size=2147483647[audioy]`; } } else if (this.opts.errorAudio == 'whitenoise') { - audioComplex = `;aevalsrc=-2+0.1*random(0):${durstr}[audioy]`; + audioComplex = `;aevalsrc=random(0):${durstr}[audioy]`; + this.volumePercent = Math.min(70, this.volumePercent); } else if (this.opts.errorAudio == 'sine') { - audioComplex = `;sine=f=440:${durstr}[audiox];[audiox]volume=-35dB[audioy]`; + audioComplex = `;sine=f=440:${durstr}[audioy]`; + this.volumePercent = Math.min(70, this.volumePercent); } ffmpegArgs.push('-pix_fmt' , 'yuv420p' ); audioComplex += ';[audioy]arealtime[audiox]'; @@ -399,11 +406,11 @@ class FFMPEG extends events.EventEmitter { } ffmpegArgs.push( - '-map', currentVideo, - '-map', currentAudio, - `-c:v`, (transcodeVideo ? this.opts.videoEncoder : 'copy'), - `-flags`, `cgop+ilme`, - `-sc_threshold`, `1000000000` + '-map', currentVideo, + '-map', currentAudio, + `-c:v`, (transcodeVideo ? this.opts.videoEncoder : 'copy'), + `-flags`, `cgop+ilme`, + `-sc_threshold`, `1000000000` ); if ( transcodeVideo ) { // add the video encoder flags From c7703a2b7725b0df7ef31f9203537b8105b34275 Mon Sep 17 00:00:00 2001 From: vexorian Date: Sun, 17 Jan 2021 16:02:12 -0400 Subject: [PATCH 3/3] Try to play error stream when offline stream fails --- src/offline-player.js | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/offline-player.js b/src/offline-player.js index 4cd0361..802dd1f 100644 --- a/src/offline-player.js +++ b/src/offline-player.js @@ -37,7 +37,7 @@ class OfflinePlayer { } else { ff = await ffmpeg.spawnOffline(duration); } - ff.pipe(outStream); + ff.pipe(outStream, {'end':false} ); ffmpeg.on('end', () => { emitter.emit('end'); @@ -45,8 +45,32 @@ class OfflinePlayer { ffmpeg.on('close', () => { emitter.emit('close'); }); - ffmpeg.on('error', (err) => { - emitter.emit('error', err); + 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.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) {