diff --git a/FlowPluginsTs/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.ts index 7a2c5c6..cc56c2c 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.ts @@ -99,6 +99,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); @@ -160,6 +161,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res2 = await cli2.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.ts index a35c295..3ca660e 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.ts @@ -356,6 +356,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.ts index 59d3bfc..70f9ee1 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.ts @@ -182,6 +182,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.ts index 07050fe..2fce826 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.ts @@ -187,6 +187,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts index 2791d89..3a85dd6 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts @@ -168,6 +168,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSizeRatioLive/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSizeRatioLive/1.0.0/index.ts new file mode 100644 index 0000000..4207b2c --- /dev/null +++ b/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSizeRatioLive/1.0.0/index.ts @@ -0,0 +1,167 @@ +import { + IpluginDetails, + IpluginInputArgs, + IpluginOutputArgs, +} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; + +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +const details = (): IpluginDetails => ({ + name: 'Compare File Size Ratio Live', + description: ` + Compare either the estimated final size or current output size to the input size and + give an error if estimated final size or current size surpasses the threshold %. + + Works with 'FfmpegCommand', 'HandBrake Custom Arguments', 'Run Classic Transcode' and other flow plugins + that output a file. + + Can be placed anywhere before a plugin which outputs a new file. + ', + `, + style: { + borderColor: 'orange', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.11.01', + sidebarPosition: -1, + icon: 'faQuestion', + inputs: [ + { + label: 'Enabled', + name: 'enabled', + type: 'boolean', + defaultValue: 'true', + inputUI: { + type: 'switch', + }, + tooltip: 'Enable or disable this plugin. For example you may want to enable it for one set of transcoding tests.', + }, + { + label: 'Compare Method', + name: 'compareMethod', + type: 'string', + defaultValue: 'estimatedFinalSize', + inputUI: { + type: 'dropdown', + options: [ + 'estimatedFinalSize', + 'currentSize', + ], + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'enabled', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, + }, + tooltip: `Specify the method to compare. + Estimated Final Size: Compare the estimated final output size to the input size. + Current Size: Compare the current output size to the input size. + `, + }, + { + label: 'Threshold Size %', + name: 'thresholdPerc', + type: 'number', + defaultValue: '60', + inputUI: { + type: 'text', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'enabled', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, + }, + tooltip: `Enter the threshold size percentage relative to the input size. + An error will be triggered if the estimated or current size exceeds this percentage. + + For example, if the input size is 100MB and the threshold is 60%, the estimated final size or current size + must not surpass 60MB else an error will be given and processing will stop. + `, + }, + { + label: 'Check Delay (seconds)', + name: 'checkDelaySeconds', + type: 'number', + defaultValue: '20', + inputUI: { + type: 'text', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'enabled', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, + }, + tooltip: ` + Specify the delay in seconds before beginning the comparison. + A larger delay gives more time for the estimated final size to stabilize. + `, + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Continue to next plugin', + }, + ], +}); + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const plugin = (args: IpluginInputArgs):IpluginOutputArgs => { + const lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + + const enabled = Boolean(args.inputs.enabled); + const compareMethod = String(args.inputs.compareMethod); + const thresholdPerc = Number(args.inputs.thresholdPerc); + const checkDelaySeconds = Number(args.inputs.checkDelaySeconds); + + // eslint-disable-next-line no-param-reassign + args.variables.liveSizeCompare = { + enabled, + compareMethod, + thresholdPerc, + checkDelaySeconds, + }; + + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +export { + details, + plugin, +}; diff --git a/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts index e44dd1b..4250d34 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts @@ -122,6 +122,7 @@ const plugin = async (args:IpluginInputArgs):Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.ts index 546517b..48fe1ca 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.ts @@ -165,6 +165,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/apprise/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/apprise/1.0.0/index.ts index 7c4276c..d4e3364 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/tools/apprise/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/apprise/1.0.0/index.ts @@ -15,7 +15,7 @@ const details = ():IpluginDetails => ({ tags: '', isStartPlugin: false, pType: '', - requiresVersion: '2.11.01', + requiresVersion: '2.18.01', sidebarPosition: -1, icon: 'faBell', inputs: [ @@ -71,6 +71,7 @@ const plugin = async (args:IpluginInputArgs):Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts index b06893a..cd2e051 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts @@ -251,6 +251,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.ts index 34167d9..cfb9ed7 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.ts @@ -48,6 +48,7 @@ const plugin = async (args:IpluginInputArgs):Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts index c1d3244..f8db0c3 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts @@ -93,6 +93,7 @@ const plugin = async (args:IpluginInputArgs):Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts b/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts index 84018e8..f51b4cd 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts @@ -2,7 +2,7 @@ import fs from 'fs'; import { editreadyParser, ffmpegParser, getHandBrakeFps, handbrakeParser, } from './cliParsers'; -import { Ilog, IupdateWorker } from './interfaces/interfaces'; +import { Ilog, IpluginInputArgs, IupdateWorker } from './interfaces/interfaces'; import { IFileObject, Istreams } from './interfaces/synced/IFileObject'; import { fileExists } from './fileUtils'; @@ -71,6 +71,7 @@ interface Iconfig { updateWorker: IupdateWorker, logFullCliOutput: boolean, inputFileObj: IFileObject, + args: IpluginInputArgs, } class CLI { @@ -89,6 +90,13 @@ class CLI { hbPass = 0; + // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types + thread: any; + + cancelled = false; + + startTime = new Date().getTime(); + constructor(config: Iconfig) { this.config = config; } @@ -156,6 +164,58 @@ class CLI { this.lastProgCheck = n; this.oldProgress = perc; + + const secondsSinceStart = (new Date().getTime() - this.startTime) / 1000; + + // live size compare + if ( + this.config.args.variables.liveSizeCompare?.enabled + ) { + const { + compareMethod, + thresholdPerc, + checkDelaySeconds, + } = this.config.args.variables.liveSizeCompare; + + if (secondsSinceStart > checkDelaySeconds) { + // MB + const inputFileSize = this.config.inputFileObj.file_size; + const inputFileSizeInGbytes = inputFileSize / 1024; + + const cancel = (ratio:number) => { + this.config.jobLog(`Input file size: ${inputFileSizeInGbytes}GB`); + this.config.jobLog(`Ratio: ${ratio}%`); + + this.config.jobLog(`Ratio is greater than threshold: ${thresholdPerc}%, cancelling job`); + this.cancelled = true; + this.killThread(); + }; + + if ( + compareMethod === 'estimatedFinalSize' + && estSize !== undefined + && estSize > 0 + ) { + const ratio = (estSize / inputFileSizeInGbytes) * 100; + + if (ratio > thresholdPerc) { + this.config.jobLog(`Estimated final size: ${estSize}GB`); + cancel(ratio); + } + } else if ( + compareMethod === 'currentSize' + && outputFileSizeInGbytes !== undefined + && outputFileSizeInGbytes > 0 + ) { + const ratio = (outputFileSizeInGbytes / inputFileSizeInGbytes) * 100; + + if (ratio > thresholdPerc) { + this.config.jobLog(`Current output size: ${outputFileSizeInGbytes}GB`); + cancel(ratio); + } + } + } + } } } } @@ -255,8 +315,7 @@ class CLI { } }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types - killThread = (thread:any): void => { + killThread = (): void => { const killArray = [ 'SIGKILL', 'SIGHUP', @@ -265,14 +324,14 @@ class CLI { ]; try { - thread.kill(); + this.thread.kill(); } catch (err) { // err } killArray.forEach((com: string) => { try { - thread.kill(com); + this.thread.kill(com); } catch (err) { // err } @@ -289,15 +348,12 @@ class CLI { this.config.jobLog(`Running ${this.config.cli} ${this.config.spawnArgs.join(' ')}`); - // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types - let thread: any; - const exitHandler = () => { - if (thread) { + if (this.thread) { try { // eslint-disable-next-line no-console console.log('Main thread exiting, cleaning up running CLI'); - this.killThread(thread); + this.killThread(); } catch (err) { // eslint-disable-next-line no-console console.log('Error running cliUtils on Exit function'); @@ -309,24 +365,24 @@ class CLI { process.on('exit', exitHandler); - const cliExitCode: number = await new Promise((resolve) => { + let cliExitCode: number = await new Promise((resolve) => { try { const opts = this.config.spawnOpts || {}; const spawnArgs = this.config.spawnArgs.map((row) => row.trim()).filter((row) => row !== ''); - thread = childProcess.spawn(this.config.cli, spawnArgs, opts); + this.thread = childProcess.spawn(this.config.cli, spawnArgs, opts); - thread.stdout.on('data', (data: string) => { + this.thread.stdout.on('data', (data: string) => { errorLogFull.push(data.toString()); this.parseOutput(data); }); - thread.stderr.on('data', (data: string) => { + this.thread.stderr.on('data', (data: string) => { // eslint-disable-next-line no-console errorLogFull.push(data.toString()); this.parseOutput(data); }); - thread.on('error', () => { + this.thread.on('error', () => { // catches execution error (bad file) // eslint-disable-next-line no-console console.log(`Error executing binary: ${this.config.cli}`); @@ -336,7 +392,7 @@ class CLI { // thread.stdout.pipe(process.stdout); // thread.stderr.pipe(process.stderr); - thread.on('close', (code: number) => { + this.thread.on('close', (code: number) => { if (code !== 0) { // eslint-disable-next-line no-console console.log(`CLI error code: ${code}`); @@ -355,12 +411,16 @@ class CLI { process.removeListener('exit', exitHandler); - thread = undefined; + this.thread = undefined; if (!this.config.logFullCliOutput) { this.config.jobLog(errorLogFull.slice(-1000).join('')); } + if (this.cancelled) { + cliExitCode = 1; + } + return { cliExitCode, errorLogFull, diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts b/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts index 1fdf402..0d1c6c8 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts @@ -96,12 +96,20 @@ export interface IffmpegCommand { overallOuputArguments: string[], } +export interface IliveSizeCompare { + enabled: boolean, + compareMethod: string, + thresholdPerc: number, + checkDelaySeconds: number, +} + export interface Ivariables { ffmpegCommand: IffmpegCommand, flowFailed: boolean, user: Record, healthCheck?: 'Success', queueTags?: string, + liveSizeCompare?: IliveSizeCompare } export interface IpluginOutputArgs {