diff --git a/.github/workflows/auto_build.yml b/.github/workflows/auto_build.yml new file mode 100644 index 000000000..91f0668f0 --- /dev/null +++ b/.github/workflows/auto_build.yml @@ -0,0 +1,21 @@ +name: Auto Build + +on: + push: + branches: + - master + +jobs: + test: + strategy: + matrix: + node-version: [18.x] + os: + [ + ["ubuntu-20.04"], + ] + runs-on: ${{ matrix.os }} + + steps: + - name: Trigger + run: "curl -XPOST -u \"${{ secrets.PAT_USERNAME}}:${{secrets.PAT_TOKEN}}\" -H \"Accept: application/vnd.github.everest-preview+json\" -H \"Content-Type: application/json\" https://api.github.com/repos/HaveAGitGat/tdarr_docs/actions/workflows/build_plug_docs.yml/dispatches --data '{\"ref\": \"main\"}'" \ No newline at end of file diff --git a/.github/workflows/lint_and_test.yml b/.github/workflows/lint_and_test.yml index f7fa63dcf..a57ab7e5d 100644 --- a/.github/workflows/lint_and_test.yml +++ b/.github/workflows/lint_and_test.yml @@ -12,8 +12,8 @@ jobs: os: [ ["ubuntu-20.04"], - ["windows-2019"], - ["macos-11.0"], + ["windows-2022"], + ["macos-14"], ] runs-on: ${{ matrix.os }} diff --git a/Community/Tdarr_Plugin_00td_action_add_audio_stream_codec.js b/Community/Tdarr_Plugin_00td_action_add_audio_stream_codec.js index ef3bacc02..1910c4634 100644 --- a/Community/Tdarr_Plugin_00td_action_add_audio_stream_codec.js +++ b/Community/Tdarr_Plugin_00td_action_add_audio_stream_codec.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_add_audio_stream_codec', Stage: 'Pre-processing', - Name: 'Add audio stream codec', + Name: 'Add Audio Stream Codec', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_00td_action_handbrake_basic_options.js b/Community/Tdarr_Plugin_00td_action_handbrake_basic_options.js index f9637e9b1..b925ce4f2 100644 --- a/Community/Tdarr_Plugin_00td_action_handbrake_basic_options.js +++ b/Community/Tdarr_Plugin_00td_action_handbrake_basic_options.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_handbrake_basic_options', Stage: 'Pre-processing', - Name: 'HandBrake basic options', + Name: 'HandBrake Basic Options', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js b/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js index a32bce816..ee1baa561 100644 --- a/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js +++ b/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom', Stage: 'Pre-processing', - Name: 'HandBrake or FFmpeg custom arguments', + Name: 'HandBrake Or FFmpeg Custom Arguments', Type: 'Video', Operation: 'Transcode', Description: ` @@ -70,7 +70,7 @@ HandBrake examples: type: 'text', }, tooltip: - 'Enter the desired container', + 'Enter the desired container. Set to "original" to keep the original container.', }, ], }); @@ -91,7 +91,13 @@ const plugin = (file, librarySettings, inputs, otherArguments) => { }; response.preset = inputs.arguments; - response.container = `.${inputs.container}`; + + if (inputs.container === 'original') { + response.container = `.${file.container}`; + } else { + response.container = `.${inputs.container}`; + } + response.handbrakeMode = inputs.cli === 'handbrake'; response.ffmpegMode = inputs.cli === 'ffmpeg'; response.reQueueAfter = true; diff --git a/Community/Tdarr_Plugin_00td_action_keep_one_audio_stream.js b/Community/Tdarr_Plugin_00td_action_keep_one_audio_stream.js index c0b3594bf..9d865dd7c 100644 --- a/Community/Tdarr_Plugin_00td_action_keep_one_audio_stream.js +++ b/Community/Tdarr_Plugin_00td_action_keep_one_audio_stream.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_keep_one_audio_stream', Stage: 'Pre-processing', - Name: 'Keep one audio stream', + Name: 'Keep One Audio Stream', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_00td_action_re_order_all_streams_v2.js b/Community/Tdarr_Plugin_00td_action_re_order_all_streams_v2.js index 8bbb5bb0d..1bd5de16f 100644 --- a/Community/Tdarr_Plugin_00td_action_re_order_all_streams_v2.js +++ b/Community/Tdarr_Plugin_00td_action_re_order_all_streams_v2.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_re_order_all_streams_v2', Stage: 'Pre-processing', - Name: 'Re-order all streams V2', + Name: 'Re-order All Streams V2', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_00td_action_remove_audio_by_channel_count.js b/Community/Tdarr_Plugin_00td_action_remove_audio_by_channel_count.js index b64dd7b8b..dd3d31c67 100644 --- a/Community/Tdarr_Plugin_00td_action_remove_audio_by_channel_count.js +++ b/Community/Tdarr_Plugin_00td_action_remove_audio_by_channel_count.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_remove_audio_by_channel_count', Stage: 'Pre-processing', - Name: 'Remove audio streams by channel count', + Name: 'Remove Audio Streams By Channel Count', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js b/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js index 4c8068990..8b476afa2 100644 --- a/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js +++ b/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js @@ -1,11 +1,12 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_remove_stream_by_specified_property', Stage: 'Pre-processing', - Name: 'Remove streams by specified property', + Name: 'Remove Streams By Specified Property', Type: 'Video', Operation: 'Transcode', Description: ` This plugin removes streams based on the specified property. + Checks FFprobe 'streams' and MediaInfo 'track' properties. `, Version: '1.00', Tags: 'action', @@ -76,7 +77,10 @@ const plugin = (file, librarySettings, inputs, otherArguments) => { let streamToRemove = false; for (let i = 0; i < file.ffProbeData.streams.length; i += 1) { try { - if (valuesToRemove.includes(String(file.ffProbeData.streams[i][propertyToCheck]))) { + if ( + valuesToRemove.includes(String(file.ffProbeData.streams[i][propertyToCheck])) + || valuesToRemove.includes(String(file.mediaInfo.track[i + 1][propertyToCheck])) + ) { response.preset += ` -map -0:${i} `; response.infoLog += ` Removing stream ${i} which is has ${propertyToCheck}` + ` of ${file.ffProbeData.streams[i][propertyToCheck]} \n`; diff --git a/Community/Tdarr_Plugin_00td_action_remux_container.js b/Community/Tdarr_Plugin_00td_action_remux_container.js index 0427bdaa3..3551e4c4d 100644 --- a/Community/Tdarr_Plugin_00td_action_remux_container.js +++ b/Community/Tdarr_Plugin_00td_action_remux_container.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_remux_container', Stage: 'Pre-processing', - Name: 'Remux container', + Name: 'Remux Container', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_00td_action_standardise_audio_stream_codecs.js b/Community/Tdarr_Plugin_00td_action_standardise_audio_stream_codecs.js index 9d40de96e..34a614d9b 100644 --- a/Community/Tdarr_Plugin_00td_action_standardise_audio_stream_codecs.js +++ b/Community/Tdarr_Plugin_00td_action_standardise_audio_stream_codecs.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_standardise_audio_stream_codecs', Stage: 'Pre-processing', - Name: 'Standardise audio stream codecs', + Name: 'Standardise Audio Stream Codecs', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_00td_action_transcode.js b/Community/Tdarr_Plugin_00td_action_transcode.js index 978c6f515..71e5b88dd 100644 --- a/Community/Tdarr_Plugin_00td_action_transcode.js +++ b/Community/Tdarr_Plugin_00td_action_transcode.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_action_transcode', Stage: 'Pre-processing', - Name: 'Transcode a video file', + Name: 'Transcode A Video File', Type: 'Video', Operation: 'Transcode', Description: 'Transcode a video file using ffmpeg. GPU transcoding will be used if possible.', diff --git a/Community/Tdarr_Plugin_00td_filter_bit_depth.js b/Community/Tdarr_Plugin_00td_filter_bit_depth.js index 576568aac..a58cc2b61 100644 --- a/Community/Tdarr_Plugin_00td_filter_bit_depth.js +++ b/Community/Tdarr_Plugin_00td_filter_bit_depth.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_bit_depth', Stage: 'Pre-processing', - Name: 'Filter bit depth: 8,10,12 bit video', + Name: 'Filter Bit Depth: 8,10,12 Bit Video', Type: 'Video', Operation: 'Filter', Description: 'Allow/disallow 8,10,12 bit video to be processed.', diff --git a/Community/Tdarr_Plugin_00td_filter_break_stack_if_processed.js b/Community/Tdarr_Plugin_00td_filter_break_stack_if_processed.js index 599f6cef2..6152a0529 100644 --- a/Community/Tdarr_Plugin_00td_filter_break_stack_if_processed.js +++ b/Community/Tdarr_Plugin_00td_filter_break_stack_if_processed.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_break_stack_if_processed', Stage: 'Pre-processing', - Name: 'Filter - break out of plugin stack if processed', + Name: 'Filter - Break Out Of Plugin Stack If Processed', Type: 'Video', Operation: 'Filter', Description: `This plugin will break out of the plugin stack if the file has been processed diff --git a/Community/Tdarr_Plugin_00td_filter_by_bitrate.js b/Community/Tdarr_Plugin_00td_filter_by_bitrate.js index 89d4777e7..5cbf7ed07 100644 --- a/Community/Tdarr_Plugin_00td_filter_by_bitrate.js +++ b/Community/Tdarr_Plugin_00td_filter_by_bitrate.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_by_bitrate', Stage: 'Pre-processing', - Name: 'Filter by bitrate', + Name: 'Filter By Bitrate', Type: 'Video', Operation: 'Filter', Description: 'Only allow files to be transcoded which are within the lower and upper bounds (Kb) \n\n', diff --git a/Community/Tdarr_Plugin_00td_filter_by_codec.js b/Community/Tdarr_Plugin_00td_filter_by_codec.js index 3e544062c..a20b9069b 100644 --- a/Community/Tdarr_Plugin_00td_filter_by_codec.js +++ b/Community/Tdarr_Plugin_00td_filter_by_codec.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_by_codec', Stage: 'Pre-processing', - Name: 'Filter by codec', + Name: 'Filter By Codec', Type: 'Video', Operation: 'Filter', Description: 'Only allow specified codecs to be processed \n\n', diff --git a/Community/Tdarr_Plugin_00td_filter_by_codec_tag_string.js b/Community/Tdarr_Plugin_00td_filter_by_codec_tag_string.js index 80a145c14..58dfb92da 100644 --- a/Community/Tdarr_Plugin_00td_filter_by_codec_tag_string.js +++ b/Community/Tdarr_Plugin_00td_filter_by_codec_tag_string.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_by_codec_tag_string', Stage: 'Pre-processing', - Name: 'Filter by codec tag string', + Name: 'Filter By Codec Tag String', Type: 'Video', Operation: 'Filter', Description: 'Only allow files with specified codec tag strings to be processed \n\n', diff --git a/Community/Tdarr_Plugin_00td_filter_by_file_property.js b/Community/Tdarr_Plugin_00td_filter_by_file_property.js index e0ae80c3f..27b25a38b 100644 --- a/Community/Tdarr_Plugin_00td_filter_by_file_property.js +++ b/Community/Tdarr_Plugin_00td_filter_by_file_property.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_by_file_property', Stage: 'Pre-processing', - Name: 'Filter by file property', + Name: 'Filter By File Property', Type: 'Video', Operation: 'Filter', Description: `Filter by a top level file property. diff --git a/Community/Tdarr_Plugin_00td_filter_by_resolution.js b/Community/Tdarr_Plugin_00td_filter_by_resolution.js index 81fcd8064..206b932a2 100644 --- a/Community/Tdarr_Plugin_00td_filter_by_resolution.js +++ b/Community/Tdarr_Plugin_00td_filter_by_resolution.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_by_resolution', Stage: 'Pre-processing', - Name: 'Filter by resolution', + Name: 'Filter By Resolution', Type: 'Video', Operation: 'Filter', Description: 'Only allow specified resolutions to be processed \n\n', diff --git a/Community/Tdarr_Plugin_00td_filter_by_size.js b/Community/Tdarr_Plugin_00td_filter_by_size.js index bc750be4e..b30561ac0 100644 --- a/Community/Tdarr_Plugin_00td_filter_by_size.js +++ b/Community/Tdarr_Plugin_00td_filter_by_size.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_by_size', Stage: 'Pre-processing', - Name: 'Filter by size', + Name: 'Filter By Size', Type: 'Video', Operation: 'Filter', Description: 'Only allow files to be transcoded which are within the lower and upper bounds (MB) \n\n', diff --git a/Community/Tdarr_Plugin_00td_filter_by_stream_tag.js b/Community/Tdarr_Plugin_00td_filter_by_stream_tag.js index ca17d0641..1aff87bcf 100644 --- a/Community/Tdarr_Plugin_00td_filter_by_stream_tag.js +++ b/Community/Tdarr_Plugin_00td_filter_by_stream_tag.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_00td_filter_by_stream_tag', Stage: 'Pre-processing', - Name: 'Filter by stream tag', + Name: 'Filter By Stream Tag', Type: 'Video', Operation: 'Filter', Description: `Filter by stream tag value. Will check all streams. Useful for when e.g. trying to force transcoding diff --git a/Community/Tdarr_Plugin_076a_re_order_audio_streams.js b/Community/Tdarr_Plugin_076a_re_order_audio_streams.js index 4eb510434..d8cc4147a 100644 --- a/Community/Tdarr_Plugin_076a_re_order_audio_streams.js +++ b/Community/Tdarr_Plugin_076a_re_order_audio_streams.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_076a_re_order_audio_streams", Stage: "Pre-processing", - Name: "Re-order audio streams", + Name: "Re-order Audio Streams", Type: "Audio", Operation: "Transcode", Description: `[Contains built-in filter] Specify a language tag for Tdarr to try and put as 1st audio track \n\n`, diff --git a/Community/Tdarr_Plugin_076b_re_order_subtitle_streams.js b/Community/Tdarr_Plugin_076b_re_order_subtitle_streams.js index 0a730246b..21596cf14 100644 --- a/Community/Tdarr_Plugin_076b_re_order_subtitle_streams.js +++ b/Community/Tdarr_Plugin_076b_re_order_subtitle_streams.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_076b_re_order_subtitle_streams", Stage: "Pre-processing", - Name: "Re-order subtitle streams", + Name: "Re-order Subtitle Streams", Type: "Subtitle", Operation: "Transcode", Description: `[Contains built-in filter] Specify a language tag for Tdarr to try and put as 1st subtitle track \n\n`, diff --git a/Community/Tdarr_Plugin_078d_Output_embedded_subs_to_SRT_and_remove.js b/Community/Tdarr_Plugin_078d_Output_embedded_subs_to_SRT_and_remove.js index f83c78dd9..00d0e879b 100644 --- a/Community/Tdarr_Plugin_078d_Output_embedded_subs_to_SRT_and_remove.js +++ b/Community/Tdarr_Plugin_078d_Output_embedded_subs_to_SRT_and_remove.js @@ -4,7 +4,7 @@ const details = () => { return { id: "Tdarr_Plugin_078d_Output_embedded_subs_to_SRT_and_remove", Stage: "Pre-processing", - Name: "Output embedded subs to SRT and remove", + Name: "Output Embedded Subs To SRT And Remove", Type: "Video", Operation: "Transcode", Description: `This plugin outputs embedded subs to SRT and then removes them \n\n`, diff --git a/Community/Tdarr_Plugin_43az_add_to_radarr.js b/Community/Tdarr_Plugin_43az_add_to_radarr.js index 7b6715875..67d23d445 100644 --- a/Community/Tdarr_Plugin_43az_add_to_radarr.js +++ b/Community/Tdarr_Plugin_43az_add_to_radarr.js @@ -4,7 +4,7 @@ const details = () => { return { id: 'Tdarr_Plugin_43az_add_to_radarr', Stage: 'Post-processing', - Name: 'Add movie to Radarr after processing', + Name: 'Add Movie To Radarr After Processing', Type: 'Video', Operation: 'Transcode', Description: 'Add movie to Radarr after processing \n\n', diff --git a/Community/Tdarr_Plugin_A47j_FFMPEG_NVENC_HEVC_Video_Only.js b/Community/Tdarr_Plugin_A47j_FFMPEG_NVENC_HEVC_Video_Only.js index 61e444684..15b51ab6b 100644 --- a/Community/Tdarr_Plugin_A47j_FFMPEG_NVENC_HEVC_Video_Only.js +++ b/Community/Tdarr_Plugin_A47j_FFMPEG_NVENC_HEVC_Video_Only.js @@ -4,7 +4,7 @@ const details = () => ({ id: 'Tdarr_Plugin_A47j_FFMPEG_NVENC_HEVC_Video_Only', Stage: 'Pre-processing', - Name: 'FFMPEG nvenc_H265 Video Only', + Name: 'FFMPEG:nvenc_H265 Video Only', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_DOOM_NVENC_Tiered_MKV_CleanAll.js b/Community/Tdarr_Plugin_DOOM_NVENC_Tiered_MKV_CleanAll.js index 3aadf9f31..4dc7c150e 100644 --- a/Community/Tdarr_Plugin_DOOM_NVENC_Tiered_MKV_CleanAll.js +++ b/Community/Tdarr_Plugin_DOOM_NVENC_Tiered_MKV_CleanAll.js @@ -4,7 +4,7 @@ const details = () => { return { id: "Tdarr_Plugin_DOOM_NVENC_Tiered_MKV_CleanAll", Stage: 'Pre-processing', - Name: "DOOM Tiered H265 MKV, remove audio & subtitles [NVENC]", + Name: "DOOM Tiered H265 MKV, Remove Audio & Subtitles [NVENC]", Stage: "Pre-processing", Type: "Video", Operation: "Transcode", diff --git a/Community/Tdarr_Plugin_ER01_Transcode audio and video with HW (PC and Mac).js b/Community/Tdarr_Plugin_ER01_Transcode audio and video with HW (PC and Mac).js index 7a62b7cd5..671d58358 100644 --- a/Community/Tdarr_Plugin_ER01_Transcode audio and video with HW (PC and Mac).js +++ b/Community/Tdarr_Plugin_ER01_Transcode audio and video with HW (PC and Mac).js @@ -8,7 +8,7 @@ const details = () => { return { id: 'Tdarr_Plugin_ER01_Transcode audio and video with HW (PC and Mac)', Stage: 'Pre-processing', - Name: 'Transcode Using QSV or VT & FFMPEG', + Name: 'Transcode Using QSV Or VT & FFMPEG', Type: 'Video', Operation: 'Transcode', Description: `Files not in H265 will be transcoded into H265 using hw with ffmpeg, assuming mkv container. Plugin uses QS if the node runs on a PC, or Videotoolbox if run on a Mac. diff --git a/Community/Tdarr_Plugin_Greg_MP3_FFMPEG_CPU.js b/Community/Tdarr_Plugin_Greg_MP3_FFMPEG_CPU.js index df4f6676c..c6f1373e7 100644 --- a/Community/Tdarr_Plugin_Greg_MP3_FFMPEG_CPU.js +++ b/Community/Tdarr_Plugin_Greg_MP3_FFMPEG_CPU.js @@ -2,7 +2,7 @@ module.exports.dependencies = ['import-fresh']; const details = () => ({ id: 'Tdarr_Plugin_Greg_MP3_FFMPEG_CPU', Stage: 'Pre-processing', - Name: 'Audio Transcode to MP3 using CPU and FFMPEG', + Name: 'Audio Transcode To MP3 Using CPU And FFMPEG', Type: 'Audio', Operation: 'Transcode', Description: '[Contains built-in filter] Convert an audio file to mp3, retaining ID3 tags, ' diff --git a/Community/Tdarr_Plugin_JB69_JBHEVCQSV_MinimalFile.js b/Community/Tdarr_Plugin_JB69_JBHEVCQSV_MinimalFile.js index 84bbafa7b..cc5e21368 100755 --- a/Community/Tdarr_Plugin_JB69_JBHEVCQSV_MinimalFile.js +++ b/Community/Tdarr_Plugin_JB69_JBHEVCQSV_MinimalFile.js @@ -89,7 +89,7 @@ Audio: (Only one audio stream is used!!) const details = () => ({ id: 'Tdarr_Plugin_JB69_JBHEVCQSV_MinimalFile', Stage: 'Pre-processing', - Name: 'JB - QSV(vaapi), H265, AAC, MKV, bitrate optimized', + Name: 'JB - QSV(vaapi), H265, AAC, MKV, Bitrate Optimized', Type: 'Video', Operation: 'Transcode', Description: `***You should not use this*** until you read the comments at the top of the code and understand diff --git a/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js b/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js index 7b655fe63..999e46711 100644 --- a/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js +++ b/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz1FFMPEG', Stage: 'Pre-processing', - Name: 'Migz-Transcode Using Nvidia GPU & FFMPEG', + Name: 'Migz Transcode Using Nvidia GPU & FFMPEG', Type: 'Video', Operation: 'Transcode', Description: `Files not in H265 will be transcoded into H265 using Nvidia GPU with ffmpeg. diff --git a/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js b/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js index 8d4d579aa..02c4f0043 100644 --- a/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js +++ b/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz1FFMPEG_CPU', Stage: 'Pre-processing', - Name: 'Migz-Transcode Using CPU & FFMPEG', + Name: 'Migz Transcode Using CPU & FFMPEG', Type: 'Video', Operation: 'Transcode', Description: `Files not in H265 will be transcoded into H265 using CPU with ffmpeg. diff --git a/Community/Tdarr_Plugin_MC93_Migz1Remux.js b/Community/Tdarr_Plugin_MC93_Migz1Remux.js index 4d0372351..91b7c5cde 100644 --- a/Community/Tdarr_Plugin_MC93_Migz1Remux.js +++ b/Community/Tdarr_Plugin_MC93_Migz1Remux.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz1Remux', Stage: 'Pre-processing', - Name: 'Migz-Remux container', + Name: 'Migz Remux Container', Type: 'Video', Operation: 'Transcode', Description: 'Files will be remuxed into either mkv or mp4. \n\n', diff --git a/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js b/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js index 94b33dca4..35e65ee41 100644 --- a/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js +++ b/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz2CleanTitle', Stage: 'Pre-processing', - Name: 'Migz-Clean title metadata', + Name: 'Migz Clean Title Metadata', Type: 'Video', Operation: 'Transcode', Description: 'This plugin removes title metadata from video/audio/subtitles.\n\n', diff --git a/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js b/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js index 5fb1cae04..4ddfb8ada 100644 --- a/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js +++ b/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz3CleanAudio', Stage: 'Pre-processing', - Name: 'Migz-Clean audio streams', + Name: 'Migz Clean Audio Streams', Type: 'Audio', Operation: 'Transcode', Description: 'This plugin keeps only specified language tracks & can tags tracks with an unknown language. \n\n', diff --git a/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js b/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js index a98b496a0..900698d9f 100644 --- a/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js +++ b/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz4CleanSubs', Stage: 'Pre-processing', - Name: 'Migz-Clean subtitle streams', + Name: 'Migz Clean Subtitle Streams', Type: 'Subtitle', Operation: 'Transcode', Description: 'This plugin keeps only specified language tracks & can tag tracks with an unknown language. \n\n', diff --git a/Community/Tdarr_Plugin_MC93_Migz5ConvertAudio.js b/Community/Tdarr_Plugin_MC93_Migz5ConvertAudio.js index 9397a718b..800cf684b 100644 --- a/Community/Tdarr_Plugin_MC93_Migz5ConvertAudio.js +++ b/Community/Tdarr_Plugin_MC93_Migz5ConvertAudio.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz5ConvertAudio', Stage: 'Pre-processing', - Name: 'Migz-Convert audio streams', + Name: 'Migz Convert Audio Streams', Type: 'Audio', Operation: 'Transcode', Description: 'This plugin can convert any 2.0 audio track/s to AAC and can create downmixed audio tracks. \n\n', diff --git a/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js b/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js index 2be21f165..88987c41b 100644 --- a/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js +++ b/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_Migz6OrderStreams', Stage: 'Pre-processing', - Name: 'Migz-Order Streams', + Name: 'Migz Order Streams', Type: 'Any', Operation: 'Transcode', Description: 'Orders streams into Video first, then Audio (2ch, 6ch, 8ch) and finally Subtitles. \n\n', diff --git a/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js b/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js index bfd0a5d75..bd0104038 100644 --- a/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js +++ b/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_MC93_MigzImageRemoval', Stage: 'Pre-processing', - Name: 'Migz-Remove image formats from file', + Name: 'Migz Remove Image Formats From File', Type: 'Video', Operation: 'Transcode', Description: 'Identify any unwanted image formats in the file and remove those streams. MJPEG, PNG & GIF \n\n', diff --git a/Community/Tdarr_Plugin_MC93_MigzPlex_Autoscan.js b/Community/Tdarr_Plugin_MC93_MigzPlex_Autoscan.js index 3b3f93b11..e8181957f 100644 --- a/Community/Tdarr_Plugin_MC93_MigzPlex_Autoscan.js +++ b/Community/Tdarr_Plugin_MC93_MigzPlex_Autoscan.js @@ -7,7 +7,7 @@ module.exports.dependencies = [ const details = () => ({ id: 'Tdarr_Plugin_MC93_MigzPlex_Autoscan', Stage: 'Post-processing', - Name: 'Send request for file to be scanned by plex_autoscan.', + Name: 'Send Request For File To Be Scanned By Plex_autoscan.', Type: 'Video', Operation: 'Transcode', Description: 'Send request for file to be scanned by plex_autoscan. https://github.com/l3uddz/plex_autoscan \n\n', diff --git a/Community/Tdarr_Plugin_MP01_MichPasCleanSubsAndAudioCodecs.js b/Community/Tdarr_Plugin_MP01_MichPasCleanSubsAndAudioCodecs.js index 560a88df1..dcdf7b930 100644 --- a/Community/Tdarr_Plugin_MP01_MichPasCleanSubsAndAudioCodecs.js +++ b/Community/Tdarr_Plugin_MP01_MichPasCleanSubsAndAudioCodecs.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_MP01_MichPasCleanSubsAndAudioCodecs", Stage: "Pre-processing", - Name: "MichPass-Remove subtitle and audio streams with certain codecs", + Name: "MichPass Remove Subtitle And Audio Streams With Certain Codecs", Type: "Any", Operation: 'Transcode', Description: `This plugin removed specified codecs from subtitle and audio tracks. Helpful to remove bitmap subtitles (pgs,vobsub) or audio codec (truehd), which can cause Plex to start transcoding. Based on Migz4 Plugin. Thanks \n\n`, diff --git a/Community/Tdarr_Plugin_O8O0dCTlb_Set_File_Permissions_For_UnRaid.js b/Community/Tdarr_Plugin_O8O0dCTlb_Set_File_Permissions_For_UnRaid.js index 141344130..b25ecf903 100644 --- a/Community/Tdarr_Plugin_O8O0dCTlb_Set_File_Permissions_For_UnRaid.js +++ b/Community/Tdarr_Plugin_O8O0dCTlb_Set_File_Permissions_For_UnRaid.js @@ -6,7 +6,7 @@ const details = () => { return { id: "Tdarr_Plugin_O8O0dCTlb_Set_File_Permissions_For_UnRaid", Stage: 'Pre-processing', - Name: "Set file permissions for UnRaid", + Name: "Set File Permissions For UnRaid", Type: "Video", Operation: "Transcode", Description: "Sets file permissions using chown nobody:users to prevent lock from root. Use at end of stack. ", diff --git a/Community/Tdarr_Plugin_SV6x_Smoove1FFMPEG_NVENC_H264.js b/Community/Tdarr_Plugin_SV6x_Smoove1FFMPEG_NVENC_H264.js index 2571214e6..83a2e877c 100644 --- a/Community/Tdarr_Plugin_SV6x_Smoove1FFMPEG_NVENC_H264.js +++ b/Community/Tdarr_Plugin_SV6x_Smoove1FFMPEG_NVENC_H264.js @@ -6,7 +6,7 @@ const details = () => ({ id: 'Tdarr_Plugin_SV6x_Smoove1FFMPEG_NVENC_H264', Stage: 'Pre-processing', // Preprocessing or Post-processing. Determines when the plugin will be executed. - Name: 'Smoove-Transcode to H264 using FFMPEG and NVENC ', + Name: 'Smoove-Transcode To H264 Using FFMPEG And NVENC', Type: 'Video', Operation: 'Transcode', Description: `Files not in H264 will be transcoded into H264 using Nvidia GPU with ffmpeg. diff --git a/Community/Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta.js b/Community/Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta.js index a6a33035d..94d9cf1d1 100644 --- a/Community/Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta.js +++ b/Community/Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta", Stage: "Pre-processing", - Name: "Drawmonster MP4 No title meta data ", + Name: "Drawmonster MP4 No Title Meta Data", Type: "Video", Operation: 'Transcode', Description: `[Contains built-in filter] This plugin removes metadata (if a title exists). The output container is mp4. \n\n`, diff --git a/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js b/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js index cd3bd61a1..333cb515c 100644 --- a/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js +++ b/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js @@ -4,7 +4,7 @@ const details = () => { id: "Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30", Stage: "Pre-processing", Name: - "HaveAGitGat HandBrake VeryFast1080p30, No title meta, no subs, 192Kb AAC stereo,MP4 ", + "HaveAGitGat HandBrake VeryFast1080p30, No Title Meta, No Subs, 192Kb AAC Stereo,MP4", Type: "Video", Operation: 'Transcode', Description: `[Contains built-in filter] This plugin transcodes into H264 using HandBrake's 'Very Fast 1080p30' preset if the file is not in H264 already. It removes subs, metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (any) doesn't exist. The output container is MP4. \n\n diff --git a/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js b/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js index 20fd46a74..cba361e1a 100644 --- a/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js +++ b/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js @@ -4,7 +4,7 @@ const details = () => { id: "Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30", Stage: "Pre-processing", Name: - "HaveAGitGat HandBrake Fast1080p30, No title meta, no subs, 192Kb AAC stereo,MP4 ", + "HaveAGitGat HandBrake Fast1080p30, No Title Meta, No Subs, 192Kb AAC Stereo,MP4", Type: "Video", Operation: 'Transcode', Description: `[Contains built-in filter] This plugin transcodes into H264 using HandBrake's 'Fast 1080p30' preset if the file is not in H264 already. It removes subs, metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (any) doesn't exist. The output container is MP4. \n\n diff --git a/Community/Tdarr_Plugin_a9he_New_file_size_check.js b/Community/Tdarr_Plugin_a9he_New_file_size_check.js index a03571336..bf5cc93e3 100644 --- a/Community/Tdarr_Plugin_a9he_New_file_size_check.js +++ b/Community/Tdarr_Plugin_a9he_New_file_size_check.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_a9he_New_file_size_check', Stage: 'Pre-processing', - Name: 'New file size check', + Name: 'New File Size Check', Type: 'Video', Operation: 'Transcode', Description: 'Give an error if new file is not within the specified upper and lower bound limits \n\n', diff --git a/Community/Tdarr_Plugin_a9hf_New_file_duration_check.js b/Community/Tdarr_Plugin_a9hf_New_file_duration_check.js index fcc9561a1..bcbf1f98d 100644 --- a/Community/Tdarr_Plugin_a9hf_New_file_duration_check.js +++ b/Community/Tdarr_Plugin_a9hf_New_file_duration_check.js @@ -3,7 +3,7 @@ const details = () => ({ id: 'Tdarr_Plugin_a9hf_New_file_duration_check', Stage: 'Pre-processing', - Name: 'New file duration check', + Name: 'New File Duration Check', Type: 'Video', Operation: 'Transcode', Description: `Give an error if new file is not within the specified upper and lower bound duration limits. diff --git a/Community/Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta.js b/Community/Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta.js index 0ab778587..11ff1c2d9 100644 --- a/Community/Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta.js +++ b/Community/Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta", Stage: "Pre-processing", - Name: "Nosirus h265, aac, no meta, subs kept", + Name: "Nosirus H265, AAC, No Meta, Subs Kept", Type: "Video", Operation: 'Transcode', Description: `[Contains built-in filter] If the file is not in h265 it will be trancoded into h265 with FFmpeg using the following command '-e x265 -q 22 --encoder-preset slow --all-audio --all-subtitles copy:aac -E fdk_aac -Q 4 -x aq-mode=3'. If no aac, aac track will be added. Subtitles are kept. Metadata is removed.\n\n diff --git a/Community/Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3.js b/Community/Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3.js index 9b9bce2ba..6ecdb5409 100644 --- a/Community/Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3.js +++ b/Community/Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3', Stage: 'Pre-processing', - Name: 'the1poet Video surround sound to ac3', + Name: 'The1poet Video Surround Sound To AC3', Type: 'Video', Operation: 'Transcode', Description: '[Contains built-in filter] If the file has surround sound tracks not in ac3,' diff --git a/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js b/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js index cef350fa0..5ebd93ef1 100644 --- a/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js +++ b/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js @@ -15,7 +15,7 @@ const details = () => ({ id: 'Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC', Stage: 'Pre-processing', - Name: 'Boosh-Transcode using QSV GPU & FFMPEG', + Name: 'Boosh-Transcode Using QSV GPU & FFMPEG', Type: 'Video', Operation: 'Transcode', Description: `==DETAILS== This is a QSV plugin. 8th+ gen INTEL QSV enabled CPUs are recommended. VAAPI is NOT used. diff --git a/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js b/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js index e878b466c..dcbbb01d7 100644 --- a/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js +++ b/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV", Stage: "Pre-processing", - Name: "Tiered FFMPEG NVENC settings depending on resolution", + Name: "Tiered FFMPEG NVENC Settings Depending On Resolution", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin uses different FFMPEG NVENC transcoding settings for 480p,576p,720p,1080p and 4KUHD. If files are not in hevc they will be transcoded. The output container is mkv. \n\n`, diff --git a/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js b/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js index 32cb0838a..1a3bf0c36 100644 --- a/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js +++ b/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js @@ -4,7 +4,7 @@ const details = () => { id: "Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4", Stage: "Pre-processing", Name: - "Dallas FFmpeg h264 mp4. Video: h264/mp4, Subs: Convert to mov_text or drop, Audio: aac", + "Dallas FFmpeg H264 MP4. Video: H264/MP4, Subs: Convert To:mov_text Or Drop, Audio:aac", Type: "Video", Operation: 'Transcode', Description: `This plugin transcodes into H264 with an MP4 container using the FFmpeg preset you select (slow,medium,fast,veryfast). It maintains all compatible subtitles and audio tracks. Drops picture tracks such as mjpeg\n\n`, diff --git a/Community/Tdarr_Plugin_drdd_standardise_all_in_one.js b/Community/Tdarr_Plugin_drdd_standardise_all_in_one.js index 45ee6c194..785af1afc 100644 --- a/Community/Tdarr_Plugin_drdd_standardise_all_in_one.js +++ b/Community/Tdarr_Plugin_drdd_standardise_all_in_one.js @@ -4,7 +4,7 @@ const details = () => { return { id: "Tdarr_Plugin_drdd_standardise_all_in_one", Stage: "Pre-processing", - Name: "DrDD H265 MKV AC3 audio subtitles [VAAPI & NVENC]", + Name: "DrDD H265 MKV AC3 Audio Subtitles [VAAPI & NVENC]", Stage: "Pre-processing", Type: "Video", Operation: "Transcode", diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js index 8a634f438..405614d78 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js @@ -5,7 +5,7 @@ const details = () => { return { id: "Tdarr_Plugin_e5c3_CnT_Add_Subtitles", Stage: "Pre-processing", - Name: "Add subtitles to MKV files", + Name: "Add Subtitles To MKV Files", Type: "Video", Operation: 'Transcode', Description: `This plugin will check for subtitles, they should be named according to the ISO 639-2 language code.\nA subtitle could look like this: eng.srt\n If there are subtitles found they will be added with FFMPEG, if there are no subs of that language found.\n On first run node module iso-639-2 will be installed in the documents folder.\n Created by @control#0405`, diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js index 7cf5ce4b7..792c78ac3 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js @@ -4,7 +4,7 @@ const details = () => { return { id: "Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio", Stage: "Pre-processing", - Name: "Keep Preffered Audio", + Name: "Keep Preferred Audio", Type: "Audio", Operation: 'Transcode', Description: diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js index 84764e2e7..07a602ce9 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js @@ -5,7 +5,7 @@ const details = () => { return { id: "Tdarr_Plugin_e5c3_CnT_Remove_Letterbox", Stage: "Pre-processing", - Name: "Remove letterbox", + Name: "Remove Letterbox", Type: "Video", Operation: "Transcode", Description: `Uses iiDrakeii's filter, and crops video files when letterboxing is detected.\nThis uses the FFMPEG NVENC transcoding(hw).\nIf a file is 4K it will be scaled down to 1080p.\nNow with user definable bitrates!(since 1.104 beta)\nCreated by @control#0405`, diff --git a/Community/Tdarr_Plugin_f4k1_aune_audio_to_flac.js b/Community/Tdarr_Plugin_f4k1_aune_audio_to_flac.js index 05c42bc44..0a4504932 100644 --- a/Community/Tdarr_Plugin_f4k1_aune_audio_to_flac.js +++ b/Community/Tdarr_Plugin_f4k1_aune_audio_to_flac.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_f4k1_aune_audio_to_flac', Stage: 'Pre-processing', - Name: 'Aune - Audio to FLAC', + Name: 'Aune - Audio To FLAC', Type: 'Audio', Operation: 'Transcode', Description: 'This plugin transcodes different audio codecs to FLAC. ' diff --git a/Community/Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs.js b/Community/Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs.js index 2b1b946e5..79ae74410 100644 --- a/Community/Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs.js +++ b/Community/Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs", Stage: "Pre-processing", - Name: "Sparticus 4K +AC3 No Subs Original container", + Name: "Sparticus 4K +AC3 No Subs Original Container", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin for 4K video removes subs. If no AC3 track exists, it adds one (max 5.1 channels). If only an AC3 commentary track exists, it adds a new AC3 main track (max 5.1 channels). The output container is the same as the original file. \n\n`, diff --git a/Community/Tdarr_Plugin_goof1_URL_Plex_Refresh.js b/Community/Tdarr_Plugin_goof1_URL_Plex_Refresh.js index eb1e0facc..3d78000bc 100644 --- a/Community/Tdarr_Plugin_goof1_URL_Plex_Refresh.js +++ b/Community/Tdarr_Plugin_goof1_URL_Plex_Refresh.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_goof1_URL_Plex_Refresh', Stage: 'Post-processing', - Name: 'Refresh Plex via URL', + Name: 'Refresh Plex Via URL', Type: 'Video', Operation: 'Transcode', Description: `Refreshes folder containing the current file in Plex so changes are picked up properly diff --git a/Community/Tdarr_Plugin_henk_Add_Specific_Audio_Codec.js b/Community/Tdarr_Plugin_henk_Add_Specific_Audio_Codec.js index 06e8eafb8..63ef37fe2 100644 --- a/Community/Tdarr_Plugin_henk_Add_Specific_Audio_Codec.js +++ b/Community/Tdarr_Plugin_henk_Add_Specific_Audio_Codec.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_henk_Add_Specific_Audio_Codec', Stage: 'Pre-processing', - Name: '[MKV ONLY] Transcode given codec to other given codec and keep original', + Name: '[MKV ONLY] Transcode Given Codec To Other Given Codec And Keep Original', Type: 'Audio', Operation: 'Transcode', Description: 'Re-encodes all audio tracks in a given codec to another given codec and keeps original.', diff --git a/Community/Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng.js b/Community/Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng.js index e88bdcea5..13bcaf70b 100644 --- a/Community/Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng.js +++ b/Community/Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng.js @@ -4,7 +4,7 @@ module.exports.dependencies = ['axios@0.27.2', '@cospired/i18n-iso-languages']; const details = () => ({ id: 'Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng', Stage: 'Pre-processing', - Name: 'Remove all langs except native and English', + Name: 'Remove All Langs Except Native And English', Type: 'Audio', Operation: 'Transcode', Description: `This plugin will remove all language audio tracks except the 'native' diff --git a/Community/Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle.js b/Community/Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle.js index 235117c45..d0036f0a2 100644 --- a/Community/Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle.js +++ b/Community/Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle", Stage: "Pre-processing", - Name: "Drawmonster MP4 Stereo AAC, No Subs, No title meta data ", + Name: "Drawmonster MP4 Stereo AAC, No Subs, No Title Meta Data", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin removes subs, metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (English or any) doesn't exist. The output container is mp4. \n\n diff --git a/Community/Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle.js b/Community/Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle.js index 3954b3ee7..68c9b3259 100644 --- a/Community/Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle.js +++ b/Community/Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle", Stage: "Pre-processing", - Name: "GilbN MP4 Stereo AAC, No title meta data ", + Name: "GilbN MP4 Stereo AAC, No Title Meta Data", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin removes metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (any) doesn't exist. The output container is mp4. \n\n diff --git a/Community/Tdarr_Plugin_jeons001_Downmix_to_stereo_and_apply_DRC.js b/Community/Tdarr_Plugin_jeons001_Downmix_to_stereo_and_apply_DRC.js index 6470e3707..eb6c86552 100644 --- a/Community/Tdarr_Plugin_jeons001_Downmix_to_stereo_and_apply_DRC.js +++ b/Community/Tdarr_Plugin_jeons001_Downmix_to_stereo_and_apply_DRC.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_jeons001_Downmix_to_stereo_and_apply_DRC', Stage: 'Pre-processing', - Name: 'Downmix & Dynamic range compression', + Name: 'Downmix & Dynamic Range Compression', Type: 'Audio', Operation: 'Transcode', Description: 'Downmixes surround to AAC stereo AND applies dynamic range compression.' diff --git a/Community/Tdarr_Plugin_lmg1_Reorder_Streams.js b/Community/Tdarr_Plugin_lmg1_Reorder_Streams.js index 06a7ecee6..1db872266 100644 --- a/Community/Tdarr_Plugin_lmg1_Reorder_Streams.js +++ b/Community/Tdarr_Plugin_lmg1_Reorder_Streams.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_lmg1_Reorder_Streams", Stage: "Pre-processing", - Name: "Tdarr_Plugin_lmg1_Reorder_Streams ", + Name: "Lmg1 Reorder Streams", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin will move the video stream to the front so Tdarr will recognize the codec correctly.\n\n`, diff --git a/Community/Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta.js b/Community/Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta.js index 1f55145f8..1d6866287 100644 --- a/Community/Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta.js +++ b/Community/Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta", Stage: "Pre-processing", - Name: "Drawmonster No title meta data ", + Name: "Drawmonster No Title Meta Data", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin removes metadata (if a title exists). The output container is the same as the original. \n\n diff --git a/Community/Tdarr_Plugin_r002_rootuser_FFMPEG_HQ_HEVC_MKV_Animation.js b/Community/Tdarr_Plugin_r002_rootuser_FFMPEG_HQ_HEVC_MKV_Animation.js index a9653b4ae..625692320 100644 --- a/Community/Tdarr_Plugin_r002_rootuser_FFMPEG_HQ_HEVC_MKV_Animation.js +++ b/Community/Tdarr_Plugin_r002_rootuser_FFMPEG_HQ_HEVC_MKV_Animation.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_r002_rootuser_FFMPEG_HQ_HEVC_MKV_Animation", Stage: "Pre-processing", - Name: "FFMPEG HQ 10-bit HEVC MKV for Animation", + Name: "FFMPEG HQ 10-bit HEVC MKV For Animation", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] High Quality FFMPEG transcoding settings for Animation. Converts all audio to AAC 512K. Preserves track names, metadata and attachments/fonts. Proper use of x265-params. CRF 18. Preset medium. 10-Bit Video encoding. Skips h.265 encoded videos. The output container is mkv. \n\n`, diff --git a/Community/Tdarr_Plugin_rr01_drpeppershaker_extract_subs_to_SRT.js b/Community/Tdarr_Plugin_rr01_drpeppershaker_extract_subs_to_SRT.js index b8b65eefa..d6869df6c 100644 --- a/Community/Tdarr_Plugin_rr01_drpeppershaker_extract_subs_to_SRT.js +++ b/Community/Tdarr_Plugin_rr01_drpeppershaker_extract_subs_to_SRT.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_rr01_drpeppershaker_extract_subs_to_SRT', Stage: 'Pre-processing', - Name: 'drpeppershaker Extract embedded subtitles and optionally remove them', + Name: 'Drpeppershaker Extract Embedded Subtitles And Optionally Remove Them', Type: 'Video', Operation: 'Transcode', Description: 'This plugin extracts embedded subs in one pass inside Tdarr and will optionally remove them. \n\n ' diff --git a/Community/Tdarr_Plugin_s7x8_winsome_h265.js b/Community/Tdarr_Plugin_s7x8_winsome_h265.js index 2c1108a2d..105134512 100644 --- a/Community/Tdarr_Plugin_s7x8_winsome_h265.js +++ b/Community/Tdarr_Plugin_s7x8_winsome_h265.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_s7x8_winsome_h265", Stage: "Pre-processing", - Name: "Winsome H265 ", + Name: "Winsome H265", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin transcodes all videos to h265 (if not in h265 already) and remuxes if not in mkv. If the English language track is not in AC3,EAC3 or DTS then an AC3 track is added.\n\n diff --git a/Community/Tdarr_Plugin_s7x9_winsome_h265_10bit.js b/Community/Tdarr_Plugin_s7x9_winsome_h265_10bit.js index fd243f699..b0b639d81 100644 --- a/Community/Tdarr_Plugin_s7x9_winsome_h265_10bit.js +++ b/Community/Tdarr_Plugin_s7x9_winsome_h265_10bit.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_s7x9_winsome_h265_10bit", Stage: "Pre-processing", - Name: "Winsome H265 10 bit ", + Name: "Winsome H265 10 Bit", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin transcodes all videos to h265 10 bit (if not in h265 already) and remuxes if not in mkv. If the English language track is not in AC3,EAC3 or DTS then an AC3 track is added.\n\n diff --git a/Community/Tdarr_Plugin_scha_rename_based_on_codec_schadi.js b/Community/Tdarr_Plugin_scha_rename_based_on_codec_schadi.js index 48537d3fd..03551778c 100644 --- a/Community/Tdarr_Plugin_scha_rename_based_on_codec_schadi.js +++ b/Community/Tdarr_Plugin_scha_rename_based_on_codec_schadi.js @@ -4,7 +4,7 @@ const details = () => ({ id: 'Tdarr_Plugin_scha_rename_based_on_codec_schadi', Stage: 'Post-processing', - Name: 'Rename based on codec Video and Audio', + Name: 'Rename Based On Codec Video And Audio', Type: 'Video', Operation: 'Transcode', Description: ` diff --git a/Community/Tdarr_Plugin_sdd3_Remove_Commentary_Tracks.js b/Community/Tdarr_Plugin_sdd3_Remove_Commentary_Tracks.js index 7c0640f2c..4eee3a8bd 100644 --- a/Community/Tdarr_Plugin_sdd3_Remove_Commentary_Tracks.js +++ b/Community/Tdarr_Plugin_sdd3_Remove_Commentary_Tracks.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_sdd3_Remove_Commentary_Tracks", Stage: "Pre-processing", - Name: "Remove video commentary tracks", + Name: "Remove Video Commentary Tracks", Type: "Video", Operation: 'Transcode', Description: `[Contains built-in filter] If commentary tracks are detected, they will be removed. \n\n`, diff --git a/Community/Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio.js b/Community/Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio.js index b8778d266..9e231f6b3 100644 --- a/Community/Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio.js +++ b/Community/Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio", Stage: "Pre-processing", - Name: "Remove Non English Audio ", + Name: "Remove Non English Audio", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin removes audio tracks which are not English or are not undefined. It ensures at least 1 audio track is left in any language. \n\n diff --git a/Community/Tdarr_Plugin_tsld_filter_modified_date.js b/Community/Tdarr_Plugin_tsld_filter_modified_date.js index 945819702..19e1c05c4 100644 --- a/Community/Tdarr_Plugin_tsld_filter_modified_date.js +++ b/Community/Tdarr_Plugin_tsld_filter_modified_date.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_tsld_filter_modified_date', Stage: 'Pre-processing', - Name: 'Filter modified date', + Name: 'Filter Modified Date', Type: 'Video', Operation: 'Filter', Description: 'This plugin prevents processing files older than 30 days \n\n', diff --git a/Community/Tdarr_Plugin_vdka_Remove_DataStreams.js b/Community/Tdarr_Plugin_vdka_Remove_DataStreams.js index 53505d504..0ee621e1f 100644 --- a/Community/Tdarr_Plugin_vdka_Remove_DataStreams.js +++ b/Community/Tdarr_Plugin_vdka_Remove_DataStreams.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_vdka_Remove_DataStreams", Stage: "Pre-processing", - Name: "Remove Data Streams ", + Name: "Remove Data Streams", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin removes data streams if detected. The output container is mkv. Helps with issues like bin_data making files impossible to process. \n\n`, diff --git a/Community/Tdarr_Plugin_x7ab_Remove_Subs.js b/Community/Tdarr_Plugin_x7ab_Remove_Subs.js index 3fa5aa991..b7b1510a1 100644 --- a/Community/Tdarr_Plugin_x7ab_Remove_Subs.js +++ b/Community/Tdarr_Plugin_x7ab_Remove_Subs.js @@ -3,7 +3,7 @@ const details = () => { return { id: "Tdarr_Plugin_x7ab_Remove_Subs", Stage: "Pre-processing", - Name: "Remove subtitles ", + Name: "Remove Subtitles", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] This plugin removes subtitles if detected. The output container is the same as the original. \n\n`, diff --git a/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js b/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js index 17ff3266f..e30420ea1 100644 --- a/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js +++ b/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_x7ac_Remove_Closed_Captions', Stage: 'Pre-processing', - Name: 'Remove burned closed captions', + Name: 'Remove Burned Closed Captions', Type: 'Video', Operation: 'Transcode', Description: diff --git a/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js b/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js index 5b859ddaa..19d05a0e1 100644 --- a/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js +++ b/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium', Stage: 'Pre-processing', - Name: 'TheRealShadoh FFmpeg Subs Medium, video MP4, audio AAC, keep subs. ', + Name: 'TheRealShadoh FFmpeg Subs Medium, Video MP4, Audio AAC, Keep Subs', Type: 'Video', Operation: 'Transcode', Description: '[Contains built-in filter] This plugin transcodes into H264 using FFmpeg\'s ' diff --git a/Community/Tdarr_Plugin_z18s_rename_files_based_on_codec.js b/Community/Tdarr_Plugin_z18s_rename_files_based_on_codec.js index 5d159172f..0a4a87c89 100644 --- a/Community/Tdarr_Plugin_z18s_rename_files_based_on_codec.js +++ b/Community/Tdarr_Plugin_z18s_rename_files_based_on_codec.js @@ -5,7 +5,7 @@ const details = () => { return { id: "Tdarr_Plugin_z18s_rename_files_based_on_codec", Stage: "Post-processing", - Name: "Rename based on codec", + Name: "Rename Based On Codec", Type: "Video", Operation: "Transcode", Description: `[Contains built-in filter] If the filename contains '264' or '265', this plugin renames 264 files to 265 or vice versa depending on codec. \n\n`, diff --git a/Community/Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution.js b/Community/Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution.js index ece12d97e..c94be4550 100644 --- a/Community/Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution.js +++ b/Community/Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution', Stage: 'Post-processing', - Name: 'Rename based on codec and resolution', + Name: 'Rename Based On Codec And Resolution', Type: 'Video', Operation: 'Transcode', Description: '[Contains built-in filter]This plugin renames files depending on codec and resolution\n\n', diff --git a/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js b/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js index 0a84a770e..680e7c27c 100644 --- a/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js +++ b/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast', Stage: 'Pre-processing', - Name: 'TheRealShadoh FFmpeg Subs Fast, video MP4, audio AAC, keep subs. ', + Name: 'TheRealShadoh FFmpeg Subs Fast, Video MP4, Audio AAC, Keep Subs', Type: 'Video', Operation: 'Transcode', Description: '[Contains built-in filter] This plugin transcodes into H264 using ' diff --git a/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js b/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js index 52c58acee..8db9823b6 100644 --- a/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js +++ b/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow', Stage: 'Pre-processing', - Name: 'TheRealShadoh FFmpeg Subs Slow, video MP4, audio AAC, keep subs. ', + Name: 'TheRealShadoh FFmpeg Subs Slow, Video MP4, Audio AAC, Keep Subs', Type: 'Video', Operation: 'Transcode', Description: '[Contains built-in filter] This plugin transcodes into H264 using FFmpeg\'s \'Slow\' preset' diff --git a/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast.js b/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast.js index 7b7623cd3..474aef892 100644 --- a/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast.js +++ b/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast.js @@ -2,7 +2,7 @@ const details = () => ({ id: 'Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast', Stage: 'Pre-processing', Name: - 'TheRealShadoh FFmpeg Subs VeryFast, video MP4, audio AAC, keep subs. ', + 'TheRealShadoh FFmpeg Subs VeryFast, Video MP4, Audio AAC, Keep Subs', Type: 'Video', Operation: 'Transcode', Description: '[Contains built-in filter] This plugin transcodes into H264 using FFmpeg\'s \'VeryFast\' preset ' diff --git a/Community/Tdarr_Plugin_z80t_keep_original_date.js b/Community/Tdarr_Plugin_z80t_keep_original_date.js index e7000b2ac..c4380f8dd 100644 --- a/Community/Tdarr_Plugin_z80t_keep_original_date.js +++ b/Community/Tdarr_Plugin_z80t_keep_original_date.js @@ -6,7 +6,7 @@ module.exports.dependencies = [ const details = () => ({ id: 'Tdarr_Plugin_z80t_keep_original_date', Stage: 'Post-processing', - Name: 'Keep original file dates and times after transcoding', + Name: 'Keep Original File Dates And Times After Transcoding', Type: 'Video', Operation: 'Transcode', Description: 'This plugin copies the original file dates and times to the transcoded file \n\n', diff --git a/FlowPlugins/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.js index 7e44bf93e..6b338ca8b 100644 --- a/FlowPlugins/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.js @@ -4,7 +4,7 @@ exports.plugin = exports.details = void 0; /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Check Audio Codec', - description: 'Check if a file has a specific audio codec', + description: 'Check if a file has a specific audio codec.', style: { borderColor: 'orange', }, diff --git a/FlowPlugins/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.js index bc0cf7f39..a2d331a42 100644 --- a/FlowPlugins/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.js @@ -128,6 +128,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 1: @@ -181,6 +182,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli2.runCli()]; case 2: diff --git a/FlowPlugins/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.js index a46fbba15..885faa744 100644 --- a/FlowPlugins/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.js @@ -51,7 +51,7 @@ var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Basic Video or Audio Settings', - description: "Basic Video or Audio settings designed to replicate\n the Basic Video or Basic Audio settings in the library settings\n ", + description: "Basic Video or Audio settings designed to replicate\n the Basic Video or Basic Audio settings in the library settings.\n ", style: { borderColor: 'green', }, @@ -383,6 +383,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 1: diff --git a/FlowPlugins/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.js index d9491a589..9610ea661 100644 --- a/FlowPlugins/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/classic/runClassicTranscodePlugin/1.0.0/index.js @@ -217,6 +217,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 2: diff --git a/FlowPlugins/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.js new file mode 100644 index 000000000..874821983 --- /dev/null +++ b/FlowPlugins/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.js @@ -0,0 +1,245 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.plugin = exports.details = void 0; +var cliUtils_1 = require("../../../../FlowHelpers/1.0.0/cliUtils"); +var classicPlugins_1 = require("../../../../FlowHelpers/1.0.0/classicPlugins"); +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +var details = function () { return ({ + name: 'Run Classic Transcode Plugin', + description: 'Run one of Tdarr\'s classic plugins that has Operation: Transcode', + style: { + borderColor: 'green', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.11.01', + sidebarPosition: -1, + icon: '', + inputs: [ + { + label: 'Plugin Source ID', + name: 'pluginSourceId', + type: 'string', + defaultValue: 'Community:Tdarr_Plugin_MC93_Migz1FFMPEG', + inputUI: { + type: 'dropdown', + options: [], + }, + tooltip: 'Specify the classic plugin ID', + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Processing was done by the classic plugin', + }, + { + number: 2, + tooltip: 'Processing was not done by the classic plugin', + }, + ], +}); }; +exports.details = details; +var replaceContainer = function (filePath, container) { + var parts = filePath.split('.'); + parts[parts.length - 1] = container.split('.').join(''); + return parts.join('.'); +}; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function () { + var lib, outcome, result, absolutePath, cacheFilePath, cliPath_1, customArgs, isCustomConfig, presetSplit, workerCommand, cliPath, cli, res; + var _a, _b, _c; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + return [4 /*yield*/, (0, classicPlugins_1.runClassicPlugin)(args, 'transcode')]; + case 1: + outcome = _d.sent(); + result = outcome.result, absolutePath = outcome.absolutePath; + cacheFilePath = outcome.cacheFilePath; + args.jobLog(JSON.stringify(result, null, 2)); + if (!result) { + args.jobLog('No result from classic plugin. Continuing to next flow plugin.'); + return [2 /*return*/, { + outputFileObj: args.inputFileObj, + outputNumber: 2, + variables: args.variables, + }]; + } + // --- Backwards compatibility------------ + if (result.handBrakeMode) { + result.handbrakeMode = result.handBrakeMode; + } + if (result.FFmpegMode) { + result.ffmpegMode = result.FFmpegMode; + } + //---------------------------------------- + if (result.ffmpegMode) { + result.cliToUse = 'ffmpeg'; + } + else if (result.handbrakeMode) { + result.cliToUse = 'handbrake'; + } + else if (typeof ((_a = result === null || result === void 0 ? void 0 : result.custom) === null || _a === void 0 ? void 0 : _a.cliPath) === 'string') { + cliPath_1 = result.custom.cliPath; + if (cliPath_1.toLowerCase().includes('ffmpeg')) { + result.cliToUse = 'ffmpeg'; + } + else if (cliPath_1.toLowerCase().includes('handbrake')) { + result.cliToUse = 'handbrake'; + } + else if (cliPath_1.toLowerCase().includes('editready')) { + result.cliToUse = 'editready'; + } + else if (cliPath_1.toLowerCase().includes('av1an')) { + result.cliToUse = 'av1an'; + } + } + result.workerLog = result.transcodeSettingsLog; + args.jobLog(JSON.stringify(result, null, 2)); + if (result.error) { + throw new Error("Plugin ".concat(absolutePath, " failed: ").concat(result.error)); + } + if (result.processFile !== true) { + args.jobLog('Classic plugin does not need to process file. Continuing to next flow plugin.'); + return [2 /*return*/, { + outputFileObj: args.inputFileObj, + outputNumber: 2, + variables: args.variables, + }]; + } + customArgs = (_b = result === null || result === void 0 ? void 0 : result.custom) === null || _b === void 0 ? void 0 : _b.args; + isCustomConfig = (Array.isArray(customArgs) && customArgs.length > 0) + || (typeof customArgs === 'string' + // @ts-expect-error length + && customArgs.length + > 0); + if (!isCustomConfig) { + cacheFilePath = replaceContainer(cacheFilePath, result.container); + } + else { + // @ts-expect-error type + cacheFilePath = result.custom.outputPath; + } + if (result.preset.includes('')) { + presetSplit = result.preset.split(''); + } + else { + presetSplit = result.preset.split(','); + } + workerCommand = []; + cliPath = ''; + if (isCustomConfig) { + // @ts-expect-error cliPath + cliPath = (_c = result === null || result === void 0 ? void 0 : result.custom) === null || _c === void 0 ? void 0 : _c.cliPath; + if (Array.isArray(customArgs)) { + workerCommand = customArgs; + } + else { + workerCommand = __spreadArray([], args.deps.parseArgsStringToArgv(customArgs, '', ''), true); + } + } + else { + // working on windows with '` and spaces + // working on unix with ' + switch (true) { + case result.cliToUse === 'handbrake': + workerCommand = __spreadArray([ + '-i', + "".concat(args.inputFileObj._id), + '-o', + "".concat(cacheFilePath) + ], args.deps.parseArgsStringToArgv(result.preset, '', ''), true); + cliPath = "".concat(args.handbrakePath); + break; + case result.cliToUse === 'ffmpeg': + workerCommand = __spreadArray(__spreadArray(__spreadArray(__spreadArray([], args.deps.parseArgsStringToArgv(presetSplit[0], '', ''), true), [ + '-i', + "".concat(args.inputFileObj._id) + ], false), args.deps.parseArgsStringToArgv(presetSplit[1], '', ''), true), [ + "".concat(cacheFilePath), + ], false); + cliPath = "".concat(args.ffmpegPath); + break; + default: + } + } + cli = new cliUtils_1.CLI({ + cli: cliPath, + spawnArgs: workerCommand, + spawnOpts: {}, + jobLog: args.jobLog, + outputFilePath: cacheFilePath, + inputFileObj: args.inputFileObj, + logFullCliOutput: args.logFullCliOutput, + updateWorker: args.updateWorker, + args: args, + }); + return [4 /*yield*/, cli.runCli()]; + case 2: + res = _d.sent(); + if (res.cliExitCode !== 0) { + args.jobLog("Running ".concat(cliPath, " failed")); + throw new Error("Running ".concat(cliPath, " failed")); + } + args.logOutcome('tSuc'); + return [2 /*return*/, { + outputFileObj: { + _id: cacheFilePath, + }, + outputNumber: 1, + variables: args.variables, + }]; + } + }); +}); }; +exports.plugin = plugin; diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.js index e04d4bc11..52954fc8c 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.js @@ -1,6 +1,11 @@ "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var os_1 = __importDefault(require("os")); +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: '10 Bit Video', @@ -28,11 +33,12 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); for (var i = 0; i < args.variables.ffmpegCommand.streams.length; i += 1) { var stream = args.variables.ffmpegCommand.streams[i]; if (stream.codec_type === 'video') { stream.outputArgs.push('-profile:v:{outputTypeIndex}', 'main10'); - if (stream.outputArgs.some(function (row) { return row.includes('qsv'); })) { + if (stream.outputArgs.some(function (row) { return row.includes('qsv'); }) && os_1.default.platform() !== 'win32') { stream.outputArgs.push('-vf', 'scale_qsv=format=p010le'); } else { diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.js index 20439f7e3..7a713c6ae 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Crop Black Bars', @@ -29,6 +30,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); return { outputFileObj: args.inputFileObj, outputNumber: 1, diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.js index 4bb3829ef..050df9141 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Custom Arguments', @@ -50,6 +51,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); var inputArguments = String(args.inputs.inputArguments); var outputArguments = String(args.inputs.outputArguments); if (inputArguments) { diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.js index 0acee6a7f..2d2deb81d 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.js @@ -2,6 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Ensure Audio Stream', @@ -224,6 +225,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); var audioEncoder = String(args.inputs.audioEncoder); var langTag = String(args.inputs.language).toLowerCase(); var wantedChannelCount = Number(args.inputs.channels); diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.js index 73d3ebb6f..f48dee6f9 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.js @@ -48,6 +48,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; var cliUtils_1 = require("../../../../FlowHelpers/1.0.0/cliUtils"); var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Execute', @@ -103,6 +104,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); cliArgs = []; cliArgs.push('-y'); cliArgs.push('-i'); @@ -183,6 +185,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 1: @@ -192,6 +195,8 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function throw new Error('FFmpeg failed'); } args.logOutcome('tSuc'); + // eslint-disable-next-line no-param-reassign + args.variables.ffmpegCommand.init = false; return [2 /*return*/, { outputFileObj: { _id: outputFilePath, diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.js index 6cda6f2b0..cdb7db056 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'HDR to SDR', @@ -28,6 +29,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); args.variables.ffmpegCommand.streams.forEach(function (stream) { if (stream.codec_type === 'video') { stream.outputArgs.push('-vf', 'zscale=t=linear:npl=100,format=yuv420p'); diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.js index 26fcf9ca4..61a8eda08 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Normalize Audio', @@ -29,6 +30,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); return { outputFileObj: args.inputFileObj, outputNumber: 1, diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.js index dea876d78..9161089bc 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.js @@ -2,6 +2,7 @@ /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint-disable no-param-reassign */ var details = function () { return ({ name: 'Remove Data Streams', @@ -29,6 +30,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); args.variables.ffmpegCommand.streams.forEach(function (stream) { if (stream.codec_type === 'data') { stream.removed = true; diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.js index b44d2eb8f..a4bfac061 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Remove Stream By Property', @@ -63,8 +64,9 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); var propertyToCheck = String(args.inputs.propertyToCheck).trim(); - var valuesToRemove = String(args.inputs.valuesToRemove).trim().split(','); + var valuesToRemove = String(args.inputs.valuesToRemove).trim().split(',').map(function (item) { return item.trim(); }); var condition = String(args.inputs.condition); args.variables.ffmpegCommand.streams.forEach(function (stream) { var _a; diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.js index 49b4a0b9f..ea722d3a8 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.js @@ -2,6 +2,7 @@ /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint-disable no-param-reassign */ var details = function () { return ({ name: 'Remove Subtitles', @@ -29,6 +30,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); args.variables.ffmpegCommand.streams.forEach(function (stream) { if (stream.codec_type === 'subtitle') { stream.removed = true; diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.js index 49d916522..af48a2d19 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.js @@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint-disable no-param-reassign */ var details = function () { return ({ name: 'Set Container', @@ -55,6 +56,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); var newContainer = String(args.inputs.container); var forceConform = args.inputs.forceConform; if ((0, fileUtils_1.getContainer)(args.inputFileObj._id) !== newContainer) { @@ -77,12 +79,15 @@ var plugin = function (args) { } } if (newContainer === 'mp4') { - if ([ - 'hdmv_pgs_subtitle', - 'eia_608', - 'timed_id3', - 'subrip', - ].includes(codecName)) { + if (codecType === 'attachment' + || [ + 'hdmv_pgs_subtitle', + 'eia_608', + 'timed_id3', + 'subrip', + 'ass', + 'ssa', + ].includes(codecName)) { stream.removed = true; } } @@ -92,6 +97,16 @@ var plugin = function (args) { } } } + // handle genpts if coming from odd container + var container = args.inputFileObj.container.toLowerCase(); + if ([ + 'ts', + 'avi', + 'mpg', + 'mpeg', + ].includes(container)) { + args.variables.ffmpegCommand.overallOuputArguments.push('-fflags', '+genpts'); + } } return { outputFileObj: args.inputFileObj, diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.js index e96f23dd3..fdb27ac62 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Set Video Framerate', @@ -40,6 +41,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); var desiredFrameRate = Number(args.inputs.framerate); args.jobLog("Desired framerate: ".concat(desiredFrameRate)); args.variables.ffmpegCommand.streams.forEach(function (stream) { diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.js index 88e8ca6f5..5e63ad259 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Set Video Resolution', @@ -65,6 +66,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); for (var i = 0; i < args.variables.ffmpegCommand.streams.length; i += 1) { var stream = args.variables.ffmpegCommand.streams[i]; if (stream.codec_type === 'video') { diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.js index 4ba49f96b..7ccb3530b 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.js @@ -2,6 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Set Video Bitrate', @@ -115,6 +116,7 @@ var plugin = function (args) { var lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); var useInputBitrate = args.inputs.useInputBitrate; var targetBitratePercent = String(args.inputs.targetBitratePercent); var fallbackBitrate = String(args.inputs.fallbackBitrate); diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.js index 61427d065..34f90f3e1 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.js @@ -39,6 +39,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; var hardwareUtils_1 = require("../../../../FlowHelpers/1.0.0/hardwareUtils"); +var flowUtils_1 = require("../../../../FlowHelpers/1.0.0/interfaces/flowUtils"); /* eslint-disable no-param-reassign */ var details = function () { return ({ name: 'Set Video Encoder', @@ -70,6 +71,16 @@ var details = function () { return ({ }, tooltip: 'Specify codec of the output file', }, + { + label: 'Enable FFmpeg Preset', + name: 'ffmpegPresetEnabled', + type: 'boolean', + defaultValue: 'true', + inputUI: { + type: 'switch', + }, + tooltip: 'Specify whether to use an FFmpeg preset', + }, { label: 'FFmpeg Preset', name: 'ffmpegPreset', @@ -88,9 +99,34 @@ var details = function () { return ({ 'superfast', 'ultrafast', ], + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'ffmpegPresetEnabled', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, }, tooltip: 'Specify ffmpeg preset', }, + { + label: 'Enable FFmpeg Quality', + name: 'ffmpegQualityEnabled', + type: 'boolean', + defaultValue: 'true', + inputUI: { + type: 'switch', + }, + tooltip: 'Specify whether to set crf (or qp for GPU encoding)', + }, { label: 'FFmpeg Quality', name: 'ffmpegQuality', @@ -98,8 +134,23 @@ var details = function () { return ({ defaultValue: '25', inputUI: { type: 'text', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'ffmpegQualityEnabled', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, }, - tooltip: 'Specify ffmpeg quality', + tooltip: 'Specify ffmpeg quality crf (or qp for GPU encoding)', }, { label: 'Hardware Encoding', @@ -159,24 +210,26 @@ var details = function () { return ({ exports.details = details; // eslint-disable-next-line @typescript-eslint/no-unused-vars var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function () { - var lib, hardwareDecoding, hardwareType, i, stream, targetCodec, ffmpegPreset, ffmpegQuality, forceEncoding, hardwarEncoding, encoderProperties; - var _a, _b; - return __generator(this, function (_c) { - switch (_c.label) { + var lib, hardwareDecoding, hardwareType, i, stream, targetCodec, _a, ffmpegPresetEnabled, ffmpegQualityEnabled, ffmpegPreset, ffmpegQuality, forceEncoding, hardwarEncoding, encoderProperties; + var _b, _c; + return __generator(this, function (_d) { + switch (_d.label) { case 0: lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + (0, flowUtils_1.checkFfmpegCommandInit)(args); hardwareDecoding = args.inputs.hardwareDecoding === true; hardwareType = String(args.inputs.hardwareType); args.variables.ffmpegCommand.hardwareDecoding = hardwareDecoding; i = 0; - _c.label = 1; + _d.label = 1; case 1: if (!(i < args.variables.ffmpegCommand.streams.length)) return [3 /*break*/, 4]; stream = args.variables.ffmpegCommand.streams[i]; if (!(stream.codec_type === 'video')) return [3 /*break*/, 3]; targetCodec = String(args.inputs.outputCodec); + _a = args.inputs, ffmpegPresetEnabled = _a.ffmpegPresetEnabled, ffmpegQualityEnabled = _a.ffmpegQualityEnabled; ffmpegPreset = String(args.inputs.ffmpegPreset); ffmpegQuality = String(args.inputs.ffmpegQuality); forceEncoding = args.inputs.forceEncoding === true; @@ -191,24 +244,28 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function args: args, })]; case 2: - encoderProperties = _c.sent(); + encoderProperties = _d.sent(); stream.outputArgs.push('-c:{outputIndex}', encoderProperties.encoder); - if (encoderProperties.isGpu) { - stream.outputArgs.push('-qp', ffmpegQuality); - } - else { - stream.outputArgs.push('-crf', ffmpegQuality); + if (ffmpegQualityEnabled) { + if (encoderProperties.isGpu) { + stream.outputArgs.push('-qp', ffmpegQuality); + } + else { + stream.outputArgs.push('-crf', ffmpegQuality); + } } - if (targetCodec !== 'av1' && ffmpegPreset) { - stream.outputArgs.push('-preset', ffmpegPreset); + if (ffmpegPresetEnabled) { + if (targetCodec !== 'av1' && ffmpegPreset) { + stream.outputArgs.push('-preset', ffmpegPreset); + } } if (hardwareDecoding) { - (_a = stream.inputArgs).push.apply(_a, encoderProperties.inputArgs); + (_b = stream.inputArgs).push.apply(_b, encoderProperties.inputArgs); } if (encoderProperties.outputArgs) { - (_b = stream.outputArgs).push.apply(_b, encoderProperties.outputArgs); + (_c = stream.outputArgs).push.apply(_c, encoderProperties.outputArgs); } - _c.label = 3; + _d.label = 3; case 3: i += 1; return [3 /*break*/, 1]; diff --git a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.js index d00a4acd8..e9f79cf31 100644 --- a/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.js @@ -44,6 +44,7 @@ var plugin = function (args) { args.inputs = lib.loadDefaultValues(args.inputs, details); var container = (0, fileUtils_1.getContainer)(args.inputFileObj._id); var ffmpegCommand = { + init: true, inputFiles: [], streams: JSON.parse(JSON.stringify(args.inputFileObj.ffProbeData.streams)).map(function (stream) { return (__assign(__assign({}, stream), { removed: false, mapArgs: [ '-map', diff --git a/FlowPlugins/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.js index b0da3c3cb..d4e0643fc 100644 --- a/FlowPlugins/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.js @@ -1,10 +1,42 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; -var fs_1 = __importDefault(require("fs")); var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ @@ -57,28 +89,36 @@ var details = function () { return ({ }); }; exports.details = details; // eslint-disable-next-line @typescript-eslint/no-unused-vars -var plugin = function (args) { - var lib = require('../../../../../methods/lib')(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign - args.inputs = lib.loadDefaultValues(args.inputs, details); - var directory = String(args.inputs.directory).trim() || (0, fileUtils_1.getFileAbosluteDir)(args.inputFileObj._id); - var fileName = (0, fileUtils_1.getFileName)(args.inputFileObj._id); - var fileToCheck = String(args.inputs.fileToCheck).trim(); - fileToCheck = fileToCheck.replace(/\${fileName}/g, fileName); - fileToCheck = fileToCheck.replace(/\${container}/g, (0, fileUtils_1.getContainer)(args.inputFileObj._id)); - fileToCheck = "".concat(directory, "/").concat(fileToCheck); - var fileExists = false; - if (fs_1.default.existsSync(fileToCheck)) { - fileExists = true; - args.jobLog("File exists: ".concat(fileToCheck)); - } - else { - args.jobLog("File does not exist: ".concat(fileToCheck)); - } - return { - outputFileObj: args.inputFileObj, - outputNumber: fileExists ? 1 : 2, - variables: args.variables, - }; -}; +var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function () { + var lib, directory, fileName, fileToCheck, fileDoesExist; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + directory = String(args.inputs.directory).trim() || (0, fileUtils_1.getFileAbosluteDir)(args.inputFileObj._id); + fileName = (0, fileUtils_1.getFileName)(args.inputFileObj._id); + fileToCheck = String(args.inputs.fileToCheck).trim(); + fileToCheck = fileToCheck.replace(/\${fileName}/g, fileName); + fileToCheck = fileToCheck.replace(/\${container}/g, (0, fileUtils_1.getContainer)(args.inputFileObj._id)); + fileToCheck = "".concat(directory, "/").concat(fileToCheck); + fileDoesExist = false; + return [4 /*yield*/, (0, fileUtils_1.fileExists)(fileToCheck)]; + case 1: + if (_a.sent()) { + fileDoesExist = true; + args.jobLog("File exists: ".concat(fileToCheck)); + } + else { + args.jobLog("File does not exist: ".concat(fileToCheck)); + } + return [2 /*return*/, { + outputFileObj: args.inputFileObj, + outputNumber: fileDoesExist ? 1 : 2, + variables: args.variables, + }]; + } + }); +}); }; exports.plugin = plugin; diff --git a/FlowPlugins/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.js index e403445b7..4649b88d7 100644 --- a/FlowPlugins/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.js @@ -38,12 +38,18 @@ var plugin = function (args) { args.inputs = lib.loadDefaultValues(args.inputs, details); var outputNumber = 1; if (args.inputFileObj.file_size < args.originalLibraryFile.file_size) { + args.jobLog("Working of size ".concat(args.inputFileObj.file_size) + + " is smaller than original file of size ".concat(args.originalLibraryFile.file_size)); outputNumber = 1; } else if (args.inputFileObj.file_size === args.originalLibraryFile.file_size) { + args.jobLog("Working of size ".concat(args.inputFileObj.file_size) + + " is same size as original file of size ".concat(args.originalLibraryFile.file_size)); outputNumber = 2; } else if (args.inputFileObj.file_size > args.originalLibraryFile.file_size) { + args.jobLog("Working of size ".concat(args.inputFileObj.file_size) + + " is larger than original file of size ".concat(args.originalLibraryFile.file_size)); outputNumber = 3; } return { diff --git a/FlowPlugins/CommunityFlowPlugins/file/compareFileSizeRatioLive/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/compareFileSizeRatioLive/1.0.0/index.js new file mode 100644 index 000000000..c3eb11b40 --- /dev/null +++ b/FlowPlugins/CommunityFlowPlugins/file/compareFileSizeRatioLive/1.0.0/index.js @@ -0,0 +1,139 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.plugin = exports.details = void 0; +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +var details = function () { return ({ + name: 'Compare File Size Ratio Live', + description: "\n Compare either the estimated final size or current output size to the input size and \n give an error if estimated final size or current size surpasses the threshold %.\n\n Works with 'FfmpegCommand', 'HandBrake Custom Arguments', 'Run Classic Transcode' and other flow plugins \n that output a file.\n\n Can be placed anywhere before a plugin which outputs a new file.\n\n You can check if this plugin caused an error by using 'Check Flow Variable' and checking if \n {{{args.variables.liveSizeCompare.error}}} is true.\n ',\n ", + 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 transcoding block and then\n disable it for another block.\n ", + }, + { + 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.\n Estimated Final Size: Compare the estimated final output size to the input size.\n Current Size: Compare the current output size to the input size.\n ", + }, + { + 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. \n An error will be triggered if the estimated or current size exceeds this percentage.\n\n For example, if the input size is 100MB and the threshold is 60%, the estimated final size or current size\n must not surpass 60MB else an error will be given and processing will stop.\n ", + }, + { + 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: "\n Specify the delay in seconds before beginning the comparison.\n A larger delay gives more time for the estimated final size to stabilize.\n ", + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Continue to next plugin', + }, + ], +}); }; +exports.details = details; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +var plugin = function (args) { + var lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + var enabled = Boolean(args.inputs.enabled); + var compareMethod = String(args.inputs.compareMethod); + var thresholdPerc = Number(args.inputs.thresholdPerc); + var checkDelaySeconds = Number(args.inputs.checkDelaySeconds); + // eslint-disable-next-line no-param-reassign + args.variables.liveSizeCompare = { + enabled: enabled, + compareMethod: compareMethod, + thresholdPerc: thresholdPerc, + checkDelaySeconds: checkDelaySeconds, + error: false, + }; + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +exports.plugin = plugin; diff --git a/FlowPlugins/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.js index 4ac05b361..bc7e6ced7 100644 --- a/FlowPlugins/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.js @@ -114,7 +114,7 @@ var details = function () { return ({ inputUI: { type: 'switch', }, - tooltip: 'Specify whether to copy/move all files in the directory (excluding the original and working file)', + tooltip: "Specify whether to copy/move all files in the directory (excluding the original and working file)\n or use the input below to specify file extensions", }, { label: 'File Extensions', diff --git a/FlowPlugins/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.js index 0e103fe0f..6a6f56350 100644 --- a/FlowPlugins/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.js @@ -107,7 +107,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function args.inputs = lib.loadDefaultValues(args.inputs, details); _a = args.inputs, keepRelativePath = _a.keepRelativePath, makeWorkingFile = _a.makeWorkingFile; outputDirectory = String(args.inputs.outputDirectory); - originalFileName = (0, fileUtils_1.getFileName)(args.originalLibraryFile._id); + originalFileName = (0, fileUtils_1.getFileName)(args.inputFileObj._id); newContainer = (0, fileUtils_1.getContainer)(args.inputFileObj._id); outputPath = ''; if (keepRelativePath) { diff --git a/FlowPlugins/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.js index a586cdc4a..96c10d1e4 100644 --- a/FlowPlugins/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.js @@ -75,7 +75,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); - originalFileName = (0, fileUtils_1.getFileName)(args.originalLibraryFile._id); + originalFileName = (0, fileUtils_1.getFileName)(args.inputFileObj._id); newContainer = (0, fileUtils_1.getContainer)(args.inputFileObj._id); outputPath = args.workDir; ouputFilePath = (0, normJoinPath_1.default)({ diff --git a/FlowPlugins/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.js index 04c491b29..bd8f7fb88 100644 --- a/FlowPlugins/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.js @@ -97,7 +97,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function args.inputs = lib.loadDefaultValues(args.inputs, details); keepRelativePath = args.inputs.keepRelativePath; outputDirectory = String(args.inputs.outputDirectory); - originalFileName = (0, fileUtils_1.getFileName)(args.originalLibraryFile._id); + originalFileName = (0, fileUtils_1.getFileName)(args.inputFileObj._id); newContainer = (0, fileUtils_1.getContainer)(args.inputFileObj._id); outputPath = ''; if (keepRelativePath) { diff --git a/FlowPlugins/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.js index 118ee59d2..b007868b6 100644 --- a/FlowPlugins/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.js @@ -40,6 +40,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var fs_1 = require("fs"); var fileMoveOrCopy_1 = __importDefault(require("../../../../FlowHelpers/1.0.0/fileMoveOrCopy")); var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ @@ -70,11 +71,10 @@ var details = function () { return ({ exports.details = details; // eslint-disable-next-line @typescript-eslint/no-unused-vars var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function () { - var fs, lib, currentPath, orignalFolder, fileName, container, newPath, newPathTmp; + var lib, currentPath, orignalFolder, fileName, container, newPath, newPathTmp; return __generator(this, function (_a) { switch (_a.label) { case 0: - fs = require('fs'); lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); @@ -110,14 +110,17 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function })]; case 2: _a.sent(); - // delete original file - if (fs.existsSync(args.originalLibraryFile._id) - && args.originalLibraryFile._id !== currentPath) { - args.jobLog("Deleting original file:".concat(args.originalLibraryFile._id)); - fs.unlinkSync(args.originalLibraryFile._id); - } - return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 2000); })]; + return [4 /*yield*/, (0, fileUtils_1.fileExists)(args.originalLibraryFile._id)]; case 3: + if (!((_a.sent()) + && args.originalLibraryFile._id !== currentPath)) return [3 /*break*/, 5]; + args.jobLog("Deleting original file:".concat(args.originalLibraryFile._id)); + return [4 /*yield*/, fs_1.promises.unlink(args.originalLibraryFile._id)]; + case 4: + _a.sent(); + _a.label = 5; + case 5: return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 2000); })]; + case 6: _a.sent(); return [4 /*yield*/, (0, fileMoveOrCopy_1.default)({ operation: 'move', @@ -125,7 +128,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function destinationPath: newPath, args: args, })]; - case 4: + case 7: _a.sent(); return [2 /*return*/, { outputFileObj: { diff --git a/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.js index d1eedf894..7e72d268b 100644 --- a/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.js @@ -153,6 +153,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 4: diff --git a/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.js index acdc8acd7..6c396a7f3 100644 --- a/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.js @@ -197,6 +197,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 4: diff --git a/FlowPlugins/CommunityFlowPlugins/tools/apprise/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/tools/apprise/1.0.0/index.js new file mode 100644 index 000000000..6bfce81b9 --- /dev/null +++ b/FlowPlugins/CommunityFlowPlugins/tools/apprise/1.0.0/index.js @@ -0,0 +1,124 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.plugin = exports.details = void 0; +var cliUtils_1 = require("../../../../FlowHelpers/1.0.0/cliUtils"); +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +var details = function () { return ({ + name: 'Apprise', + description: 'Use Apprise to send notifications.', + style: { + borderColor: 'green', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.18.01', + sidebarPosition: -1, + icon: 'faBell', + inputs: [ + { + label: 'Command', + name: 'command', + type: 'string', + defaultValue: '-vv -t "Success" -b "File {{{args.inputFileObj._id}}}" "discord://xxx/xxxx"', + inputUI: { + type: 'textarea', + style: { + height: '100px', + }, + }, + tooltip: "Visit the following for more information on Apprise: https://github.com/caronc/apprise\n \\nExample\\n\n -vv -t \"Success\" -b \"File {{{args.inputFileObj._id}}}\" \"discord://xxx/xxxx\"\n\n\n \\nExample\\n\n -vv -t \"Processing\" -b \"File {{{args.inputFileObj._id}}}\" " + + "\"discord://{{{args.userVariables.global.discord_webhook}}}\"\n ", + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Continue to next plugin', + }, + ], +}); }; +exports.details = details; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function () { + var lib, command, cliArgs, cli, res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + command = args.inputs.command; + cliArgs = __spreadArray([], args.deps.parseArgsStringToArgv(command, '', ''), true); + cli = new cliUtils_1.CLI({ + cli: 'apprise', + spawnArgs: cliArgs, + spawnOpts: {}, + jobLog: args.jobLog, + outputFilePath: '', + inputFileObj: args.inputFileObj, + logFullCliOutput: args.logFullCliOutput, + updateWorker: args.updateWorker, + args: args, + }); + return [4 /*yield*/, cli.runCli()]; + case 1: + res = _a.sent(); + if (res.cliExitCode !== 0) { + args.jobLog('Running Apprise failed'); + throw new Error('Running Apprise failed'); + } + return [2 /*return*/, { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }]; + } + }); +}); }; +exports.plugin = plugin; diff --git a/FlowPlugins/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.js index 5854242cf..e5b0bdc65 100644 --- a/FlowPlugins/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.js @@ -19,7 +19,7 @@ var details = function () { return ({ label: 'Variable', name: 'variable', type: 'string', - defaultValue: '{{{args.librarySettings._id}}}', + defaultValue: '', inputUI: { type: 'text', }, diff --git a/FlowPlugins/CommunityFlowPlugins/tools/requireReview/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/tools/requireReview/1.0.0/index.js index 9f5c7777e..6851eaf05 100644 --- a/FlowPlugins/CommunityFlowPlugins/tools/requireReview/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/tools/requireReview/1.0.0/index.js @@ -4,7 +4,7 @@ exports.plugin = exports.details = void 0; /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Require Review', - description: "Makes the flow pause.\n The file will stay in the staging section on the Tdarr tab until the user clicks the \"Reviewed\" button.\n ", + description: "Makes the flow pause.\n The file will stay in the staging section on the Tdarr tab until the user clicks the \"Reviewed\" button.\n\n Note: The 'Auto accept successful transcodes' option on the Tdarr tab will cause this plugin to be skipped.\n ", style: { borderColor: 'yellow', }, diff --git a/FlowPlugins/CommunityFlowPlugins/tools/runCli/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/tools/runCli/1.0.0/index.js index 412e89fc9..ac1909acf 100644 --- a/FlowPlugins/CommunityFlowPlugins/tools/runCli/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/tools/runCli/1.0.0/index.js @@ -62,6 +62,16 @@ var details = function () { return ({ sidebarPosition: -1, icon: '', inputs: [ + { + label: 'Use Custom CLI Path?', + name: 'useCustomCliPath', + type: 'boolean', + defaultValue: 'false', + inputUI: { + type: 'switch', + }, + tooltip: 'Specify whether to use a custom CLI path', + }, { label: 'CLI', name: 'userCli', @@ -73,9 +83,49 @@ var details = function () { return ({ 'mkvmerge', 'mkvpropedit', ], + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useCustomCliPath', + value: 'false', + condition: '===', + }, + ], + }, + ], + }, }, tooltip: 'CLI to run', }, + { + label: 'Custom CLI Path', + name: 'customCliPath', + type: 'string', + defaultValue: '/usr/bin/mkvmerge', + inputUI: { + type: 'text', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useCustomCliPath', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, + }, + tooltip: 'Specify the path to the CLI to run', + }, { label: 'Does Command Create Output File?', name: 'doesCommandCreateOutputFile', @@ -112,6 +162,17 @@ var details = function () { return ({ }, tooltip: "\n This path can be accessed using ${outputFilePath} in the \"CLI Arguments\" input below.\n\n \\n\n ${cacheDir} is a special variable that points to the Tdarr worker cache directory.\n\n \\n \n ${fileName} is a special variable for the filename without extension.\n \n \\nExample\\n\n ${cacheDir}/${fileName}.{{{args.inputFileObj.container}}}\n ", }, + { + label: 'CLI Arguments', + name: 'cliArguments', + type: 'string', + // eslint-disable-next-line no-template-curly-in-string + defaultValue: '-o "${outputFilePath}" "{{{args.inputFileObj._id}}}"', + inputUI: { + type: 'text', + }, + tooltip: "Specify arguments to pass to the CLI. \n Normal variable templating with {{{}}} applies but ${outputFilePath} is a special\n variable from the \"Output File Path\" input above.\n\n \\nExample\\n\n -o \"${outputFilePath}\" \"{{{args.inputFileObj._id}}}\"\n ", + }, { label: 'Output File Becomes Working File?', name: 'outputFileBecomesWorkingFile', @@ -137,17 +198,6 @@ var details = function () { return ({ }, tooltip: 'Toggle this on to make the output file become the working file for the next plugin.', }, - { - label: 'CLI Arguments', - name: 'cliArguments', - type: 'string', - // eslint-disable-next-line no-template-curly-in-string - defaultValue: '-o "${outputFilePath}" "{{{args.inputFileObj._id}}}"', - inputUI: { - type: 'text', - }, - tooltip: "Specify arguments to pass to the CLI. \n Normal variable templating with {{{}}} applies but ${outputFilePath} is a special\n variable from the \"Output File Path\" input above.\n\n \\nExample\\n\n -o \"${outputFilePath}\" \"{{{args.inputFileObj._id}}}\"\n ", - }, ], outputs: [ { @@ -159,7 +209,7 @@ var details = function () { return ({ exports.details = details; // eslint-disable-next-line @typescript-eslint/no-unused-vars var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function () { - var lib, userCli, outputFileBecomesWorkingFile, userOutputFilePath, cliArguments, cacheDir, fileName, cliArgs, availableCli, msg, cli, res, msg; + var lib, userCli, useCustomCliPath, customCliPath, cliPath, outputFileBecomesWorkingFile, userOutputFilePath, cliArguments, cacheDir, fileName, cliArgs, availableCli, msg, cli, res, msg; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -167,6 +217,9 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); userCli = String(args.inputs.userCli); + useCustomCliPath = args.inputs.useCustomCliPath; + customCliPath = String(args.inputs.customCliPath); + cliPath = ''; outputFileBecomesWorkingFile = args.inputs.outputFileBecomesWorkingFile; userOutputFilePath = String(args.inputs.userOutputFilePath); cliArguments = String(args.inputs.cliArguments); @@ -189,14 +242,19 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function mkvpropedit: args.mkvpropeditPath, mkvmerge: 'mkvmerge', }; - if (!availableCli[userCli]) { - msg = "CLI ".concat(userCli, " not available to run in this plugin"); - args.jobLog(msg); - throw new Error(msg); + if (useCustomCliPath) { + cliPath = customCliPath; + } + else { + if (!availableCli[userCli]) { + msg = "CLI ".concat(userCli, " not available to run in this plugin"); + args.jobLog(msg); + throw new Error(msg); + } + cliPath = availableCli[userCli]; } - userCli = availableCli[userCli]; cli = new cliUtils_1.CLI({ - cli: userCli, + cli: cliPath, spawnArgs: cliArgs, spawnOpts: {}, jobLog: args.jobLog, @@ -204,12 +262,13 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 1: res = _a.sent(); if (res.cliExitCode !== 0) { - msg = "Running ".concat(userCli, " failed"); + msg = "Running ".concat(cliPath, " failed"); args.jobLog(msg); throw new Error(msg); } diff --git a/FlowPlugins/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.js index 16cd80601..06e74ee13 100644 --- a/FlowPlugins/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.js @@ -83,6 +83,7 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 1: diff --git a/FlowPlugins/CommunityFlowPlugins/tools/tagsRequeue/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/tools/tagsRequeue/1.0.0/index.js new file mode 100644 index 000000000..2c90c6d1a --- /dev/null +++ b/FlowPlugins/CommunityFlowPlugins/tools/tagsRequeue/1.0.0/index.js @@ -0,0 +1,115 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.plugin = exports.details = void 0; +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +var details = function () { return ({ + name: 'Tags: Requeue', + description: "\nPlace the file back in the staging queue with specific tags.\n\nOnly Nodes/Workers which match the tags will be able to process the file.\n\nThe tags must have one of the following: 'requireCPU', 'requireGPU', or 'requireCPUorGPU'.\n\nThe above tells the server what type of worker is required to process the file.\n\nSubsequent tags must not use the reserved word 'require' in them.\n\nYou can set the 'Node Tags' in the Node options panel.\n\nA worker will only process a file if the Custom Queue Tags are a subset of the Worker/Node Tags\n", + style: { + borderColor: 'yellow', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.20.01', + sidebarPosition: -1, + icon: 'faRedo', + inputs: [ + { + label: 'Use Basic Queue Tags', + name: 'useBasicQueueTags', + type: 'boolean', + defaultValue: 'true', + inputUI: { + type: 'switch', + }, + tooltip: 'Use basic queue tags or custom tags.', + }, + { + label: 'Basic Queue Tags', + name: 'basicQueueTags', + type: 'string', + defaultValue: 'requireCPU', + inputUI: { + type: 'dropdown', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useBasicQueueTags', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, + options: [ + 'requireCPU', + 'requireGPU', + 'requireGPU:nvenc', + 'requireGPU:qsv', + 'requireGPU:vaapi', + 'requireGPU:videotoolbox', + 'requireGPU:amf', + 'requireCPUorGPU', + ], + }, + tooltip: 'Specify tags to requeue file with.', + }, + { + label: 'Custom Queue Tags', + name: 'customQueueTags', + type: 'string', + defaultValue: 'requireCPUorGPU,tag1', + inputUI: { + type: 'textarea', + style: { + height: '100px', + }, + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useBasicQueueTags', + value: 'true', + condition: '!==', + }, + ], + }, + ], + }, + }, + tooltip: "\nrequireGPU:nvenc,tag1,tag2\nrequireCPUorGPU,tag1,tag2\nrequireCPU,tag1,tag2\nrequireGPU,tag1,tag2,tag3\nrequireGPU,tag1\nrequireGPU,{{{args.userVariables.global.test}}}\nrequireCPUorGPU,tag1,tag2\n ", + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Continue to next plugin', + }, + ], +}); }; +exports.details = details; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +var plugin = function (args) { + var lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + var basicQueueTags = String(args.inputs.basicQueueTags); + var customQueueTags = String(args.inputs.customQueueTags); + // eslint-disable-next-line no-param-reassign + args.variables.queueTags = args.inputs.useBasicQueueTags ? basicQueueTags : customQueueTags; + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +exports.plugin = plugin; diff --git a/FlowPlugins/CommunityFlowPlugins/tools/tagsWorkerType/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/tools/tagsWorkerType/1.0.0/index.js new file mode 100644 index 000000000..2006d1b1b --- /dev/null +++ b/FlowPlugins/CommunityFlowPlugins/tools/tagsWorkerType/1.0.0/index.js @@ -0,0 +1,123 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.plugin = exports.details = void 0; +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +var details = function () { return ({ + name: 'Tags: Worker Type', + description: "\nRequeues the item into the staging section if the current worker\ndoes not match the required worker type and tags.\n\nYou can set the 'Node Tags' in the Node options panel.\n\nThe required tags must be a subset of the current tags for the current worker to process the item,\nelse the item will be requeued with the required tags.\n ", + style: { + borderColor: 'yellow', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.20.01', + sidebarPosition: -1, + icon: 'faFilter', + inputs: [ + { + label: 'Required Transcode Worker Type', + name: 'requiredWorkerType', + type: 'string', + defaultValue: 'CPUorGPU', + inputUI: { + type: 'dropdown', + options: [ + 'CPUorGPU', + 'CPU', + 'GPU', + 'GPU:nvenc', + 'GPU:qsv', + 'GPU:vaapi', + 'GPU:videotoolbox', + 'GPU:amf', + ], + }, + tooltip: 'Specify worker type', + }, + { + label: 'Required Node Tags', + name: 'requiredNodeTags', + type: 'string', + defaultValue: '', + inputUI: { + type: 'textarea', + style: { + height: '100px', + }, + }, + tooltip: "\ntag1,tag2\n ", + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Continue to next plugin', + }, + ], +}); }; +exports.details = details; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +var plugin = function (args) { + var lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + var requiredWorkerType = String(args.inputs.requiredWorkerType); + var requiredNodeTags = String(args.inputs.requiredNodeTags); + var requiredTags = []; + var currentTags = []; + requiredTags.push("require".concat(requiredWorkerType)); + if (requiredNodeTags) { + requiredTags = requiredTags.concat(requiredNodeTags.split(',')); + } + var currentWorkerType = args.workerType; + if (requiredWorkerType === 'CPUorGPU') { + currentTags.push('requireCPUorGPU'); + } + else if (currentWorkerType === 'transcodecpu') { + currentTags.push('requireCPU'); + } + else if (currentWorkerType === 'transcodegpu') { + if (args.nodeHardwareType && args.nodeHardwareType !== '-') { + currentTags.push("requireGPU:".concat(args.nodeHardwareType)); + } + else { + currentTags.push('requireGPU'); + } + } + if (args.nodeTags) { + currentTags = currentTags.concat(args.nodeTags.split(',')); + } + requiredTags = requiredTags.map(function (tag) { return tag.trim(); }).filter(function (tag) { return tag !== ''; }); + currentTags = currentTags.map(function (tag) { return tag.trim(); }).filter(function (tag) { return tag !== ''; }); + args.jobLog("Required Tags: ".concat(requiredTags.join(','))); + args.jobLog("Current Tags: ".concat(currentTags.join(','))); + var isSubset = true; + for (var i = 0; i < requiredTags.length; i += 1) { + if (!currentTags.includes(requiredTags[i])) { + isSubset = false; + break; + } + } + // requiredTags needs to be subset of currentTags + args.jobLog("Current tags: ".concat(currentTags)); + args.jobLog("Required tags: ".concat(requiredTags)); + args.jobLog("Is Subset: ".concat(isSubset)); + if (isSubset) { + // eslint-disable-next-line no-param-reassign + args.variables.queueTags = ''; + args.jobLog('Required tags are subset of current tags, continuing to next plugin.'); + } + else { + args.jobLog('Required tags are not subset of current tags, requeueing.'); + // eslint-disable-next-line no-param-reassign + args.variables.queueTags = requiredTags.join(','); + args.jobLog("Requeueing with tags ".concat(args.variables.queueTags)); + } + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +exports.plugin = plugin; diff --git a/FlowPlugins/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.js index 9075aae3f..dfc2d4a94 100644 --- a/FlowPlugins/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.js @@ -122,14 +122,25 @@ var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args: args, }); return [4 /*yield*/, cli.runCli()]; case 1: res = _a.sent(); + if (!(typeof args.updateStat !== 'undefined')) return [3 /*break*/, 3]; + return [4 /*yield*/, args.updateStat(args.originalLibraryFile.DB, 'totalHealthCheckCount', 1)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: if (res.cliExitCode !== 0) { args.jobLog('Running CLI failed'); + args.logOutcome('hErr'); throw new Error('Running CLI failed'); } + args.logOutcome('hSuc'); + // will cause item to go into the health check success table + args.variables.healthCheck = 'Success'; return [2 /*return*/, { outputFileObj: args.inputFileObj, outputNumber: 1, diff --git a/FlowPlugins/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.js b/FlowPlugins/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.js index 3f05e5fa2..aa543a011 100644 --- a/FlowPlugins/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.js +++ b/FlowPlugins/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.js @@ -1,6 +1,44 @@ "use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.plugin = exports.details = void 0; +var fs_1 = require("fs"); +var fileUtils_1 = require("../../../../FlowHelpers/1.0.0/fileUtils"); /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ var details = function () { return ({ name: 'Transcode Video File', @@ -42,21 +80,32 @@ var details = function () { return ({ }); }; exports.details = details; // eslint-disable-next-line @typescript-eslint/no-unused-vars -var plugin = function (args) { - var lib = require('../../../../../methods/lib')(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign - args.inputs = lib.loadDefaultValues(args.inputs, details); - var fs = require('fs'); - var oldFile = args.inputFileObj._id; - var newFile = "".concat(args.inputFileObj._id, ".tmp"); - if (fs.existsSync(newFile)) { - fs.unlinkSync(newFile); - } - fs.copyFileSync(oldFile, newFile); - return { - outputFileObj: { _id: newFile }, - outputNumber: 1, - variables: args.variables, - }; -}; +var plugin = function (args) { return __awaiter(void 0, void 0, void 0, function () { + var lib, oldFile, newFile; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + lib = require('../../../../../methods/lib')(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign + args.inputs = lib.loadDefaultValues(args.inputs, details); + oldFile = args.inputFileObj._id; + newFile = "".concat(args.inputFileObj._id, ".tmp"); + return [4 /*yield*/, (0, fileUtils_1.fileExists)(newFile)]; + case 1: + if (!_a.sent()) return [3 /*break*/, 3]; + return [4 /*yield*/, fs_1.promises.unlink(newFile)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: return [4 /*yield*/, fs_1.promises.copyFile(oldFile, newFile)]; + case 4: + _a.sent(); + return [2 /*return*/, { + outputFileObj: { _id: newFile }, + outputNumber: 1, + variables: args.variables, + }]; + } + }); +}); }; exports.plugin = plugin; diff --git a/FlowPlugins/CommunityFlowTemplates/video/basicVideoMigz.js b/FlowPlugins/CommunityFlowTemplates/video/basicVideoMigz.js new file mode 100644 index 000000000..03bd58464 --- /dev/null +++ b/FlowPlugins/CommunityFlowTemplates/video/basicVideoMigz.js @@ -0,0 +1,177 @@ +"use strict"; +/* eslint-disable no-template-curly-in-string */ +/* eslint-disable import/prefer-default-export */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.details = void 0; +var details = function () { return ({ + name: 'Basic HEVC Video Flow - Migz 50%', + description: 'Basic HEVC video flow which uses the Migz GPU (NVENC) ' + + 'and Migz CPU plugins to aim for 50% file size reduction.', + tags: '', + flowPlugins: [ + { + name: 'Input File', + sourceRepo: 'Community', + pluginName: 'inputFile', + version: '1.0.0', + id: 'pE6rU7gkW', + position: { + x: 605.6174844367866, + y: 91.61529256488166, + }, + }, + { + name: 'Check if hevc', + sourceRepo: 'Community', + pluginName: 'checkVideoCodec', + version: '1.0.0', + id: '91b7IrsEc', + position: { + x: 605.9056229600291, + y: 192.7915128738341, + }, + }, + { + name: 'Replace Original File', + sourceRepo: 'Community', + pluginName: 'replaceOriginalFile', + version: '1.0.0', + id: '4fkfOyR3l', + position: { + x: 616.6829422267598, + y: 723.4017566509596, + }, + }, + { + name: 'Run Classic Transcode Plugin: Migz GPU', + sourceRepo: 'Community', + pluginName: 'runClassicTranscodePlugin', + version: '2.0.0', + id: 'QaMarr7U2', + position: { + x: 277.3652089704872, + y: 482.2580996510953, + }, + }, + { + name: 'Check Flow Variable: Worker Type', + sourceRepo: 'Community', + pluginName: 'checkFlowVariable', + version: '1.0.0', + id: 'R3SsqA2R2', + position: { + x: 388.92513564303005, + y: 265.27914587528255, + }, + inputsDB: { + variable: '{{{args.workerType}}}', + value: 'transcodegpu', + }, + }, + { + name: 'Run Classic Transcode Plugin: Migz CPU', + sourceRepo: 'Community', + pluginName: 'runClassicTranscodePlugin', + version: '2.0.0', + id: 'vML4LnVoU', + position: { + x: 480.1963619411388, + y: 479.8508686675832, + }, + inputsDB: { + pluginSourceId: 'Community:Tdarr_Plugin_MC93_Migz1FFMPEG_CPU', + }, + }, + { + name: 'Check Node Hardware Encoder', + sourceRepo: 'Community', + pluginName: 'checkNodeHardwareEncoder', + version: '1.0.0', + id: 'nXh1BK3js', + position: { + x: 302.73826398477604, + y: 373.54857265752986, + }, + }, + ], + flowEdges: [ + { + source: 'pE6rU7gkW', + sourceHandle: '1', + target: '91b7IrsEc', + targetHandle: null, + id: 'HhF4rw2DZ', + }, + { + source: '91b7IrsEc', + sourceHandle: '1', + target: '4fkfOyR3l', + targetHandle: null, + id: 'W2nVG7ts5', + }, + { + source: '91b7IrsEc', + sourceHandle: '2', + target: 'R3SsqA2R2', + targetHandle: null, + id: 'xZsf8IwDg', + }, + { + source: 'R3SsqA2R2', + sourceHandle: '2', + target: 'vML4LnVoU', + targetHandle: null, + id: 'RWv471I6E', + }, + { + source: 'QaMarr7U2', + sourceHandle: '1', + target: '4fkfOyR3l', + targetHandle: null, + id: 'CEk8bEYqP', + }, + { + source: 'QaMarr7U2', + sourceHandle: '2', + target: '4fkfOyR3l', + targetHandle: null, + id: 'vsKLZM4zM', + }, + { + source: 'vML4LnVoU', + sourceHandle: '1', + target: '4fkfOyR3l', + targetHandle: null, + id: 'vnP8TvN2d', + }, + { + source: 'vML4LnVoU', + sourceHandle: '2', + target: '4fkfOyR3l', + targetHandle: null, + id: '-KMkJCTg3', + }, + { + source: 'R3SsqA2R2', + sourceHandle: '1', + target: 'nXh1BK3js', + targetHandle: null, + id: 'vfT4o_4G6', + }, + { + source: 'nXh1BK3js', + sourceHandle: '1', + target: 'QaMarr7U2', + targetHandle: null, + id: 'eADOkFsGe', + }, + { + source: 'nXh1BK3js', + sourceHandle: '2', + target: 'vML4LnVoU', + targetHandle: null, + id: 'Blu0QflQK', + }, + ], +}); }; +exports.details = details; diff --git a/FlowPlugins/FlowHelpers/1.0.0/classicPlugins.js b/FlowPlugins/FlowHelpers/1.0.0/classicPlugins.js index f37b54528..69a6e69e6 100644 --- a/FlowPlugins/FlowHelpers/1.0.0/classicPlugins.js +++ b/FlowPlugins/FlowHelpers/1.0.0/classicPlugins.js @@ -40,7 +40,7 @@ exports.runClassicPlugin = void 0; var fs_1 = require("fs"); var fileUtils_1 = require("./fileUtils"); var runClassicPlugin = function (args, type) { return __awaiter(void 0, void 0, void 0, function () { - var path, pluginSourceId, parts, pluginSource, pluginId, relativePluginPath, absolutePath, classicPlugin, pluginSrcStr, res, container, cacheFilePath, scanTypes, pluginInputFileObj, originalLibraryFile, otherArguments, result; + var path, pluginSourceId, parts, pluginSource, pluginId, relativePluginPath, absolutePath, classicPlugin, pluginSrcStr, res, container, cacheFilePath, scanTypes, pluginInputFileObj, originalLibraryFile, inputFileScanArgs, originalLibraryFileScanArgs, otherArguments, result; var _a; return __generator(this, function (_b) { switch (_b.label) { @@ -99,28 +99,43 @@ var runClassicPlugin = function (args, type) { return __awaiter(void 0, void 0, container = (0, fileUtils_1.getContainer)(args.inputFileObj._id); cacheFilePath = "".concat((0, fileUtils_1.getPluginWorkDir)(args), "/").concat((0, fileUtils_1.getFileName)(args.inputFileObj._id), ".").concat(container); scanTypes = (0, fileUtils_1.getScanTypes)([pluginSrcStr]); + inputFileScanArgs = { + _id: args.inputFileObj._id, + file: args.inputFileObj.file, + DB: args.inputFileObj.DB, + footprintId: args.inputFileObj.footprintId, + }; + originalLibraryFileScanArgs = { + _id: args.originalLibraryFile._id, + file: args.originalLibraryFile.file, + DB: args.originalLibraryFile.DB, + footprintId: args.originalLibraryFile.footprintId, + }; + if (!(typeof args.scanIndividualFile !== 'undefined')) return [3 /*break*/, 12]; + args.jobLog('Scanning files using Node'); + return [4 /*yield*/, args.scanIndividualFile(inputFileScanArgs, scanTypes)]; + case 10: + pluginInputFileObj = _b.sent(); + return [4 /*yield*/, args.scanIndividualFile(originalLibraryFileScanArgs, scanTypes)]; + case 11: + originalLibraryFile = _b.sent(); + return [3 /*break*/, 15]; + case 12: + args.jobLog('Scanning files using Server API'); return [4 /*yield*/, args.deps.axiosMiddleware('api/v2/scan-individual-file', { - file: { - _id: args.inputFileObj._id, - file: args.inputFileObj.file, - DB: args.inputFileObj.DB, - footprintId: args.inputFileObj.footprintId, - }, + file: inputFileScanArgs, scanTypes: scanTypes, })]; - case 10: + case 13: pluginInputFileObj = _b.sent(); return [4 /*yield*/, args.deps.axiosMiddleware('api/v2/scan-individual-file', { - file: { - _id: args.originalLibraryFile._id, - file: args.originalLibraryFile.file, - DB: args.originalLibraryFile.DB, - footprintId: args.originalLibraryFile.footprintId, - }, + file: originalLibraryFileScanArgs, scanTypes: scanTypes, })]; - case 11: + case 14: originalLibraryFile = _b.sent(); + _b.label = 15; + case 15: otherArguments = { handbrakePath: args.handbrakePath, ffmpegPath: args.ffmpegPath, @@ -135,14 +150,14 @@ var runClassicPlugin = function (args, type) { return __awaiter(void 0, void 0, job: args.job, }; return [4 /*yield*/, classicPlugin.plugin(pluginInputFileObj, args.librarySettings, args.inputs, otherArguments)]; - case 12: + case 16: result = _b.sent(); if (((_a = result === null || result === void 0 ? void 0 : result.file) === null || _a === void 0 ? void 0 : _a._id) && args.inputFileObj._id !== result.file._id) { + args.jobLog("File ID changed from ".concat(args.inputFileObj._id, " to ").concat(result.file._id)); // eslint-disable-next-line no-param-reassign args.inputFileObj._id = result.file._id; // eslint-disable-next-line no-param-reassign args.inputFileObj.file = result.file.file; - args.jobLog("File ID changed from ".concat(args.inputFileObj._id, " to ").concat(result.file._id)); } return [2 /*return*/, { result: result, diff --git a/FlowPlugins/FlowHelpers/1.0.0/cliParsers.js b/FlowPlugins/FlowHelpers/1.0.0/cliParsers.js index eee0cfde1..e14129012 100644 --- a/FlowPlugins/FlowHelpers/1.0.0/cliParsers.js +++ b/FlowPlugins/FlowHelpers/1.0.0/cliParsers.js @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.editreadyParser = exports.getFFmpegVar = exports.getFFmpegPercentage = exports.ffmpegParser = exports.handbrakeParser = void 0; +exports.editreadyParser = exports.getHandBrakeFps = exports.getFFmpegVar = exports.getFFmpegPercentage = exports.ffmpegParser = exports.handbrakeParser = void 0; var handbrakeParser = function (_a) { var str = _a.str, hbPass = _a.hbPass; if (typeof str !== 'string') { @@ -30,6 +30,24 @@ var handbrakeParser = function (_a) { return percentage; }; exports.handbrakeParser = handbrakeParser; +var getHandBrakeFps = function (_a) { + var str = _a.str; + try { + if (typeof str !== 'string' || !(str.includes('(') && str.includes('fps'))) { + return 0; + } + var out = parseInt(str.split('(')[1].split('fps')[0].trim(), 10); + // eslint-disable-next-line no-restricted-globals + if (!isNaN(out)) { + return out; + } + } + catch (err) { + // err + } + return 0; +}; +exports.getHandBrakeFps = getHandBrakeFps; // frame= 889 fps=106 q=26.0 Lsize= 25526kB time=00:00:35.69 bitrate=5858.3kbits/s speed=4.25x var getFFmpegVar = function (_a) { var str = _a.str, variable = _a.variable; diff --git a/FlowPlugins/FlowHelpers/1.0.0/cliUtils.js b/FlowPlugins/FlowHelpers/1.0.0/cliUtils.js index 22b228abe..1acba4b59 100644 --- a/FlowPlugins/FlowHelpers/1.0.0/cliUtils.js +++ b/FlowPlugins/FlowHelpers/1.0.0/cliUtils.js @@ -35,10 +35,14 @@ var __generator = (this && this.__generator) || function (thisArg, body) { if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.CLI = exports.getFFmpegVar = void 0; +var fs_1 = __importDefault(require("fs")); var cliParsers_1 = require("./cliParsers"); -var fs = require('fs'); +var fileUtils_1 = require("./fileUtils"); var fancyTimeFormat = function (time) { // Hours, minutes and seconds // eslint-disable-next-line no-bitwise @@ -93,60 +97,111 @@ var CLI = /** @class */ (function () { this.oldProgress = 0; this.lastProgCheck = 0; this.hbPass = 0; - this.updateETA = function (perc) { - if (perc > 0) { - if (_this.lastProgCheck === 0) { - _this.lastProgCheck = new Date().getTime(); - _this.oldProgress = perc; - } - else if (perc !== _this.oldProgress) { - var n = new Date().getTime(); - var secsSinceLastCheck = (n - _this.lastProgCheck) / 1000; - if (secsSinceLastCheck > 1) { - // eta total - var eta = Math.round((100 / (perc - _this.oldProgress)) * secsSinceLastCheck); + this.cancelled = false; + this.startTime = new Date().getTime(); + this.updateETA = function (perc) { return __awaiter(_this, void 0, void 0, function () { + var n, secsSinceLastCheck, eta, sum, avg, estSize, outputFileSizeInGbytes, singleFileSize, err_1, secondsSinceStart, _a, compareMethod, thresholdPerc_1, checkDelaySeconds, inputFileSize, inputFileSizeInGbytes_1, cancel, ratio, ratio; + var _this = this; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (!(perc > 0)) return [3 /*break*/, 6]; + if (!(this.lastProgCheck === 0)) return [3 /*break*/, 1]; + this.lastProgCheck = new Date().getTime(); + this.oldProgress = perc; + return [3 /*break*/, 6]; + case 1: + if (!(perc !== this.oldProgress)) return [3 /*break*/, 6]; + n = new Date().getTime(); + secsSinceLastCheck = (n - this.lastProgCheck) / 1000; + if (!(secsSinceLastCheck > 1)) return [3 /*break*/, 6]; + eta = Math.round((100 / (perc - this.oldProgress)) * secsSinceLastCheck); // eta remaining eta *= ((100 - perc) / 100); - _this.progAVG.push(eta); - // let values = [2, 56, 3, 41, 0, 4, 100, 23]; - var sum = _this.progAVG.reduce( + this.progAVG.push(eta); + sum = this.progAVG.reduce( // eslint-disable-next-line function (previous, current) { return (current += previous); }); - var avg = sum / _this.progAVG.length; - // est size - var estSize = 0; - var outputFileSizeInGbytes = void 0; - try { - if (fs.existsSync(_this.config.outputFilePath)) { - var singleFileSize = fs.statSync(_this.config.outputFilePath); - singleFileSize = singleFileSize.size; - outputFileSizeInGbytes = singleFileSize / (1024 * 1024 * 1024); - if (outputFileSizeInGbytes !== _this.oldOutSize) { - _this.oldOutSize = outputFileSizeInGbytes; - estSize = outputFileSizeInGbytes - + ((100 - perc) / perc) * outputFileSizeInGbytes; - _this.oldEstSize = estSize; - } + avg = sum / this.progAVG.length; + estSize = 0; + outputFileSizeInGbytes = void 0; + _c.label = 2; + case 2: + _c.trys.push([2, 4, , 5]); + return [4 /*yield*/, (0, fileUtils_1.fileExists)(this.config.outputFilePath)]; + case 3: + if (_c.sent()) { + singleFileSize = fs_1.default.statSync(this.config.outputFilePath); + // @ts-expect-error type + singleFileSize = singleFileSize.size; + // @ts-expect-error type + outputFileSizeInGbytes = singleFileSize / (1024 * 1024 * 1024); + if (outputFileSizeInGbytes !== this.oldOutSize) { + this.oldOutSize = outputFileSizeInGbytes; + estSize = outputFileSizeInGbytes + + ((100 - perc) / perc) * outputFileSizeInGbytes; + this.oldEstSize = estSize; } } - catch (err) { - // eslint-disable-next-line no-console - console.log(err); - } - _this.config.updateWorker({ + return [3 /*break*/, 5]; + case 4: + err_1 = _c.sent(); + // eslint-disable-next-line no-console + console.log(err_1); + return [3 /*break*/, 5]; + case 5: + this.config.updateWorker({ ETA: fancyTimeFormat(avg), outputFileSizeInGbytes: outputFileSizeInGbytes === undefined ? 0 : outputFileSizeInGbytes, - estSize: _this.oldEstSize === undefined ? 0 : _this.oldEstSize, + estSize: this.oldEstSize === undefined ? 0 : this.oldEstSize, }); - if (_this.progAVG.length > 30) { - _this.progAVG.splice(0, 1); + if (this.progAVG.length > 30) { + this.progAVG.splice(0, 1); } - _this.lastProgCheck = n; - _this.oldProgress = perc; - } + this.lastProgCheck = n; + this.oldProgress = perc; + secondsSinceStart = (new Date().getTime() - this.startTime) / 1000; + // live size compare + if ((_b = this.config.args.variables.liveSizeCompare) === null || _b === void 0 ? void 0 : _b.enabled) { + _a = this.config.args.variables.liveSizeCompare, compareMethod = _a.compareMethod, thresholdPerc_1 = _a.thresholdPerc, checkDelaySeconds = _a.checkDelaySeconds; + if (secondsSinceStart > checkDelaySeconds) { + inputFileSize = this.config.inputFileObj.file_size; + inputFileSizeInGbytes_1 = inputFileSize / 1024; + cancel = function (ratio) { + _this.config.jobLog("Input file size: ".concat(inputFileSizeInGbytes_1, "GB")); + _this.config.jobLog("Ratio: ".concat(ratio, "%")); + _this.config.jobLog("Ratio is greater than threshold: ".concat(thresholdPerc_1, "%, cancelling job")); + _this.cancelled = true; + // @ts-expect-error must exist to be here + _this.config.args.variables.liveSizeCompare.error = true; + _this.killThread(); + }; + if (compareMethod === 'estimatedFinalSize' + && estSize !== undefined + && estSize > 0) { + ratio = (estSize / inputFileSizeInGbytes_1) * 100; + if (ratio > thresholdPerc_1) { + this.config.jobLog("Estimated final size: ".concat(estSize, "GB")); + cancel(ratio); + } + } + else if (compareMethod === 'currentSize' + && outputFileSizeInGbytes !== undefined + && outputFileSizeInGbytes > 0) { + ratio = (outputFileSizeInGbytes / inputFileSizeInGbytes_1) * 100; + if (ratio > thresholdPerc_1) { + this.config.jobLog("Current output size: ".concat(outputFileSizeInGbytes, "GB")); + cancel(ratio); + } + } + } + } + _c.label = 6; + case 6: return [2 /*return*/]; } - } - }; + }); + }); }; this.parseOutput = function (data) { var _a, _b, _c, _d, _e, _f, _g; var str = "".concat(data); @@ -166,11 +221,19 @@ var CLI = /** @class */ (function () { hbPass: _this.hbPass, }); if (percentage > 0) { - _this.updateETA(percentage); + void _this.updateETA(percentage); _this.config.updateWorker({ percentage: percentage, }); } + var fps = (0, cliParsers_1.getHandBrakeFps)({ + str: str, + }); + if (fps > 0) { + _this.config.updateWorker({ + fps: fps, + }); + } } else if (_this.config.cli.toLowerCase().includes('ffmpeg')) { var n = str.indexOf('fps'); @@ -206,7 +269,7 @@ var CLI = /** @class */ (function () { }); } if (percentage > 0) { - _this.updateETA(percentage); + void _this.updateETA(percentage); _this.config.updateWorker({ percentage: percentage, }); @@ -217,15 +280,14 @@ var CLI = /** @class */ (function () { str: str, }); if (percentage > 0) { - _this.updateETA(percentage); + void _this.updateETA(percentage); _this.config.updateWorker({ percentage: percentage, }); } } }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types - this.killThread = function (thread) { + this.killThread = function () { var killArray = [ 'SIGKILL', 'SIGHUP', @@ -233,14 +295,14 @@ var CLI = /** @class */ (function () { 'SIGINT', ]; try { - thread.kill(); + _this.thread.kill(); } catch (err) { // err } killArray.forEach(function (com) { try { - thread.kill(com); + _this.thread.kill(com); } catch (err) { // err @@ -248,7 +310,7 @@ var CLI = /** @class */ (function () { }); }; this.runCli = function () { return __awaiter(_this, void 0, void 0, function () { - var childProcess, errorLogFull, thread, exitHandler, cliExitCode; + var childProcess, errorLogFull, exitHandler, cliExitCode; var _this = this; return __generator(this, function (_a) { switch (_a.label) { @@ -257,11 +319,11 @@ var CLI = /** @class */ (function () { errorLogFull = []; this.config.jobLog("Running ".concat(this.config.cli, " ").concat(this.config.spawnArgs.join(' '))); exitHandler = function () { - 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 @@ -276,28 +338,30 @@ var CLI = /** @class */ (function () { try { var opts = _this.config.spawnOpts || {}; var spawnArgs = _this.config.spawnArgs.map(function (row) { return row.trim(); }).filter(function (row) { return row !== ''; }); - thread = childProcess.spawn(_this.config.cli, spawnArgs, opts); - thread.stdout.on('data', function (data) { + _this.thread = childProcess.spawn(_this.config.cli, spawnArgs, opts); + _this.thread.stdout.on('data', function (data) { errorLogFull.push(data.toString()); _this.parseOutput(data); }); - thread.stderr.on('data', function (data) { + _this.thread.stderr.on('data', function (data) { // eslint-disable-next-line no-console errorLogFull.push(data.toString()); _this.parseOutput(data); }); - thread.on('error', function () { + _this.thread.on('error', function () { // catches execution error (bad file) // eslint-disable-next-line no-console - console.log(1, "Error executing binary: ".concat(_this.config.cli)); + console.log("Error executing binary: ".concat(_this.config.cli)); + _this.config.jobLog("Error executing binary: ".concat(_this.config.cli)); resolve(1); }); // thread.stdout.pipe(process.stdout); // thread.stderr.pipe(process.stderr); - thread.on('close', function (code) { + _this.thread.on('close', function (code) { if (code !== 0) { // eslint-disable-next-line no-console - console.log(code, 'CLI error'); + console.log("CLI error code: ".concat(code)); + _this.config.jobLog("CLI error code: ".concat(code)); } resolve(code); }); @@ -305,17 +369,22 @@ var CLI = /** @class */ (function () { catch (err) { // catches execution error (no file) // eslint-disable-next-line no-console - console.log(1, "Error executing binary: ".concat(_this.config.cli)); + console.log("Error executing binary: ".concat(_this.config.cli, ": ").concat(err)); + _this.config.jobLog("Error executing binary: ".concat(_this.config.cli, ": ").concat(err)); resolve(1); } })]; case 1: cliExitCode = _a.sent(); 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; + } + this.config.jobLog("CLI ".concat(this.config.cli, " exited with code: ").concat(cliExitCode)); return [2 /*return*/, { cliExitCode: cliExitCode, errorLogFull: errorLogFull, diff --git a/FlowPlugins/FlowHelpers/1.0.0/fileUtils.js b/FlowPlugins/FlowHelpers/1.0.0/fileUtils.js index 1e3604571..49e8d2b62 100644 --- a/FlowPlugins/FlowHelpers/1.0.0/fileUtils.js +++ b/FlowPlugins/FlowHelpers/1.0.0/fileUtils.js @@ -36,8 +36,15 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getScanTypes = exports.getPluginWorkDir = exports.moveFileAndValidate = exports.getFileSize = exports.getSubStem = exports.getFfType = exports.getFileAbosluteDir = exports.getFileName = exports.getContainer = void 0; +exports.getScanTypes = exports.getPluginWorkDir = exports.moveFileAndValidate = exports.getFileSize = exports.getSubStem = exports.getFfType = exports.getFileAbosluteDir = exports.getFileName = exports.getContainer = exports.fileExists = void 0; var fs_1 = require("fs"); +var fileExists = function (path) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, fs_1.promises.stat(path).catch(function () { return false; })]; + case 1: return [2 /*return*/, !!(_a.sent())]; + } +}); }); }; +exports.fileExists = fileExists; var getContainer = function (filePath) { var parts = filePath.split('.'); return parts[parts.length - 1]; diff --git a/FlowPlugins/FlowHelpers/1.0.0/interfaces/flowUtils.js b/FlowPlugins/FlowHelpers/1.0.0/interfaces/flowUtils.js new file mode 100644 index 000000000..1b137a8a7 --- /dev/null +++ b/FlowPlugins/FlowHelpers/1.0.0/interfaces/flowUtils.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.checkFfmpegCommandInit = void 0; +// eslint-disable-next-line import/prefer-default-export +var checkFfmpegCommandInit = function (args) { + var _a, _b; + if (!((_b = (_a = args === null || args === void 0 ? void 0 : args.variables) === null || _a === void 0 ? void 0 : _a.ffmpegCommand) === null || _b === void 0 ? void 0 : _b.init)) { + throw new Error('FFmpeg command plugins not used correctly.' + + ' Please use the "Begin Command" plugin before using this plugin.' + + ' Afterwards, use the "Execute" plugin to execute the built FFmpeg command.' + + ' Once the "Execute" plugin has been used, you need to use a new "Begin Command"' + + ' plugin to start a new FFmpeg command.'); + } +}; +exports.checkFfmpegCommandInit = checkFfmpegCommandInit; diff --git a/FlowPluginsTs/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.ts index 812db93d3..ea5a66817 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/audio/checkAudioCodec/1.0.0/index.ts @@ -7,7 +7,7 @@ import { /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ const details = ():IpluginDetails => ({ name: 'Check Audio Codec', - description: 'Check if a file has a specific audio codec', + description: 'Check if a file has a specific audio codec.', style: { borderColor: 'orange', }, diff --git a/FlowPluginsTs/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/audio/normalizeAudio/1.0.0/index.ts index 7a2c5c66c..cc56c2c76 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 2f1a1c163..3ca660e47 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/basic/basicVideoOrAudio/1.0.0/index.ts @@ -10,7 +10,7 @@ import { getContainer, getFileName, getPluginWorkDir } from '../../../../FlowHel const details = (): IpluginDetails => ({ name: 'Basic Video or Audio Settings', description: `Basic Video or Audio settings designed to replicate - the Basic Video or Basic Audio settings in the library settings + the Basic Video or Basic Audio settings in the library settings. `, style: { borderColor: 'green', @@ -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 59d3bfc56..70f9ee190 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 new file mode 100644 index 000000000..2fce826c3 --- /dev/null +++ b/FlowPluginsTs/CommunityFlowPlugins/classic/runClassicTranscodePlugin/2.0.0/index.ts @@ -0,0 +1,213 @@ +import { CLI } from '../../../../FlowHelpers/1.0.0/cliUtils'; +import { + IpluginDetails, + IpluginInputArgs, + IpluginOutputArgs, +} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; +import { runClassicPlugin } from '../../../../FlowHelpers/1.0.0/classicPlugins'; + +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +const details = (): IpluginDetails => ({ + name: 'Run Classic Transcode Plugin', + description: 'Run one of Tdarr\'s classic plugins that has Operation: Transcode', + style: { + borderColor: 'green', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.11.01', + sidebarPosition: -1, + icon: '', + inputs: [ + { + label: 'Plugin Source ID', + name: 'pluginSourceId', + type: 'string', + defaultValue: 'Community:Tdarr_Plugin_MC93_Migz1FFMPEG', + inputUI: { + type: 'dropdown', + options: [], + }, + tooltip: 'Specify the classic plugin ID', + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Processing was done by the classic plugin', + }, + { + number: 2, + tooltip: 'Processing was not done by the classic plugin', + }, + ], +}); + +const replaceContainer = (filePath:string, container:string): string => { + const parts = filePath.split('.'); + parts[parts.length - 1] = container.split('.').join(''); + return parts.join('.'); +}; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const plugin = async (args: IpluginInputArgs): Promise => { + 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 outcome = await runClassicPlugin(args, 'transcode'); + const { result, absolutePath } = outcome; + + let { cacheFilePath } = outcome; + + args.jobLog(JSON.stringify(result, null, 2)); + + if (!result) { + args.jobLog('No result from classic plugin. Continuing to next flow plugin.'); + return { + outputFileObj: args.inputFileObj, + outputNumber: 2, + variables: args.variables, + }; + } + + // --- Backwards compatibility------------ + if (result.handBrakeMode) { + result.handbrakeMode = result.handBrakeMode; + } + + if (result.FFmpegMode) { + result.ffmpegMode = result.FFmpegMode; + } + //---------------------------------------- + + if (result.ffmpegMode) { + result.cliToUse = 'ffmpeg'; + } else if (result.handbrakeMode) { + result.cliToUse = 'handbrake'; + } else if (typeof result?.custom?.cliPath === 'string') { + const { cliPath } = result.custom; + if (cliPath.toLowerCase().includes('ffmpeg')) { + result.cliToUse = 'ffmpeg'; + } else if (cliPath.toLowerCase().includes('handbrake')) { + result.cliToUse = 'handbrake'; + } else if (cliPath.toLowerCase().includes('editready')) { + result.cliToUse = 'editready'; + } else if (cliPath.toLowerCase().includes('av1an')) { + result.cliToUse = 'av1an'; + } + } + + result.workerLog = result.transcodeSettingsLog; + args.jobLog(JSON.stringify(result, null, 2)); + + if (result.error) { + throw new Error(`Plugin ${absolutePath} failed: ${result.error}`); + } if (result.processFile !== true) { + args.jobLog('Classic plugin does not need to process file. Continuing to next flow plugin.'); + return { + outputFileObj: args.inputFileObj, + outputNumber: 2, + variables: args.variables, + }; + } + + const customArgs = result?.custom?.args; + const isCustomConfig = (Array.isArray(customArgs) && customArgs.length > 0) + || (typeof customArgs === 'string' + // @ts-expect-error length + && customArgs.length + > 0); + + if (!isCustomConfig) { + cacheFilePath = replaceContainer(cacheFilePath, result.container); + } else { + // @ts-expect-error type + cacheFilePath = result.custom.outputPath; + } + + let presetSplit; + if (result.preset.includes('')) { + presetSplit = result.preset.split(''); + } else { + presetSplit = result.preset.split(','); + } + + let workerCommand: string[] = []; + let cliPath = ''; + + if (isCustomConfig) { + // @ts-expect-error cliPath + cliPath = result?.custom?.cliPath; + + if (Array.isArray(customArgs)) { + workerCommand = customArgs; + } else { + workerCommand = [ + ...args.deps.parseArgsStringToArgv(customArgs, '', ''), + ]; + } + } else { + // working on windows with '` and spaces + // working on unix with ' + switch (true) { + case result.cliToUse === 'handbrake': + workerCommand = [ + '-i', + `${args.inputFileObj._id}`, + '-o', + `${cacheFilePath}`, + ...args.deps.parseArgsStringToArgv(result.preset, '', ''), + ]; + + cliPath = `${args.handbrakePath}`; + break; + + case result.cliToUse === 'ffmpeg': + workerCommand = [ + ...args.deps.parseArgsStringToArgv(presetSplit[0], '', ''), + '-i', + `${args.inputFileObj._id}`, + ...args.deps.parseArgsStringToArgv(presetSplit[1], '', ''), + `${cacheFilePath}`, + ]; + cliPath = `${args.ffmpegPath}`; + break; + default: + } + } + + const cli = new CLI({ + cli: cliPath, + spawnArgs: workerCommand, + spawnOpts: {}, + jobLog: args.jobLog, + outputFilePath: cacheFilePath, + inputFileObj: args.inputFileObj, + logFullCliOutput: args.logFullCliOutput, + updateWorker: args.updateWorker, + args, + }); + + const res = await cli.runCli(); + + if (res.cliExitCode !== 0) { + args.jobLog(`Running ${cliPath} failed`); + throw new Error(`Running ${cliPath} failed`); + } + + args.logOutcome('tSuc'); + + return { + outputFileObj: { + _id: cacheFilePath, + }, + outputNumber: 1, + variables: args.variables, + }; +}; +export { + details, + plugin, +}; diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.ts index ee44e3072..03d2e9f90 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommand10BitVideo/1.0.0/index.ts @@ -1,8 +1,10 @@ +import os from 'os'; import { IpluginDetails, IpluginInputArgs, IpluginOutputArgs, } from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ const details = () :IpluginDetails => ({ @@ -32,12 +34,14 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + for (let i = 0; i < args.variables.ffmpegCommand.streams.length; i += 1) { const stream = args.variables.ffmpegCommand.streams[i]; if (stream.codec_type === 'video') { stream.outputArgs.push('-profile:v:{outputTypeIndex}', 'main10'); - if (stream.outputArgs.some((row) => row.includes('qsv'))) { + if (stream.outputArgs.some((row) => row.includes('qsv')) && os.platform() !== 'win32') { stream.outputArgs.push('-vf', 'scale_qsv=format=p010le'); } else { stream.outputArgs.push('-pix_fmt:v:{outputTypeIndex}', 'p010le'); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.ts index 9f05381fb..9c54868f2 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCropBlackBars/1.0.0/index.ts @@ -1,3 +1,4 @@ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -33,6 +34,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + return { outputFileObj: args.inputFileObj, outputNumber: 1, diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.ts index 37215090a..74ac04e0b 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandCustomArguments/1.0.0/index.ts @@ -1,3 +1,4 @@ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -54,6 +55,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const inputArguments = String(args.inputs.inputArguments); const outputArguments = String(args.inputs.outputArguments); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.ts index ff3b084a9..49efcbe49 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandEnsureAudioStream/1.0.0/index.ts @@ -1,4 +1,5 @@ import { getFfType } from '../../../../FlowHelpers/1.0.0/fileUtils'; +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IffmpegCommandStream, IpluginDetails, @@ -270,6 +271,8 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const audioEncoder = String(args.inputs.audioEncoder); const langTag = String(args.inputs.language).toLowerCase(); const wantedChannelCount = Number(args.inputs.channels); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts index 2791d89a2..7c1838519 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandExecute/1.0.0/index.ts @@ -6,6 +6,7 @@ import { } from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; import { CLI } from '../../../../FlowHelpers/1.0.0/cliUtils'; import { getFileName, getPluginWorkDir } from '../../../../FlowHelpers/1.0.0/fileUtils'; +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ const details = (): IpluginDetails => ({ @@ -68,6 +69,8 @@ const plugin = async (args: IpluginInputArgs): Promise => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const cliArgs: string[] = []; cliArgs.push('-y'); @@ -168,6 +171,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); @@ -179,6 +183,9 @@ const plugin = async (args: IpluginInputArgs): Promise => { args.logOutcome('tSuc'); + // eslint-disable-next-line no-param-reassign + args.variables.ffmpegCommand.init = false; + return { outputFileObj: { _id: outputFilePath, diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.ts index 16022748d..3383db4a8 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandHdrToSdr/1.0.0/index.ts @@ -1,3 +1,4 @@ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -32,6 +33,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + args.variables.ffmpegCommand.streams.forEach((stream) => { if (stream.codec_type === 'video') { stream.outputArgs.push('-vf', 'zscale=t=linear:npl=100,format=yuv420p'); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.ts index fd925f3d3..e427d14aa 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandNormalizeAudio/1.0.0/index.ts @@ -1,3 +1,4 @@ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -33,6 +34,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + return { outputFileObj: args.inputFileObj, outputNumber: 1, diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.ts index 041da601d..c4b5ba000 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveDataStreams/1.0.0/index.ts @@ -1,5 +1,6 @@ /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -35,6 +36,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + args.variables.ffmpegCommand.streams.forEach((stream) => { if (stream.codec_type === 'data') { stream.removed = true; diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.ts index 5a9c987eb..7d034983a 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveStreamByProperty/1.0.0/index.ts @@ -1,3 +1,4 @@ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -84,8 +85,10 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const propertyToCheck = String(args.inputs.propertyToCheck).trim(); - const valuesToRemove = String(args.inputs.valuesToRemove).trim().split(','); + const valuesToRemove = String(args.inputs.valuesToRemove).trim().split(',').map((item) => item.trim()); const condition = String(args.inputs.condition); args.variables.ffmpegCommand.streams.forEach((stream) => { @@ -101,7 +104,6 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { const prop = String(target).toLowerCase(); for (let i = 0; i < valuesToRemove.length; i += 1) { const val = valuesToRemove[i].toLowerCase(); - const prefix = `Removing stream index ${stream.index} because ${propertyToCheck} of ${prop}`; if (condition === 'includes' && prop.includes(val)) { args.jobLog(`${prefix} includes ${val}\n`); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.ts index f25661563..c36125327 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandRemoveSubtitles/1.0.0/index.ts @@ -1,5 +1,6 @@ /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -34,6 +35,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + args.variables.ffmpegCommand.streams.forEach((stream) => { if (stream.codec_type === 'subtitle') { stream.removed = true; diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.ts index 2ed84f985..cfdcf4f06 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetContainer/1.0.0/index.ts @@ -1,6 +1,7 @@ /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ import { getContainer } from '../../../../FlowHelpers/1.0.0/fileUtils'; +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -64,6 +65,8 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const newContainer = String(args.inputs.container); const { forceConform } = args.inputs; @@ -93,11 +96,14 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { if (newContainer === 'mp4') { if ( - [ + codecType === 'attachment' + || [ 'hdmv_pgs_subtitle', 'eia_608', 'timed_id3', 'subrip', + 'ass', + 'ssa', ].includes(codecName) ) { stream.removed = true; @@ -108,6 +114,18 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { } } } + // handle genpts if coming from odd container + const container = args.inputFileObj.container.toLowerCase(); + if ( + [ + 'ts', + 'avi', + 'mpg', + 'mpeg', + ].includes(container) + ) { + args.variables.ffmpegCommand.overallOuputArguments.push('-fflags', '+genpts'); + } } return { diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.ts index 37021be51..bf76158f5 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoFramerate/1.0.0/index.ts @@ -1,3 +1,4 @@ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -44,6 +45,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const desiredFrameRate = Number(args.inputs.framerate); args.jobLog(`Desired framerate: ${desiredFrameRate}`); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.ts index 8f44b1f32..6069a9277 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVdeoResolution/1.0.0/index.ts @@ -1,3 +1,4 @@ +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -77,6 +78,8 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + for (let i = 0; i < args.variables.ffmpegCommand.streams.length; i += 1) { const stream = args.variables.ffmpegCommand.streams[i]; diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.ts index 178768552..535087286 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoBitrate/1.0.0/index.ts @@ -4,6 +4,7 @@ import { IpluginOutputArgs, } from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; import { getFfType } from '../../../../FlowHelpers/1.0.0/fileUtils'; +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ const details = (): IpluginDetails => ({ @@ -120,6 +121,8 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const { useInputBitrate } = args.inputs; const targetBitratePercent = String(args.inputs.targetBitratePercent); const fallbackBitrate = String(args.inputs.fallbackBitrate); diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.ts index 920ece68c..3591ce070 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandSetVideoEncoder/1.0.0/index.ts @@ -1,6 +1,7 @@ /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ import { getEncoder } from '../../../../FlowHelpers/1.0.0/hardwareUtils'; +import { checkFfmpegCommandInit } from '../../../../FlowHelpers/1.0.0/interfaces/flowUtils'; import { IpluginDetails, IpluginInputArgs, @@ -38,6 +39,16 @@ const details = (): IpluginDetails => ({ }, tooltip: 'Specify codec of the output file', }, + { + label: 'Enable FFmpeg Preset', + name: 'ffmpegPresetEnabled', + type: 'boolean', + defaultValue: 'true', + inputUI: { + type: 'switch', + }, + tooltip: 'Specify whether to use an FFmpeg preset', + }, { label: 'FFmpeg Preset', name: 'ffmpegPreset', @@ -56,9 +67,34 @@ const details = (): IpluginDetails => ({ 'superfast', 'ultrafast', ], + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'ffmpegPresetEnabled', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, }, tooltip: 'Specify ffmpeg preset', }, + { + label: 'Enable FFmpeg Quality', + name: 'ffmpegQualityEnabled', + type: 'boolean', + defaultValue: 'true', + inputUI: { + type: 'switch', + }, + tooltip: 'Specify whether to set crf (or qp for GPU encoding)', + }, { label: 'FFmpeg Quality', name: 'ffmpegQuality', @@ -66,8 +102,23 @@ const details = (): IpluginDetails => ({ defaultValue: '25', inputUI: { type: 'text', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'ffmpegQualityEnabled', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, }, - tooltip: 'Specify ffmpeg quality', + tooltip: 'Specify ffmpeg quality crf (or qp for GPU encoding)', }, { label: 'Hardware Encoding', @@ -131,6 +182,8 @@ const plugin = async (args: IpluginInputArgs): Promise => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); + checkFfmpegCommandInit(args); + const hardwareDecoding = args.inputs.hardwareDecoding === true; const hardwareType = String(args.inputs.hardwareType); args.variables.ffmpegCommand.hardwareDecoding = hardwareDecoding; @@ -140,6 +193,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { if (stream.codec_type === 'video') { const targetCodec = String(args.inputs.outputCodec); + const { ffmpegPresetEnabled, ffmpegQualityEnabled } = args.inputs; const ffmpegPreset = String(args.inputs.ffmpegPreset); const ffmpegQuality = String(args.inputs.ffmpegQuality); const forceEncoding = args.inputs.forceEncoding === true; @@ -161,14 +215,18 @@ const plugin = async (args: IpluginInputArgs): Promise => { stream.outputArgs.push('-c:{outputIndex}', encoderProperties.encoder); - if (encoderProperties.isGpu) { - stream.outputArgs.push('-qp', ffmpegQuality); - } else { - stream.outputArgs.push('-crf', ffmpegQuality); + if (ffmpegQualityEnabled) { + if (encoderProperties.isGpu) { + stream.outputArgs.push('-qp', ffmpegQuality); + } else { + stream.outputArgs.push('-crf', ffmpegQuality); + } } - if (targetCodec !== 'av1' && ffmpegPreset) { - stream.outputArgs.push('-preset', ffmpegPreset); + if (ffmpegPresetEnabled) { + if (targetCodec !== 'av1' && ffmpegPreset) { + stream.outputArgs.push('-preset', ffmpegPreset); + } } if (hardwareDecoding) { diff --git a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.ts index a2824072a..1cb6c2f1d 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/ffmpegCommand/ffmpegCommandStart/1.0.0/index.ts @@ -40,6 +40,7 @@ const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { const container = getContainer(args.inputFileObj._id); const ffmpegCommand = { + init: true, inputFiles: [], streams: JSON.parse(JSON.stringify(args.inputFileObj.ffProbeData.streams)).map((stream:Istreams) => ({ ...stream, diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.ts index a16c39c4b..de26096f0 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/checkFileExists/1.0.0/index.ts @@ -1,5 +1,6 @@ -import fs from 'fs'; -import { getContainer, getFileAbosluteDir, getFileName } from '../../../../FlowHelpers/1.0.0/fileUtils'; +import { + fileExists, getContainer, getFileAbosluteDir, getFileName, +} from '../../../../FlowHelpers/1.0.0/fileUtils'; import { IpluginDetails, IpluginInputArgs, @@ -57,7 +58,7 @@ const details = (): IpluginDetails => ({ }); // eslint-disable-next-line @typescript-eslint/no-unused-vars -const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { +const plugin = async (args: IpluginInputArgs): Promise => { const lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); @@ -71,9 +72,9 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { fileToCheck = fileToCheck.replace(/\${container}/g, getContainer(args.inputFileObj._id)); fileToCheck = `${directory}/${fileToCheck}`; - let fileExists = false; - if (fs.existsSync(fileToCheck)) { - fileExists = true; + let fileDoesExist = false; + if (await fileExists(fileToCheck)) { + fileDoesExist = true; args.jobLog(`File exists: ${fileToCheck}`); } else { args.jobLog(`File does not exist: ${fileToCheck}`); @@ -81,7 +82,7 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { return { outputFileObj: args.inputFileObj, - outputNumber: fileExists ? 1 : 2, + outputNumber: fileDoesExist ? 1 : 2, variables: args.variables, }; }; diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.ts index c1a041e14..726d0c6ee 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSize/1.0.0/index.ts @@ -45,10 +45,16 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => { let outputNumber = 1; if (args.inputFileObj.file_size < args.originalLibraryFile.file_size) { + args.jobLog(`Working of size ${args.inputFileObj.file_size}` + + ` is smaller than original file of size ${args.originalLibraryFile.file_size}`); outputNumber = 1; } else if (args.inputFileObj.file_size === args.originalLibraryFile.file_size) { + args.jobLog(`Working of size ${args.inputFileObj.file_size}` + + ` is same size as original file of size ${args.originalLibraryFile.file_size}`); outputNumber = 2; } else if (args.inputFileObj.file_size > args.originalLibraryFile.file_size) { + args.jobLog(`Working of size ${args.inputFileObj.file_size}` + + ` is larger than original file of size ${args.originalLibraryFile.file_size}`); outputNumber = 3; } 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 000000000..4051238c3 --- /dev/null +++ b/FlowPluginsTs/CommunityFlowPlugins/file/compareFileSizeRatioLive/1.0.0/index.ts @@ -0,0 +1,173 @@ +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. + + You can check if this plugin caused an error by using 'Check Flow Variable' and checking if + {{{args.variables.liveSizeCompare.error}}} is true. + ', + `, + 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 transcoding block and then + disable it for another block. + `, + }, + { + 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, + error: false, + }; + + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +export { + details, + plugin, +}; diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.ts index 673af0407..ca4615f25 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/copyMoveFolderContent/1.0.0/index.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { getContainer, getFileAbosluteDir, getSubStem, } from '../../../../FlowHelpers/1.0.0/fileUtils'; @@ -82,7 +82,8 @@ Useful if, for example, you want to move things like subtitle files or cover art inputUI: { type: 'switch', }, - tooltip: 'Specify whether to copy/move all files in the directory (excluding the original and working file)', + tooltip: `Specify whether to copy/move all files in the directory (excluding the original and working file) + or use the input below to specify file extensions`, }, { label: 'File Extensions', @@ -187,7 +188,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { sourceDir = getFileAbosluteDir(args.inputFileObj._id); } - let filesInDir = (await fs.readdir(sourceDir)) + let filesInDir = (await fsp.readdir(sourceDir)) .map((row) => ({ source: `${sourceDir}/${row}`, destination: normJoinPath({ diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.ts index 6d198602b..ade516129 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/copyToDirectory/1.0.0/index.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { getContainer, getFileName, getSubStem } from '../../../../FlowHelpers/1.0.0/fileUtils'; import { IpluginDetails, @@ -73,7 +73,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { const outputDirectory = String(args.inputs.outputDirectory); - const originalFileName = getFileName(args.originalLibraryFile._id); + const originalFileName = getFileName(args.inputFileObj._id); const newContainer = getContainer(args.inputFileObj._id); let outputPath = ''; @@ -126,7 +126,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { args.deps.fsextra.ensureDirSync(outputPath); - await fs.copyFile(args.inputFileObj._id, ouputFilePath); + await fsp.copyFile(args.inputFileObj._id, ouputFilePath); return { outputFileObj: { diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.ts index 04458d1f8..fb587005f 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/copyToWorkDirectory/1.0.0/index.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { getContainer, getFileName } from '../../../../FlowHelpers/1.0.0/fileUtils'; import { IpluginDetails, @@ -37,7 +37,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); - const originalFileName = getFileName(args.originalLibraryFile._id); + const originalFileName = getFileName(args.inputFileObj._id); const newContainer = getContainer(args.inputFileObj._id); const outputPath = args.workDir; @@ -67,7 +67,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { args.deps.fsextra.ensureDirSync(outputPath); - await fs.copyFile(args.inputFileObj._id, ouputFilePath); + await fsp.copyFile(args.inputFileObj._id, ouputFilePath); return { outputFileObj: { diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/deleteFile/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/deleteFile/1.0.0/index.ts index 1969c22f0..e403d9ca9 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/deleteFile/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/deleteFile/1.0.0/index.ts @@ -1,4 +1,5 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; + import { IpluginDetails, IpluginInputArgs, @@ -64,21 +65,21 @@ const plugin = async (args: IpluginInputArgs): Promise => { if (fileToDelete === 'workingFile') { args.jobLog(`Deleting working file ${args.inputFileObj._id}`); - await fs.unlink(args.inputFileObj._id); + await fsp.unlink(args.inputFileObj._id); } else if (fileToDelete === 'originalFile') { args.jobLog(`Deleting original file ${args.originalLibraryFile._id}`); - await fs.unlink(args.originalLibraryFile._id); + await fsp.unlink(args.originalLibraryFile._id); } const fileDir = getFileAbosluteDir(args.originalLibraryFile._id); if (deleteParentFolderIfEmpty) { args.jobLog(`Checking if folder ${fileDir} is empty`); - const files = await fs.readdir(fileDir); + const files = await fsp.readdir(fileDir); if (files.length === 0) { args.jobLog(`Deleting empty folder ${fileDir}`); - await fs.rmdir(fileDir); + await fsp.rmdir(fileDir); } else { args.jobLog(`Folder ${fileDir} is not empty, skipping delete`); } diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.ts index 75b2d6483..1dffd6070 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/moveToDirectory/2.0.0/index.ts @@ -65,7 +65,7 @@ const plugin = async (args:IpluginInputArgs):Promise => { const outputDirectory = String(args.inputs.outputDirectory); - const originalFileName = getFileName(args.originalLibraryFile._id); + const originalFileName = getFileName(args.inputFileObj._id); const newContainer = getContainer(args.inputFileObj._id); let outputPath = ''; diff --git a/FlowPluginsTs/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.ts index 34098cee6..7a2431d58 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/file/replaceOriginalFile/1.0.0/index.ts @@ -1,5 +1,7 @@ +import { promises as fsp } from 'fs'; import fileMoveOrCopy from '../../../../FlowHelpers/1.0.0/fileMoveOrCopy'; import { + fileExists, getContainer, getFileAbosluteDir, getFileName, } from '../../../../FlowHelpers/1.0.0/fileUtils'; import { @@ -36,7 +38,6 @@ const details = (): IpluginDetails => ({ // eslint-disable-next-line @typescript-eslint/no-unused-vars const plugin = async (args: IpluginInputArgs): Promise => { - const fs = require('fs'); const lib = require('../../../../../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); @@ -80,11 +81,11 @@ const plugin = async (args: IpluginInputArgs): Promise => { // delete original file if ( - fs.existsSync(args.originalLibraryFile._id) + await fileExists(args.originalLibraryFile._id) && args.originalLibraryFile._id !== currentPath ) { args.jobLog(`Deleting original file:${args.originalLibraryFile._id}`); - fs.unlinkSync(args.originalLibraryFile._id); + await fsp.unlink(args.originalLibraryFile._id); } await new Promise((resolve) => setTimeout(resolve, 2000)); diff --git a/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts index 1b97c8721..4250d3431 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/1.0.0/index.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { CLI } from '../../../../FlowHelpers/1.0.0/cliUtils'; import { IpluginDetails, @@ -99,7 +99,7 @@ const plugin = async (args:IpluginInputArgs):Promise => { if (presetString.trim() !== '') { const preset = JSON.parse(presetString); - await fs.writeFile(presetPath, JSON.stringify(preset, null, 2)); + await fsp.writeFile(presetPath, JSON.stringify(preset, null, 2)); cliArgs.push('--preset-import-file'); cliArgs.push(presetPath); cliArgs.push('-Z'); @@ -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 6ac4355c4..48fe1ca04 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/handbrake/handbrakeCustomArguments/2.0.0/index.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { CLI } from '../../../../FlowHelpers/1.0.0/cliUtils'; import { IpluginDetails, @@ -142,7 +142,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { if (useJsonPreset) { const preset = JSON.parse(presetString); - await fs.writeFile(presetPath, JSON.stringify(preset, null, 2)); + await fsp.writeFile(presetPath, JSON.stringify(preset, null, 2)); cliArgs.push('--preset-import-file'); cliArgs.push(presetPath); cliArgs.push('-Z'); @@ -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/input/inputFile/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/input/inputFile/1.0.0/index.ts index 0dc18a081..b6b220e2e 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/input/inputFile/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/input/inputFile/1.0.0/index.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { IpluginDetails, @@ -86,7 +86,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { const checkReadWrite = async (location: string) => { try { - await fs.access(location, fs.constants.R_OK); + await fsp.access(location, fsp.constants.R_OK); } catch (err) { args.jobLog(JSON.stringify(err)); if (pauseNodeIfAccessChecksFail) { @@ -97,7 +97,7 @@ const plugin = async (args: IpluginInputArgs): Promise => { } try { - await fs.access(location, fs.constants.W_OK); + await fsp.access(location, fsp.constants.W_OK); } catch (err) { args.jobLog(JSON.stringify(err)); if (pauseNodeIfAccessChecksFail) { diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/apprise/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/apprise/1.0.0/index.ts new file mode 100644 index 000000000..d4e336465 --- /dev/null +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/apprise/1.0.0/index.ts @@ -0,0 +1,93 @@ +import { CLI } from '../../../../FlowHelpers/1.0.0/cliUtils'; +import { + IpluginDetails, + IpluginInputArgs, + IpluginOutputArgs, +} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; + +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +const details = ():IpluginDetails => ({ + name: 'Apprise', + description: 'Use Apprise to send notifications.', + style: { + borderColor: 'green', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.18.01', + sidebarPosition: -1, + icon: 'faBell', + inputs: [ + { + label: 'Command', + name: 'command', + type: 'string', + defaultValue: '-vv -t "Success" -b "File {{{args.inputFileObj._id}}}" "discord://xxx/xxxx"', + inputUI: { + type: 'textarea', + style: { + height: '100px', + }, + }, + tooltip: `Visit the following for more information on Apprise: https://github.com/caronc/apprise + \\nExample\\n + -vv -t "Success" -b "File {{{args.inputFileObj._id}}}" "discord://xxx/xxxx" + + + \\nExample\\n + -vv -t "Processing" -b "File {{{args.inputFileObj._id}}}" ` + + + `"discord://{{{args.userVariables.global.discord_webhook}}}" + `, + }, + ], + outputs: [ + { + number: 1, + tooltip: 'Continue to next plugin', + }, + ], +}); + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const plugin = async (args:IpluginInputArgs):Promise => { + 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 { command } = args.inputs; + + const cliArgs = [ + ...args.deps.parseArgsStringToArgv(command, '', ''), + ]; + + const cli = new CLI({ + cli: 'apprise', + spawnArgs: cliArgs, + spawnOpts: {}, + jobLog: args.jobLog, + outputFilePath: '', + inputFileObj: args.inputFileObj, + logFullCliOutput: args.logFullCliOutput, + updateWorker: args.updateWorker, + args, + }); + + const res = await cli.runCli(); + + if (res.cliExitCode !== 0) { + args.jobLog('Running Apprise failed'); + throw new Error('Running Apprise failed'); + } + + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +export { + details, + plugin, +}; diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.ts index 02b37877e..e7010863c 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/checkFlowVariable/1.0.0/index.ts @@ -22,7 +22,7 @@ const details = (): IpluginDetails => ({ label: 'Variable', name: 'variable', type: 'string', - defaultValue: '{{{args.librarySettings._id}}}', + defaultValue: '', inputUI: { type: 'text', }, diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/requireReview/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/requireReview/1.0.0/index.ts index 053e0d15b..d399ce2af 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/tools/requireReview/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/requireReview/1.0.0/index.ts @@ -9,6 +9,8 @@ const details = (): IpluginDetails => ({ name: 'Require Review', description: `Makes the flow pause. The file will stay in the staging section on the Tdarr tab until the user clicks the "Reviewed" button. + + Note: The 'Auto accept successful transcodes' option on the Tdarr tab will cause this plugin to be skipped. `, style: { borderColor: 'yellow', diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts index 9fbc7fc0d..cd2e05192 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/runCli/1.0.0/index.ts @@ -20,6 +20,16 @@ const details = (): IpluginDetails => ({ sidebarPosition: -1, icon: '', inputs: [ + { + label: 'Use Custom CLI Path?', + name: 'useCustomCliPath', + type: 'boolean', + defaultValue: 'false', + inputUI: { + type: 'switch', + }, + tooltip: 'Specify whether to use a custom CLI path', + }, { label: 'CLI', name: 'userCli', @@ -31,9 +41,49 @@ const details = (): IpluginDetails => ({ 'mkvmerge', 'mkvpropedit', ], + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useCustomCliPath', + value: 'false', + condition: '===', + }, + ], + }, + ], + }, }, tooltip: 'CLI to run', }, + { + label: 'Custom CLI Path', + name: 'customCliPath', + type: 'string', + defaultValue: '/usr/bin/mkvmerge', + inputUI: { + type: 'text', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useCustomCliPath', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, + }, + tooltip: 'Specify the path to the CLI to run', + }, { label: 'Does Command Create Output File?', name: 'doesCommandCreateOutputFile', @@ -82,6 +132,24 @@ const details = (): IpluginDetails => ({ \${cacheDir}/\${fileName}.{{{args.inputFileObj.container}}} `, }, + { + label: 'CLI Arguments', + name: 'cliArguments', + type: 'string', + // eslint-disable-next-line no-template-curly-in-string + defaultValue: '-o "${outputFilePath}" "{{{args.inputFileObj._id}}}"', + inputUI: { + type: 'text', + }, + tooltip: `Specify arguments to pass to the CLI. + Normal variable templating with {{{}}} applies but \${outputFilePath} is a special + variable from the "Output File Path" input above. + + \\nExample\\n + -o "\${outputFilePath}" "{{{args.inputFileObj._id}}}" + `, + }, + { label: 'Output File Becomes Working File?', name: 'outputFileBecomesWorkingFile', @@ -108,23 +176,6 @@ const details = (): IpluginDetails => ({ tooltip: 'Toggle this on to make the output file become the working file for the next plugin.', }, - { - label: 'CLI Arguments', - name: 'cliArguments', - type: 'string', - // eslint-disable-next-line no-template-curly-in-string - defaultValue: '-o "${outputFilePath}" "{{{args.inputFileObj._id}}}"', - inputUI: { - type: 'text', - }, - tooltip: `Specify arguments to pass to the CLI. - Normal variable templating with {{{}}} applies but \${outputFilePath} is a special - variable from the "Output File Path" input above. - - \\nExample\\n - -o "\${outputFilePath}" "{{{args.inputFileObj._id}}}" - `, - }, ], outputs: [ { @@ -140,7 +191,11 @@ const plugin = async (args: IpluginInputArgs): Promise => { // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign args.inputs = lib.loadDefaultValues(args.inputs, details); - let userCli = String(args.inputs.userCli); + const userCli = String(args.inputs.userCli); + const { useCustomCliPath } = args.inputs; + const customCliPath = String(args.inputs.customCliPath); + let cliPath = ''; + const { outputFileBecomesWorkingFile, } = args.inputs; @@ -175,16 +230,20 @@ const plugin = async (args: IpluginInputArgs): Promise => { mkvmerge: 'mkvmerge', }; - if (!availableCli[userCli]) { - const msg = `CLI ${userCli} not available to run in this plugin`; - args.jobLog(msg); - throw new Error(msg); - } + if (useCustomCliPath) { + cliPath = customCliPath; + } else { + if (!availableCli[userCli]) { + const msg = `CLI ${userCli} not available to run in this plugin`; + args.jobLog(msg); + throw new Error(msg); + } - userCli = availableCli[userCli]; + cliPath = availableCli[userCli]; + } const cli = new CLI({ - cli: userCli, + cli: cliPath, spawnArgs: cliArgs, spawnOpts: {}, jobLog: args.jobLog, @@ -192,12 +251,13 @@ const plugin = async (args: IpluginInputArgs): Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); if (res.cliExitCode !== 0) { - const msg = `Running ${userCli} failed`; + const msg = `Running ${cliPath} failed`; args.jobLog(msg); throw new Error(msg); } diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/runMkvPropEdit/1.0.0/index.ts index 34167d972..cfb9ed73f 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/tools/tagsRequeue/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/tagsRequeue/1.0.0/index.ts new file mode 100644 index 000000000..6cbd519fd --- /dev/null +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/tagsRequeue/1.0.0/index.ts @@ -0,0 +1,146 @@ +import { + IpluginDetails, + IpluginInputArgs, + IpluginOutputArgs, +} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; + +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +const details = (): IpluginDetails => ({ + name: 'Tags: Requeue', + description: ` +Place the file back in the staging queue with specific tags. + +Only Nodes/Workers which match the tags will be able to process the file. + +The tags must have one of the following: 'requireCPU', 'requireGPU', or 'requireCPUorGPU'. + +The above tells the server what type of worker is required to process the file. + +Subsequent tags must not use the reserved word 'require' in them. + +You can set the 'Node Tags' in the Node options panel. + +A worker will only process a file if the Custom Queue Tags are a subset of the Worker/Node Tags +`, + style: { + borderColor: 'yellow', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.20.01', + sidebarPosition: -1, + icon: 'faRedo', + inputs: [ + { + label: 'Use Basic Queue Tags', + name: 'useBasicQueueTags', + type: 'boolean', + defaultValue: 'true', + inputUI: { + type: 'switch', + }, + tooltip: 'Use basic queue tags or custom tags.', + }, + { + label: 'Basic Queue Tags', + name: 'basicQueueTags', + type: 'string', + defaultValue: 'requireCPU', + inputUI: { + type: 'dropdown', + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useBasicQueueTags', + value: 'true', + condition: '===', + }, + ], + }, + ], + }, + options: [ + 'requireCPU', + 'requireGPU', + 'requireGPU:nvenc', + 'requireGPU:qsv', + 'requireGPU:vaapi', + 'requireGPU:videotoolbox', + 'requireGPU:amf', + 'requireCPUorGPU', + ], + }, + tooltip: 'Specify tags to requeue file with.', + }, + { + label: 'Custom Queue Tags', + name: 'customQueueTags', + type: 'string', + defaultValue: 'requireCPUorGPU,tag1', + inputUI: { + type: 'textarea', + style: { + height: '100px', + }, + displayConditions: { + logic: 'AND', + sets: [ + { + logic: 'AND', + inputs: [ + { + name: 'useBasicQueueTags', + value: 'true', + condition: '!==', + }, + ], + }, + ], + }, + }, + tooltip: ` +requireGPU:nvenc,tag1,tag2 +requireCPUorGPU,tag1,tag2 +requireCPU,tag1,tag2 +requireGPU,tag1,tag2,tag3 +requireGPU,tag1 +requireGPU,{{{args.userVariables.global.test}}} +requireCPUorGPU,tag1,tag2 + `, + }, + ], + 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 basicQueueTags = String(args.inputs.basicQueueTags); + const customQueueTags = String(args.inputs.customQueueTags); + + // eslint-disable-next-line no-param-reassign + args.variables.queueTags = args.inputs.useBasicQueueTags ? basicQueueTags : customQueueTags; + + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +export { + details, + plugin, +}; diff --git a/FlowPluginsTs/CommunityFlowPlugins/tools/tagsWorkerType/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/tools/tagsWorkerType/1.0.0/index.ts new file mode 100644 index 000000000..793eaebf7 --- /dev/null +++ b/FlowPluginsTs/CommunityFlowPlugins/tools/tagsWorkerType/1.0.0/index.ts @@ -0,0 +1,147 @@ +import { + IpluginDetails, + IpluginInputArgs, + IpluginOutputArgs, +} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; + +/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ +const details = (): IpluginDetails => ({ + name: 'Tags: Worker Type', + description: ` +Requeues the item into the staging section if the current worker +does not match the required worker type and tags. + +You can set the 'Node Tags' in the Node options panel. + +The required tags must be a subset of the current tags for the current worker to process the item, +else the item will be requeued with the required tags. + `, + style: { + borderColor: 'yellow', + }, + tags: '', + isStartPlugin: false, + pType: '', + requiresVersion: '2.20.01', + sidebarPosition: -1, + icon: 'faFilter', + inputs: [ + { + label: 'Required Transcode Worker Type', + name: 'requiredWorkerType', + type: 'string', + defaultValue: 'CPUorGPU', + inputUI: { + type: 'dropdown', + options: [ + 'CPUorGPU', + 'CPU', + 'GPU', + 'GPU:nvenc', + 'GPU:qsv', + 'GPU:vaapi', + 'GPU:videotoolbox', + 'GPU:amf', + ], + }, + tooltip: 'Specify worker type', + }, + { + label: 'Required Node Tags', + name: 'requiredNodeTags', + type: 'string', + defaultValue: '', + inputUI: { + type: 'textarea', + style: { + height: '100px', + }, + }, + tooltip: ` +tag1,tag2 + `, + }, + ], + 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 requiredWorkerType = String(args.inputs.requiredWorkerType); + const requiredNodeTags = String(args.inputs.requiredNodeTags); + + let requiredTags = []; + let currentTags = []; + + requiredTags.push(`require${requiredWorkerType}`); + if (requiredNodeTags) { + requiredTags = requiredTags.concat(requiredNodeTags.split(',')); + } + + const currentWorkerType = args.workerType; + + if (requiredWorkerType === 'CPUorGPU') { + currentTags.push('requireCPUorGPU'); + } else if (currentWorkerType === 'transcodecpu') { + currentTags.push('requireCPU'); + } else if (currentWorkerType === 'transcodegpu') { + if (args.nodeHardwareType && args.nodeHardwareType !== '-') { + currentTags.push(`requireGPU:${args.nodeHardwareType}`); + } else { + currentTags.push('requireGPU'); + } + } + + if (args.nodeTags) { + currentTags = currentTags.concat(args.nodeTags.split(',')); + } + + requiredTags = requiredTags.map((tag) => tag.trim()).filter((tag) => tag !== ''); + currentTags = currentTags.map((tag) => tag.trim()).filter((tag) => tag !== ''); + + args.jobLog(`Required Tags: ${requiredTags.join(',')}`); + args.jobLog(`Current Tags: ${currentTags.join(',')}`); + + let isSubset = true; + + for (let i = 0; i < requiredTags.length; i += 1) { + if (!currentTags.includes(requiredTags[i])) { + isSubset = false; + break; + } + } + // requiredTags needs to be subset of currentTags + args.jobLog(`Current tags: ${currentTags}`); + args.jobLog(`Required tags: ${requiredTags}`); + args.jobLog(`Is Subset: ${isSubset}`); + + if (isSubset) { + // eslint-disable-next-line no-param-reassign + args.variables.queueTags = ''; + args.jobLog('Required tags are subset of current tags, continuing to next plugin.'); + } else { + args.jobLog('Required tags are not subset of current tags, requeueing.'); + // eslint-disable-next-line no-param-reassign + args.variables.queueTags = requiredTags.join(','); + args.jobLog(`Requeueing with tags ${args.variables.queueTags}`); + } + + return { + outputFileObj: args.inputFileObj, + outputNumber: 1, + variables: args.variables, + }; +}; +export { + details, + plugin, +}; diff --git a/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts index 550062b5b..f8db0c3e0 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/video/runHealthCheck/1.0.0/index.ts @@ -93,15 +93,27 @@ const plugin = async (args:IpluginInputArgs):Promise => { inputFileObj: args.inputFileObj, logFullCliOutput: args.logFullCliOutput, updateWorker: args.updateWorker, + args, }); const res = await cli.runCli(); + // Added in 2.19.01 + if (typeof args.updateStat !== 'undefined') { + await args.updateStat(args.originalLibraryFile.DB, 'totalHealthCheckCount', 1); + } + if (res.cliExitCode !== 0) { args.jobLog('Running CLI failed'); + args.logOutcome('hErr'); throw new Error('Running CLI failed'); } + args.logOutcome('hSuc'); + + // will cause item to go into the health check success table + args.variables.healthCheck = 'Success'; + return { outputFileObj: args.inputFileObj, outputNumber: 1, diff --git a/FlowPluginsTs/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.ts b/FlowPluginsTs/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.ts index 14b7d1e8b..643f88176 100644 --- a/FlowPluginsTs/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.ts +++ b/FlowPluginsTs/CommunityFlowPlugins/video/transcodeVideo/1.0.0/index.ts @@ -1,8 +1,10 @@ +import { promises as fsp } from 'fs'; import { IpluginDetails, IpluginInputArgs, IpluginOutputArgs, } from '../../../../FlowHelpers/1.0.0/interfaces/interfaces'; +import { fileExists } from '../../../../FlowHelpers/1.0.0/fileUtils'; /* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ const details = ():IpluginDetails => ({ @@ -46,21 +48,19 @@ const details = ():IpluginDetails => ({ }); // eslint-disable-next-line @typescript-eslint/no-unused-vars -const plugin = (args:IpluginInputArgs):IpluginOutputArgs => { +const plugin = async (args:IpluginInputArgs):Promise => { 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 fs = require('fs'); - const oldFile = args.inputFileObj._id; const newFile = `${args.inputFileObj._id}.tmp`; - if (fs.existsSync(newFile)) { - fs.unlinkSync(newFile); + if (await fileExists(newFile)) { + await fsp.unlink(newFile); } - fs.copyFileSync(oldFile, newFile); + await fsp.copyFile(oldFile, newFile); return { outputFileObj: { _id: newFile }, diff --git a/FlowPluginsTs/CommunityFlowTemplates/video/basicVideoMigz.ts b/FlowPluginsTs/CommunityFlowTemplates/video/basicVideoMigz.ts new file mode 100644 index 000000000..c57274688 --- /dev/null +++ b/FlowPluginsTs/CommunityFlowTemplates/video/basicVideoMigz.ts @@ -0,0 +1,180 @@ +/* eslint-disable no-template-curly-in-string */ +/* eslint-disable import/prefer-default-export */ + +import { IflowTemplate } from '../../FlowHelpers/1.0.0/interfaces/interfaces'; + +const details = () :IflowTemplate => ({ + name: 'Basic HEVC Video Flow - Migz 50%', + description: 'Basic HEVC video flow which uses the Migz GPU (NVENC) ' + + 'and Migz CPU plugins to aim for 50% file size reduction.', + tags: '', + flowPlugins: [ + { + name: 'Input File', + sourceRepo: 'Community', + pluginName: 'inputFile', + version: '1.0.0', + id: 'pE6rU7gkW', + position: { + x: 605.6174844367866, + y: 91.61529256488166, + }, + }, + { + name: 'Check if hevc', + sourceRepo: 'Community', + pluginName: 'checkVideoCodec', + version: '1.0.0', + id: '91b7IrsEc', + position: { + x: 605.9056229600291, + y: 192.7915128738341, + }, + }, + { + name: 'Replace Original File', + sourceRepo: 'Community', + pluginName: 'replaceOriginalFile', + version: '1.0.0', + id: '4fkfOyR3l', + position: { + x: 616.6829422267598, + y: 723.4017566509596, + }, + }, + { + name: 'Run Classic Transcode Plugin: Migz GPU', + sourceRepo: 'Community', + pluginName: 'runClassicTranscodePlugin', + version: '2.0.0', + id: 'QaMarr7U2', + position: { + x: 277.3652089704872, + y: 482.2580996510953, + }, + }, + { + name: 'Check Flow Variable: Worker Type', + sourceRepo: 'Community', + pluginName: 'checkFlowVariable', + version: '1.0.0', + id: 'R3SsqA2R2', + position: { + x: 388.92513564303005, + y: 265.27914587528255, + }, + inputsDB: { + variable: '{{{args.workerType}}}', + value: 'transcodegpu', + }, + }, + { + name: 'Run Classic Transcode Plugin: Migz CPU', + sourceRepo: 'Community', + pluginName: 'runClassicTranscodePlugin', + version: '2.0.0', + id: 'vML4LnVoU', + position: { + x: 480.1963619411388, + y: 479.8508686675832, + }, + inputsDB: { + pluginSourceId: 'Community:Tdarr_Plugin_MC93_Migz1FFMPEG_CPU', + }, + }, + { + name: 'Check Node Hardware Encoder', + sourceRepo: 'Community', + pluginName: 'checkNodeHardwareEncoder', + version: '1.0.0', + id: 'nXh1BK3js', + position: { + x: 302.73826398477604, + y: 373.54857265752986, + }, + }, + ], + flowEdges: [ + { + source: 'pE6rU7gkW', + sourceHandle: '1', + target: '91b7IrsEc', + targetHandle: null, + id: 'HhF4rw2DZ', + }, + { + source: '91b7IrsEc', + sourceHandle: '1', + target: '4fkfOyR3l', + targetHandle: null, + id: 'W2nVG7ts5', + }, + { + source: '91b7IrsEc', + sourceHandle: '2', + target: 'R3SsqA2R2', + targetHandle: null, + id: 'xZsf8IwDg', + }, + { + source: 'R3SsqA2R2', + sourceHandle: '2', + target: 'vML4LnVoU', + targetHandle: null, + id: 'RWv471I6E', + }, + { + source: 'QaMarr7U2', + sourceHandle: '1', + target: '4fkfOyR3l', + targetHandle: null, + id: 'CEk8bEYqP', + }, + { + source: 'QaMarr7U2', + sourceHandle: '2', + target: '4fkfOyR3l', + targetHandle: null, + id: 'vsKLZM4zM', + }, + { + source: 'vML4LnVoU', + sourceHandle: '1', + target: '4fkfOyR3l', + targetHandle: null, + id: 'vnP8TvN2d', + }, + { + source: 'vML4LnVoU', + sourceHandle: '2', + target: '4fkfOyR3l', + targetHandle: null, + id: '-KMkJCTg3', + }, + { + source: 'R3SsqA2R2', + sourceHandle: '1', + target: 'nXh1BK3js', + targetHandle: null, + id: 'vfT4o_4G6', + }, + { + source: 'nXh1BK3js', + sourceHandle: '1', + target: 'QaMarr7U2', + targetHandle: null, + id: 'eADOkFsGe', + }, + { + source: 'nXh1BK3js', + sourceHandle: '2', + target: 'vML4LnVoU', + targetHandle: null, + id: 'Blu0QflQK', + }, + ], +}); + +export { + details, +}; diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/classicPlugins.ts b/FlowPluginsTs/FlowHelpers/1.0.0/classicPlugins.ts index 00c89773e..ca6a0eb01 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/classicPlugins.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/classicPlugins.ts @@ -1,8 +1,9 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { getContainer, getFileName, getPluginWorkDir, getScanTypes, } from './fileUtils'; import { IpluginInputArgs } from './interfaces/interfaces'; +import { IFileObject } from './interfaces/synced/IFileObject'; export interface IrunClassicPlugin { result:{ @@ -42,7 +43,7 @@ export const runClassicPlugin = async (args:IpluginInputArgs, type:'filter'|'tra let pluginSrcStr = ''; if (pluginSource === 'Community') { classicPlugin = args.deps.importFresh(relativePluginPath); - pluginSrcStr = await fs.readFile(absolutePath, 'utf8'); + pluginSrcStr = await fsp.readFile(absolutePath, 'utf8'); } else { // eslint-disable-next-line no-await-in-loop const res = await args.deps.axiosMiddleware('api/v2/read-plugin', { @@ -90,25 +91,41 @@ export const runClassicPlugin = async (args:IpluginInputArgs, type:'filter'|'tra const scanTypes = getScanTypes([pluginSrcStr]); - const pluginInputFileObj = await args.deps.axiosMiddleware('api/v2/scan-individual-file', { - file: { - _id: args.inputFileObj._id, - file: args.inputFileObj.file, - DB: args.inputFileObj.DB, - footprintId: args.inputFileObj.footprintId, - }, - scanTypes, - }); - - const originalLibraryFile = await args.deps.axiosMiddleware('api/v2/scan-individual-file', { - file: { - _id: args.originalLibraryFile._id, - file: args.originalLibraryFile.file, - DB: args.originalLibraryFile.DB, - footprintId: args.originalLibraryFile.footprintId, - }, - scanTypes, - }); + let pluginInputFileObj:IFileObject; + let originalLibraryFile:IFileObject; + + const inputFileScanArgs = { + _id: args.inputFileObj._id, + file: args.inputFileObj.file, + DB: args.inputFileObj.DB, + footprintId: args.inputFileObj.footprintId, + }; + + const originalLibraryFileScanArgs = { + _id: args.originalLibraryFile._id, + file: args.originalLibraryFile.file, + DB: args.originalLibraryFile.DB, + footprintId: args.originalLibraryFile.footprintId, + }; + + // added in 2.19.01 + if (typeof args.scanIndividualFile !== 'undefined') { + args.jobLog('Scanning files using Node'); + pluginInputFileObj = await args.scanIndividualFile(inputFileScanArgs, scanTypes); + originalLibraryFile = await args.scanIndividualFile(originalLibraryFileScanArgs, scanTypes); + } else { + args.jobLog('Scanning files using Server API'); + + pluginInputFileObj = await args.deps.axiosMiddleware('api/v2/scan-individual-file', { + file: inputFileScanArgs, + scanTypes, + }); + + originalLibraryFile = await args.deps.axiosMiddleware('api/v2/scan-individual-file', { + file: originalLibraryFileScanArgs, + scanTypes, + }); + } const otherArguments = { handbrakePath: args.handbrakePath, @@ -132,11 +149,11 @@ export const runClassicPlugin = async (args:IpluginInputArgs, type:'filter'|'tra ); if (result?.file?._id && args.inputFileObj._id !== result.file._id) { + args.jobLog(`File ID changed from ${args.inputFileObj._id} to ${result.file._id}`); // eslint-disable-next-line no-param-reassign args.inputFileObj._id = result.file._id; // eslint-disable-next-line no-param-reassign args.inputFileObj.file = result.file.file; - args.jobLog(`File ID changed from ${args.inputFileObj._id} to ${result.file._id}`); } return { diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/cliParsers.ts b/FlowPluginsTs/FlowHelpers/1.0.0/cliParsers.ts index 4c9bded30..1429e744e 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/cliParsers.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/cliParsers.ts @@ -39,6 +39,28 @@ const handbrakeParser = ({ return percentage; }; +const getHandBrakeFps = ({ + str, +}: { + str: string, +}): number => { + try { + if (typeof str !== 'string' || !(str.includes('(') && str.includes('fps'))) { + return 0; + } + + const out = parseInt(str.split('(')[1].split('fps')[0].trim(), 10); + + // eslint-disable-next-line no-restricted-globals + if (!isNaN(out)) { + return out; + } + } catch (err) { + // err + } + return 0; +}; + // frame= 889 fps=106 q=26.0 Lsize= 25526kB time=00:00:35.69 bitrate=5858.3kbits/s speed=4.25x const getFFmpegVar = ({ str, @@ -227,5 +249,6 @@ export { ffmpegParser, getFFmpegPercentage, getFFmpegVar, + getHandBrakeFps, editreadyParser, }; diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts b/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts index fcd074a37..ac0cf9e18 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/cliUtils.ts @@ -1,8 +1,10 @@ -import { editreadyParser, ffmpegParser, handbrakeParser } from './cliParsers'; -import { Ilog, IupdateWorker } from './interfaces/interfaces'; +import fs from 'fs'; +import { + editreadyParser, ffmpegParser, getHandBrakeFps, handbrakeParser, +} from './cliParsers'; +import { Ilog, IpluginInputArgs, IupdateWorker } from './interfaces/interfaces'; import { IFileObject, Istreams } from './interfaces/synced/IFileObject'; - -const fs = require('fs'); +import { fileExists } from './fileUtils'; const fancyTimeFormat = (time: number) => { // Hours, minutes and seconds @@ -69,6 +71,7 @@ interface Iconfig { updateWorker: IupdateWorker, logFullCliOutput: boolean, inputFileObj: IFileObject, + args: IpluginInputArgs, } class CLI { @@ -87,11 +90,18 @@ 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; } - updateETA = (perc: number): void => { + updateETA = async (perc: number): Promise => { if (perc > 0) { if (this.lastProgCheck === 0) { this.lastProgCheck = new Date().getTime(); @@ -123,9 +133,11 @@ class CLI { let outputFileSizeInGbytes; try { - if (fs.existsSync(this.config.outputFilePath)) { + if (await fileExists(this.config.outputFilePath)) { let singleFileSize = fs.statSync(this.config.outputFilePath); + // @ts-expect-error type singleFileSize = singleFileSize.size; + // @ts-expect-error type outputFileSizeInGbytes = singleFileSize / (1024 * 1024 * 1024); if (outputFileSizeInGbytes !== this.oldOutSize) { @@ -152,6 +164,60 @@ 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; + // @ts-expect-error must exist to be here + this.config.args.variables.liveSizeCompare.error = 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); + } + } + } + } } } } @@ -177,11 +243,21 @@ class CLI { }); if (percentage > 0) { - this.updateETA(percentage); + void this.updateETA(percentage); this.config.updateWorker({ percentage, }); } + + const fps = getHandBrakeFps({ + str, + }); + + if (fps > 0) { + this.config.updateWorker({ + fps, + }); + } } else if (this.config.cli.toLowerCase().includes('ffmpeg')) { const n = str.indexOf('fps'); const shouldUpdate = str.length >= 6 && n >= 6; @@ -223,7 +299,7 @@ class CLI { } if (percentage > 0) { - this.updateETA(percentage); + void this.updateETA(percentage); this.config.updateWorker({ percentage, }); @@ -233,7 +309,7 @@ class CLI { str, }); if (percentage > 0) { - this.updateETA(percentage); + void this.updateETA(percentage); this.config.updateWorker({ percentage, }); @@ -241,8 +317,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', @@ -251,14 +326,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 } @@ -275,15 +350,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'); @@ -295,55 +367,64 @@ 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(1, `Error executing binary: ${this.config.cli}`); + console.log(`Error executing binary: ${this.config.cli}`); + this.config.jobLog(`Error executing binary: ${this.config.cli}`); resolve(1); }); // 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(code, 'CLI error'); + console.log(`CLI error code: ${code}`); + this.config.jobLog(`CLI error code: ${code}`); } resolve(code); }); } catch (err) { // catches execution error (no file) // eslint-disable-next-line no-console - console.log(1, `Error executing binary: ${this.config.cli}`); + console.log(`Error executing binary: ${this.config.cli}: ${err}`); + this.config.jobLog(`Error executing binary: ${this.config.cli}: ${err}`); resolve(1); } }); 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; + } + + this.config.jobLog(`CLI ${this.config.cli} exited with code: ${cliExitCode}`); + return { cliExitCode, errorLogFull, diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/fileMoveOrCopy.ts b/FlowPluginsTs/FlowHelpers/1.0.0/fileMoveOrCopy.ts index d3a487153..809d55889 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/fileMoveOrCopy.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/fileMoveOrCopy.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { getFileSize } from './fileUtils'; import { IpluginInputArgs } from './interfaces/interfaces'; @@ -48,7 +48,7 @@ const tryMove = async ({ let error = false; try { - await fs.rename(sourcePath, destinationPath); + await fsp.rename(sourcePath, destinationPath); } catch (err) { error = true; args.jobLog(`File move error: ${JSON.stringify(err)}`); @@ -157,7 +157,7 @@ const tryNormalCopy = async ({ let error = false; try { - await fs.copyFile(sourcePath, destinationPath); + await fsp.copyFile(sourcePath, destinationPath); } catch (err) { error = true; args.jobLog(`File copy error: ${JSON.stringify(err)}`); @@ -186,7 +186,7 @@ const cleanSourceFile = async ({ }) => { try { args.jobLog(`Deleting source file ${sourcePath}`); - await fs.unlink(sourcePath); + await fsp.unlink(sourcePath); } catch (err) { args.jobLog(`Failed to delete source file ${sourcePath}: ${JSON.stringify(err)}`); } diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/fileUtils.ts b/FlowPluginsTs/FlowHelpers/1.0.0/fileUtils.ts index a7f4cfeba..d06e5b25b 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/fileUtils.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/fileUtils.ts @@ -1,6 +1,8 @@ -import { promises as fs } from 'fs'; +import { promises as fsp } from 'fs'; import { IpluginInputArgs } from './interfaces/interfaces'; +export const fileExists = async (path:string): Promise => !!(await fsp.stat(path).catch(() => false)); + export const getContainer = (filePath: string): string => { const parts = filePath.split('.'); return parts[parts.length - 1]; @@ -37,7 +39,7 @@ export const getSubStem = ({ }; export const getFileSize = async (file:string):Promise => { - const stats = await fs.stat(file); + const stats = await fsp.stat(file); const { size } = stats; return size; }; diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/flowUtils.ts b/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/flowUtils.ts new file mode 100644 index 000000000..73291a823 --- /dev/null +++ b/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/flowUtils.ts @@ -0,0 +1,14 @@ +import { IpluginInputArgs } from './interfaces'; + +// eslint-disable-next-line import/prefer-default-export +export const checkFfmpegCommandInit = (args: IpluginInputArgs): void => { + if (!args?.variables?.ffmpegCommand?.init) { + throw new Error( + 'FFmpeg command plugins not used correctly.' + + ' Please use the "Begin Command" plugin before using this plugin.' + + ' Afterwards, use the "Execute" plugin to execute the built FFmpeg command.' + + ' Once the "Execute" plugin has been used, you need to use a new "Begin Command"' + + ' plugin to start a new FFmpeg command.', + ); + } +}; diff --git a/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts b/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts index efb4c3685..490d3e962 100644 --- a/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts +++ b/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts @@ -1,4 +1,5 @@ -import { IFileObject, Istreams } from './synced/IFileObject'; +import { IscanTypes } from '../fileUtils'; +import { IFileObject, IFileObjectMin, Istreams } from './synced/IFileObject'; import Ijob from './synced/jobInterface'; export interface IpluginInputUi { @@ -86,6 +87,7 @@ export interface IffmpegCommandStream extends Istreams { } export interface IffmpegCommand { + init: boolean, inputFiles: string[], streams: IffmpegCommandStream[] container: string, @@ -95,10 +97,21 @@ export interface IffmpegCommand { overallOuputArguments: string[], } +export interface IliveSizeCompare { + enabled: boolean, + compareMethod: string, + thresholdPerc: number, + checkDelaySeconds: number, + error: boolean, +} + export interface Ivariables { ffmpegCommand: IffmpegCommand, flowFailed: boolean, user: Record, + healthCheck?: 'Success', + queueTags?: string, + liveSizeCompare?: IliveSizeCompare } export interface IpluginOutputArgs { @@ -124,6 +137,7 @@ export interface IpluginInputArgs { originalLibraryFile: IFileObject, nodeHardwareType: string, workerType: string, + nodeTags?: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any config: any, job: Ijob, @@ -136,6 +150,8 @@ export interface IpluginInputArgs { updateWorker: IupdateWorker, logFullCliOutput: boolean, logOutcome: (outcome: string) => void, + scanIndividualFile?: (filee: IFileObjectMin, scanTypes: IscanTypes) => Promise, + updateStat: (db: string, key: string, inc: number) => Promise, deps: { // eslint-disable-next-line @typescript-eslint/no-explicit-any fsextra: any, diff --git a/examples/Tdarr_Plugin_a9he_New_file_size_check.js b/examples/Tdarr_Plugin_a9he_New_file_size_check.js index b5531716c..665fc2d05 100644 --- a/examples/Tdarr_Plugin_a9he_New_file_size_check.js +++ b/examples/Tdarr_Plugin_a9he_New_file_size_check.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_a9he_New_file_size_check', Stage: 'Pre-processing', - Name: 'New file size check', + Name: 'New File Size Check', Type: 'Video', Operation: 'Transcode', Description: 'Give an error if new file is larger than the original \n\n', diff --git a/examples/Tdarr_Plugin_f001_Filter_Example.js b/examples/Tdarr_Plugin_f001_Filter_Example.js index d6be88258..32e1f3e83 100644 --- a/examples/Tdarr_Plugin_f001_Filter_Example.js +++ b/examples/Tdarr_Plugin_f001_Filter_Example.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_f001_Filter_Example', Stage: 'Pre-processing', - Name: 'Filter keywords ', + Name: 'Filter Keywords', Type: 'Video', Operation: 'Filter', Description: 'This plugin prevents processing files which contain keywords \n\n', diff --git a/examples/Tdarr_Plugin_f002_Filter_Example.js b/examples/Tdarr_Plugin_f002_Filter_Example.js index 5a1961bbf..fa42b5e91 100644 --- a/examples/Tdarr_Plugin_f002_Filter_Example.js +++ b/examples/Tdarr_Plugin_f002_Filter_Example.js @@ -1,7 +1,7 @@ const details = () => ({ id: 'Tdarr_Plugin_f002_Filter_Example', Stage: 'Pre-processing', - Name: 'Filter resolutions', + Name: 'Filter Resolutions', Type: 'Video', Operation: 'Filter', Description: 'This plugin prevents processing files with specified resolutions \n\n', diff --git a/examples/Tdarr_Plugin_pos1_Post_Proc_Example.js b/examples/Tdarr_Plugin_pos1_Post_Proc_Example.js index 492fabc74..94f288e4c 100644 --- a/examples/Tdarr_Plugin_pos1_Post_Proc_Example.js +++ b/examples/Tdarr_Plugin_pos1_Post_Proc_Example.js @@ -14,7 +14,7 @@ module.exports.dependencies = [ const details = () => ({ id: 'Tdarr_Plugin_pos1_Post_Proc_Example', Stage: 'Post-processing', // Preprocessing or Post-processing. Determines when the plugin will be executed. This plugin does some stuff after all plugins have been executed - Name: 'Post proc ', + Name: 'Post Proc', Type: 'Video', Operation: 'Transcode', Description: 'This plugin does some stuff after all plugins have been executed. \n\n', diff --git a/examples/Tdarr_Plugin_pre1_Pre_Proc_Example.js b/examples/Tdarr_Plugin_pre1_Pre_Proc_Example.js index 76efd68fe..a1f9bf005 100644 --- a/examples/Tdarr_Plugin_pre1_Pre_Proc_Example.js +++ b/examples/Tdarr_Plugin_pre1_Pre_Proc_Example.js @@ -14,7 +14,7 @@ module.exports.dependencies = [ const details = () => ({ id: 'Tdarr_Plugin_pre1_Pre_Proc_Example', Stage: 'Pre-processing', // Pre-processing or Post-processing. Determines when the plugin will be executed. - Name: 'No title meta data ', + Name: 'No Title Meta Data', Type: 'Video', Operation: 'Transcode', Description: 'This plugin removes metadata (if a title exists). The output container is the same as the original. \n\n', diff --git a/tests/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js b/tests/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js index b4105a4ec..9d4f85ee5 100644 --- a/tests/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js +++ b/tests/Community/Tdarr_Plugin_00td_action_handbrake_ffmpeg_custom.js @@ -61,6 +61,27 @@ const tests = [ infoLog: 'File is being transcoded using custom arguments \n', }, }, + { + input: { + file: require('../sampleData/media/sampleH264_1.json'), + librarySettings: {}, + inputs: { + cli: 'ffmpeg', + arguments: '-c:v libx265 -crf 23 -ac 6 -c:a aac -preset veryfast', + container: 'original', + }, + otherArguments: {}, + }, + output: { + processFile: true, + preset: '-c:v libx265 -crf 23 -ac 6 -c:a aac -preset veryfast', + container: '.mp4', + handbrakeMode: false, + ffmpegMode: true, + reQueueAfter: true, + infoLog: 'File is being transcoded using custom arguments \n', + }, + }, ]; void run(tests); diff --git a/tests/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js b/tests/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js index 1457d044d..b397f1c64 100644 --- a/tests/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js +++ b/tests/Community/Tdarr_Plugin_00td_action_remove_stream_by_specified_property.js @@ -217,6 +217,30 @@ const tests = [ + ' Files has streams which need to be removed, processing \n', }, }, + + { + input: { + file: _.cloneDeep(require('../sampleData/media/sampleH264_2.json')), + librarySettings: {}, + inputs: { + propertyToCheck: 'CodecID', + valuesToRemove: 'A_AAC-2,S_TEXT/UTF8', + }, + otherArguments: {}, + }, + output: { + processFile: true, + preset: ', -map 0 -c copy -max_muxing_queue_size 9999 -map -0:4 -map -0:5 -map -0:6 ', + container: '.mkv', + handBrakeMode: false, + FFmpegMode: true, + reQueueAfter: false, + infoLog: ' Removing stream 4 which is has CodecID of undefined \n' + + ' Removing stream 5 which is has CodecID of undefined \n' + + ' Removing stream 6 which is has CodecID of undefined \n' + + ' Files has streams which need to be removed, processing \n', + }, + }, ]; void run(tests); diff --git a/tests/checkPlugins.js b/tests/checkPlugins.js index c98e96eca..7abc19a9d 100644 --- a/tests/checkPlugins.js +++ b/tests/checkPlugins.js @@ -122,6 +122,13 @@ module.exports.plugin = plugin;`; errorEncountered = true; } + console.log(files[i]); + // check if words in pluginDetails.Name are not capitalized + if (pluginDetails.Name.split(' ').some((word) => word[0] !== word[0].toUpperCase())) { + console.log(chalk.red(`Plugin Name is not capitalized '${folder}/${files[i]}'`)); + errorEncountered = true; + } + if (!['Pre-processing', 'Post-processing'].includes(pluginDetails.Stage)) { console.log(chalk.red(`Plugin does not have a valid Type'${folder}/${files[i]}'`)); errorEncountered = true;