From baa6d2fd5c1852531b1547488dcd4de22a15ec4d Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 7 Feb 2020 00:33:42 +0100 Subject: [PATCH 01/15] Stage: "Pre-processing" added --- Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js index c4ba044..373d420 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js @@ -4,6 +4,7 @@ const execSync = require('child_process').execSync; function details() { return { id: "Tdarr_Plugin_e5c3_CnT_Add_Subtitles", + Stage: "Pre-processing", Name: "Add subtitles to MKV files", Type: "Video", Operation:"Remux", From 52f50ffc2c097f31603a219b87cc816cd0ba21c0 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 7 Feb 2020 00:35:53 +0100 Subject: [PATCH 02/15] Stage: "Pre-processing" added --- Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js index 2c80b8c..6e72d7d 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js @@ -4,6 +4,7 @@ const fs = require('fs'); function details() { return { id: "Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio", + Stage: "Pre-processing", Name: "Keep Preffered Audio", Type: "Video", Operation:"Remove Audio", From 8799c6ab5b75b071065ec5025a05ef0dd3acc84d Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 7 Feb 2020 00:38:13 +0100 Subject: [PATCH 03/15] Tdarr_Plugin_e5c3_CnT_Remove_Letterbox Uses iiDrakeii's filter, and crops video files when letterboxing is detected. This uses the FFMPEG NVENC transcoding(hw). If a file is 4K it will be scaled down to 1080p. Now with user definable bitrates!(since 1.104 beta) --- .../Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js | 394 ++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js new file mode 100644 index 0000000..9657947 --- /dev/null +++ b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js @@ -0,0 +1,394 @@ +const fs = require('fs'); +const execSync = require('child_process').execSync; + +function details() { + return { + id: "Tdarr_Plugin_e5c3_CnT_Remove_Letterbox", + Stage: "Pre-processing", + 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`, + Version: "1.2", + Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js", + Inputs: [ + { + name: 'bitrate', + tooltip: `Desired bitrate for a 1080p video, minimum transcode size is based of this too!\n 720p will be half of 1080p, 480p will be half of 720p.\nThe default is '3000', this value is based of movies.\nI would suggest 1500-2000 for series.` + }, + ] + } +} + +function plugin(file, librarySettings, inputs) { + console.log(inputs.bitrate); + if (inputs.bitrate == "") { + var min_bitrate = 6600; + var avg_rate = 3000; + var max_rate = 6000; + } else { + var min_bitrate = inputs.bitrate*2.2; + var avg_rate = inputs.bitrate; + var max_rate = inputs.bitrate*2; + } + + + var source = file.meta.SourceFile; //source file + var dir = file.meta.Directory; //source directory + var sourcename = file.meta.FileName.substring(0, file.meta.FileName.lastIndexOf(".")); //filename without extension + var cropfile = `${dir}/${sourcename}.txt`; //location and name of the crop file + var min_crop = parseInt(file.meta.ImageHeight*.98); //if the crop value is larger than this the file won't be cropped + var duration = file.meta.Duration; //duration of video in seconds + var stats = fs.statSync(source); + var size = stats["size"]/1000000000; + size = size.toFixed(2); + var decoder = decoder_string(file); //decoder, before the input + var encoder = encoder_string_full(file, highres(file), crop_decider(file, create_crop_values(file).crop_height).crop, avg_rate, max_rate); //encoder + var process = 0; //decides if it should be processed + + //default values that will be returned + var response = { + processFile: false, + preset: '', + container: '.mkv', + handBrakeMode: false, + FFmpegMode: false, + reQueueAfter: true, + infoLog: '' + } + + var returns = { + create_crop: create_crop_values(file), + crop: crop_decider(file, create_crop_values(file).crop_height), + size: size_check(file, min_bitrate) + } + + var transcode = { + hevc: hevc(file), //if it's not hevc it will be processed, unless file size is too small + highres: highres(file) //changes to '1' if it's 4k, it should be transcoded to 1080p + } + + var log = { + size: returns.size.log, + hevc: ``, + resolution: ``, + crop: returns.crop.log, + createcrop: returns.create_crop.log + } + + //check if the file is a video + //if (file.fileMedium !== "video") { + // response.infoLog += `☒ - File is not a video \n` + // return response; + //} else { + // response.infoLog += `☑ - File is a video \n` + //} + + //filters + if (size_check(file, min_bitrate).size == 1) { + if (hevc(file) == 1) { + process = 1; + log.hevc = `☑ - Video is not HEVC \n`; + } else { + log.hevc += "☒ - File is already in HEVC \n" + } + + if (highres(file) == 1) { + process = 1; + log.resolution += `☑ - Resolution > 1080p.\n File will be transcoded to 1080p \n`; + } else { + log.resolution += `☒ - Resolution <= 1080p \n`; + } + + if (crop_decider(file, create_crop_values(file).crop_height).crop != "0") { + process = 1; + } + } + + response.infoLog += log.createcrop + + log.crop + + log.resolution + + log.size + + log.hevc; + + //change response + if (process == 1) { + response.processFile = true; + response.FFmpegMode = true; + response.infoLog += `File will be processed\n`; + response.preset = `${decoder}, -map 0:v:0 -map 0:a -map 0:s? ${encoder}` + response.reQueueAfter = true; + } else { + response.infoLog += `Processing not necessary\n`; + } + + return response; +} + +function highres(file) { + //if file is larger than 1080p it should be transcoded + if (file.meta.ImageWidth > 1920) { + return 1; + } else { + return 0; + } +} + +function create_crop_values(file) { + var source = file.meta.SourceFile; //source file + var dir = file.meta.Directory; //source directory + var sourcename = file.meta.FileName.substring(0, file.meta.FileName.lastIndexOf(".")); //filename without extension + var cropfile = `${dir}/${sourcename}.txt`; //location and name of the crop file + var returns = { + crop_height: 0, //return value for this function, required for crop_decider + log: `` + } + //delete old crop value if it exists + //if (fs.existsSync(`${cropfile}`)) { + // returns.log += `removing old cropvalues...\n`; + // fs.unlinkSync(`${cropfile}`); + //} + + //create crop value + if (!fs.existsSync(`${cropfile}`)) { + returns.log += `Creating crop values...\n`; + execSync(`ffmpeg -ss 300 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 > \"${cropfile}\"`); + execSync(`ffmpeg -ss 1200 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 >> \"${cropfile}\"`); + //get data from copvalue.txt + var data = fs.readFileSync(`${cropfile}`).toString().split("\n"); //full data from cropvalue.txt + //get height of the supposed cropped video + //var crop_height = parseInt(data[0].substring(10, 14)); + + for (var c = 0; c < data.length; c++) { + if (parseInt(data[c].substring(10, 14)) > returns.crop_height) { + returns.crop_height = parseInt(data[c].substring(10, 14)); + returns.log += `New cropheight: ${parseInt(data[c].substring(10, 14))}\n`; + } + } + } else { + returns.log += `Crop values already exist\n`; + + var data = fs.readFileSync(`${cropfile}`).toString().split("\n"); //full data from cropvalue.txt + //get height of the supposed cropped video + //var crop_height = parseInt(data[0].substring(10, 14)); + + for (var c = 0; c < data.length; c++) { + if (parseInt(data[c].substring(10, 14)) > returns.crop_height) { + returns.crop_height = parseInt(data[c].substring(10, 14)); + returns.log += `New cropheight: ${parseInt(data[c].substring(10, 14))}\n`; + } + } + } + + return returns; +} + +function hevc(file) { + //check if the file is already hevc, it will not be transcoded if true + if ("hevc".toLowerCase().includes(file.ffProbeData.streams[0].codec_name.toLowerCase())) { + return 0; + } else { + return 1; + } +} + +function decoder_string(file) { + var decoder = ``; //decoder, before the input + + //use the correct decoder + if (file.video_codec_name == 'h263') { + decoder = `-c:v h263_cuvid` + } + else if (file.video_codec_name == 'h264') { + if (file.ffProbeData.streams[0].profile != 'High 10') { //Remove HW Decoding for High 10 Profile + decoder = `-c:v h264_cuvid` + } + } + else if (file.video_codec_name == 'mjpeg') { + decoder = `c:v mjpeg_cuvid` + } + else if (file.video_codec_name == 'mpeg1') { + decoder = `-c:v mpeg1_cuvid` + } + else if (file.video_codec_name == 'mpeg2') { + decoder = `-c:v mpeg2_cuvid` + } + else if (file.video_codec_name == 'vc1') { + decoder = `-c:v vc1_cuvid` + } + else if (file.video_codec_name == 'vp8') { + decoder = `-c:v vp8_cuvid` + } + else if (file.video_codec_name == 'vp9') { + decoder = `-c:v vp9_cuvid` + } + + return decoder; +} + +function crop_decider(file, crop_height) { + var min_crop = parseInt(file.meta.ImageHeight*.98); //if the crop value is larger than this the file won't be cropped + var returns = { + crop: `0`, //sets the crop filter + log: ``, + } + + //tree for resolution : quality + if (file.meta.ImageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) + //crop only if it is a larger crop than 1%; + if (crop_height < min_crop) { + var crop_hdis = parseInt((file.meta.ImageHeight-crop_height)/2); + if (crop_height >= 790) { + returns.crop = `-filter:0 crop=1920:${crop_height}:0:${crop_hdis}`; + returns.log += `☑ - crop is larger than 1%\n`; + } + } else { + returns.log += `☒ - Crop is not necessary\n`; + } + } else if(file.meta.ImageWidth < 1300 && file.meta.ImageWidth >= 770) { + //crop only if it is a larger crop than 1%; + if (crop_height < min_crop) { + var crop_hdis = parseInt((file.meta.ImageHeight-crop_height)/2); + if (crop_height >= 530) { + returns.crop = `-filter:0 crop=1280:${crop_height}:0:${crop_hdis}`; + returns.log += `☑ - crop is larger than 1%\n`; + } + } else { + returns.log += `☒ - Crop is not necessary\n`; + } + } else if(file.meta.ImageWidth < 770) { //file won't be cropped at this resolution + returns.log += `No crop: Resolution < 720p\n`; + } + + return returns; +} + +function size_check(file, min_bitrate) { + var duration = file.meta.Duration; //duration of video in seconds + var source = file.meta.SourceFile; //source file + var stats = fs.statSync(source); + var size = stats["size"]/1000000000; + size = size.toFixed(2); + var returns = { + size: 0, + log: `` + } + + //tree for resolution : quality + if (file.meta.ImageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) + var min_transcode_size = (min_bitrate * duration * 0.125)/1000000; //minimum size in GB for transcode + min_transcode_size = min_transcode_size.toFixed(2); + + console.log(min_bitrate) + + //check if file is large enough for transcode + if (size >= (min_bitrate * duration * 0.125)/1000000) { + returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`; + returns.size = 1; + } else { + returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; + } + } else if(file.meta.ImageWidth < 1300 && file.meta.ImageWidth >= 770) { //file will be encoded if the resolution is 720p + var min_transcode_size = ((min_bitrate/2) * duration * 0.125)/1000000; //minimum size in GB for transcode + min_transcode_size = min_transcode_size.toFixed(2); + + //check if file is large enough for transcode + if (size >= ((min_bitrate/2) * duration * 0.125)/1000000) { + returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`; + returns.size = 1; + } else { + returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; + } + } else if(file.meta.ImageWidth < 770) { //file will be encoded if the resolution is 480p or 576p + var min_transcode_size = ((min_bitrate/4) * duration * 0.125)/1000000; //minimum size in GB for transcode + min_transcode_size = min_transcode_size.toFixed(2); + + //check if file is large enough for transcode + if (size >= ((min_bitrate/4) * duration * 0.125)/1000000) { + returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`; + returns.size = 1; + } else { + returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; + } + } + + return returns; +} + +function error_fix(file) { + var fix = { + sub_codec: 0, //changes to 1 if unwanted codec is found + muxing: 0 + } + + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + + //these subtitle codecs don't fit in a mkv container + if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "eia_608" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase.includes("sub")) { + fix.sub_codec = 1; + } + + //mitigate TrueHD audio causing Too many packets error + if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "truehd" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "dts" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" ) { + fix.muxing = 1; + } + + } + + return fix; +} + +function encoder_string(file, avg_rate, max_rate) { + var encoder = ``; //encoder + var fix = error_fix(file); + var sub = ``; + + console.log(avg_rate); + + //tree for resolution : quality + if (file.meta.ImageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) + encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate}k -maxrate:v ${max_rate}k`; //-qp 26 + } else if(file.meta.ImageWidth < 1300 && file.meta.ImageWidth >= 770) { //file will be encoded if the resolution is 720p + encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate/2}k -maxrate:v ${max_rate/2}k`; //-qp 28 + } else if(file.meta.ImageWidth < 770) { //file will be encoded if the resolution is 480p or 576p + encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate/4}k -maxrate:v ${max_rate/4}k`; //-qp 30 + } + encoder += ` -c:v hevc_nvenc -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -dn`; + + if (fix.sub_codec == 1) { + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "eia_608" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase().includes("sub")) { + sub += ` -c:${i} ass`; + } else { + if (file.ffProbeData.streams[i].codec_type.toLowerCase().includes("sub")) { + sub += ` -c:${i} copy`; + } + } + } + } else { + sub = ` -c:s copy` + } + + if (fix.muxing == 1) { + encoder += ` -max_muxing_queue_size 2048`; + } + + return encoder + ` -c:a copy` + sub; +} + +function encoder_string_full(file, highres, crop, avg_rate, max_rate) { + var encoder = encoder_string(file, avg_rate, max_rate); + + if (highres == 1 && crop != "0") { + return crop + `,scale=-1:1920 ` + encoder; + } else if (highres == 1) { + return `-filter:0 scale=-1:1920 ` + encoder; + } else if (crop != "0") { + return crop + encoder; + } else { + return encoder; + } +} + +module.exports.details = details; +module.exports.plugin = plugin; From 73a1ee0704ba3849153ecdf7e0c69a17bf15be9b Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 7 Feb 2020 00:39:06 +0100 Subject: [PATCH 04/15] Updated link --- Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js index 6e72d7d..4631388 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js @@ -10,7 +10,7 @@ function details() { Operation:"Remove Audio", Description: "Plugin that checks for unwanted audio, per 1.104 beta you can change the languages yourself from within Tdarr!\nUntill you enter a value it keep english tracks by default.\nUndefined languages are kept to prevent videos without sound.\nIf you would like to keep track of the languages you have for each file you can use the 'special' option.\nCreated by @control#0405", Version: "1.1", - Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_non_English_Audio.js", + Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js", Inputs: [ { name: 'languages', From 426227d8edd01350450b34b9a77d96a3811c57b5 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 7 Feb 2020 00:47:19 +0100 Subject: [PATCH 05/15] Updated inputs, iso-639-2 auto install on any OS Updated for 1.104 beta to support inputs. change install_packages to yes to automatically install the node_module that is required for this plugin. ISO-639-2 node module can now be installed on any system automatically! Only tested on Linux but should hypothetically work on other OS too. --- Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js index 373d420..89a5d70 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js @@ -125,8 +125,6 @@ function plugin(file, librarySettings, inputs, otherArguments) { response.infoLog += `No new subtitle languages were found\n`; } - //response.infoLog += `The ffmpeg string is: ${response.preset}\n` - return response } From 207ef9d42225dfbf3db8a0239df3fcbfc0079863 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 7 Feb 2020 01:05:07 +0100 Subject: [PATCH 06/15] updated link --- Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js index 4631388..a9e4568 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js @@ -30,8 +30,10 @@ function plugin(file, librarySettings, inputs, otherArguments) { } else { var languages = inputs.languages.split(','); //these languages should be kept, named according to ISO 639-2 language scheme } - if (inputs.special !== null) { + if (inputs.special !== "") { var special = inputs.special.split(','); + } else { + var special = ``; } if (languages.length >= special.length) { var length = languages.length; From f86d8c98fe15ae21b58fe3d4528d38d844eb129e Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 14 Feb 2020 10:26:54 +0100 Subject: [PATCH 07/15] Update Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js --- Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js index a9e4568..95c9ca4 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js @@ -11,6 +11,7 @@ function details() { Description: "Plugin that checks for unwanted audio, per 1.104 beta you can change the languages yourself from within Tdarr!\nUntill you enter a value it keep english tracks by default.\nUndefined languages are kept to prevent videos without sound.\nIf you would like to keep track of the languages you have for each file you can use the 'special' option.\nCreated by @control#0405", Version: "1.1", Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js", + Tags:'pre-processing,ffmpeg,audio only,configurable', Inputs: [ { name: 'languages', From e208cb8266ace1dca15e21cd5e82f61bd45f055e Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 14 Feb 2020 10:30:44 +0100 Subject: [PATCH 08/15] Tags --- Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js index 89a5d70..5ce10f7 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js @@ -11,6 +11,7 @@ function details() { 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`, Version: "1.3", Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js", + Tags:'pre-processing,ffmpeg,subtitle only,configurable', Inputs: [ { name: 'install_packages', From de2146e786f77561d4b0a1c3d6336db50ed605e4 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 14 Feb 2020 10:35:25 +0100 Subject: [PATCH 09/15] Added force processing and muxing for container force processing will make sure the file gets transcoded even if the filters don't match. It will still look at the resolution, the file won't be cropped. If the container doesn't match the preferred container and all filters already match it will be muxed to the desired container. --- .../Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js | 88 ++++++++++--------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js index 9657947..10c46dc 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js @@ -9,19 +9,22 @@ function details() { 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`, - Version: "1.2", + Version: "1.3", Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js", Inputs: [ { name: 'bitrate', - tooltip: `Desired bitrate for a 1080p video, minimum transcode size is based of this too!\n 720p will be half of 1080p, 480p will be half of 720p.\nThe default is '3000', this value is based of movies.\nI would suggest 1500-2000 for series.` + tooltip: `Desired bitrate for a 1080p video, minimum transcode size is based of this too!\\n 720p will be half of 1080p, 480p will be half of 720p.\\nThe default is '3000', this value is based of movies.\\nI would suggest 1500-2000 for series.\\nExample:\\n3000` + }, + { + name: 'container', + tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv` }, ] } } -function plugin(file, librarySettings, inputs) { - console.log(inputs.bitrate); +function plugin(file, librarySettings, inputs, otherArguments) { if (inputs.bitrate == "") { var min_bitrate = 6600; var avg_rate = 3000; @@ -31,14 +34,10 @@ function plugin(file, librarySettings, inputs) { var avg_rate = inputs.bitrate; var max_rate = inputs.bitrate*2; } - var source = file.meta.SourceFile; //source file var dir = file.meta.Directory; //source directory var sourcename = file.meta.FileName.substring(0, file.meta.FileName.lastIndexOf(".")); //filename without extension - var cropfile = `${dir}/${sourcename}.txt`; //location and name of the crop file - var min_crop = parseInt(file.meta.ImageHeight*.98); //if the crop value is larger than this the file won't be cropped - var duration = file.meta.Duration; //duration of video in seconds var stats = fs.statSync(source); var size = stats["size"]/1000000000; size = size.toFixed(2); @@ -52,10 +51,15 @@ function plugin(file, librarySettings, inputs) { preset: '', container: '.mkv', handBrakeMode: false, - FFmpegMode: false, + FFmpegMode: true, reQueueAfter: true, infoLog: '' } + + if (inputs.container !== undefined) { + response.container = inputs.container; + console.log(`Changed container to: ` + inputs.container); + } var returns = { create_crop: create_crop_values(file), @@ -63,11 +67,6 @@ function plugin(file, librarySettings, inputs) { size: size_check(file, min_bitrate) } - var transcode = { - hevc: hevc(file), //if it's not hevc it will be processed, unless file size is too small - highres: highres(file) //changes to '1' if it's 4k, it should be transcoded to 1080p - } - var log = { size: returns.size.log, hevc: ``, @@ -75,22 +74,14 @@ function plugin(file, librarySettings, inputs) { crop: returns.crop.log, createcrop: returns.create_crop.log } - - //check if the file is a video - //if (file.fileMedium !== "video") { - // response.infoLog += `☒ - File is not a video \n` - // return response; - //} else { - // response.infoLog += `☑ - File is a video \n` - //} //filters if (size_check(file, min_bitrate).size == 1) { if (hevc(file) == 1) { - process = 1; log.hevc = `☑ - Video is not HEVC \n`; } else { log.hevc += "☒ - File is already in HEVC \n" + process = 1; } if (highres(file) == 1) { @@ -110,14 +101,19 @@ function plugin(file, librarySettings, inputs) { log.resolution + log.size + log.hevc; + response.preset = `${decoder}, -map 0:v:0 -map 0:a -map 0:s? ${encoder}` //change response if (process == 1) { response.processFile = true; - response.FFmpegMode = true; response.infoLog += `File will be processed\n`; - response.preset = `${decoder}, -map 0:v:0 -map 0:a -map 0:s? ${encoder}` - response.reQueueAfter = true; + } else if (file.forceProcessing === true) { + response.processFile = true; + response.infoLog += `Force processing!\n`; + } else if (response.container !== `.` + file.container) { + response.infoLog += `Container is not correct\nMuxing to ${response.container}!\n`; + response.preset = `${decoder}, -c copy`; + response.processFile = true; } else { response.infoLog += `Processing not necessary\n`; } @@ -227,17 +223,25 @@ function decoder_string(file) { } function crop_decider(file, crop_height) { - var min_crop = parseInt(file.meta.ImageHeight*.98); //if the crop value is larger than this the file won't be cropped var returns = { crop: `0`, //sets the crop filter log: ``, } + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + if (file.ffProbeData.streams[i].width !== undefined) { + var imageWidth = file.ffProbeData.streams[i].width; + var imageHeight = file.ffProbeData.streams[i].height; + break; + } + } + var min_crop = parseInt(imageHeight*.98); //if the crop value is larger than this the file won't be cropped + //tree for resolution : quality - if (file.meta.ImageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) + if (imageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) //crop only if it is a larger crop than 1%; if (crop_height < min_crop) { - var crop_hdis = parseInt((file.meta.ImageHeight-crop_height)/2); + var crop_hdis = parseInt((imageHeight-crop_height)/2); if (crop_height >= 790) { returns.crop = `-filter:0 crop=1920:${crop_height}:0:${crop_hdis}`; returns.log += `☑ - crop is larger than 1%\n`; @@ -245,10 +249,10 @@ function crop_decider(file, crop_height) { } else { returns.log += `☒ - Crop is not necessary\n`; } - } else if(file.meta.ImageWidth < 1300 && file.meta.ImageWidth >= 770) { + } else if(imageWidth < 1300 && file.meta.ImageWidth >= 770) { //crop only if it is a larger crop than 1%; if (crop_height < min_crop) { - var crop_hdis = parseInt((file.meta.ImageHeight-crop_height)/2); + var crop_hdis = parseInt((imageHeight-crop_height)/2); if (crop_height >= 530) { returns.crop = `-filter:0 crop=1280:${crop_height}:0:${crop_hdis}`; returns.log += `☑ - crop is larger than 1%\n`; @@ -256,7 +260,7 @@ function crop_decider(file, crop_height) { } else { returns.log += `☒ - Crop is not necessary\n`; } - } else if(file.meta.ImageWidth < 770) { //file won't be cropped at this resolution + } else if(imageWidth < 770) { //file won't be cropped at this resolution returns.log += `No crop: Resolution < 720p\n`; } @@ -275,12 +279,10 @@ function size_check(file, min_bitrate) { } //tree for resolution : quality - if (file.meta.ImageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) + if (file.video_resolution === "1080p" || file.video_resolution === "4KUHD") { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) var min_transcode_size = (min_bitrate * duration * 0.125)/1000000; //minimum size in GB for transcode min_transcode_size = min_transcode_size.toFixed(2); - console.log(min_bitrate) - //check if file is large enough for transcode if (size >= (min_bitrate * duration * 0.125)/1000000) { returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`; @@ -288,7 +290,7 @@ function size_check(file, min_bitrate) { } else { returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; } - } else if(file.meta.ImageWidth < 1300 && file.meta.ImageWidth >= 770) { //file will be encoded if the resolution is 720p + } else if(file.video_resolution === "720p") { //file will be encoded if the resolution is 720p var min_transcode_size = ((min_bitrate/2) * duration * 0.125)/1000000; //minimum size in GB for transcode min_transcode_size = min_transcode_size.toFixed(2); @@ -299,7 +301,7 @@ function size_check(file, min_bitrate) { } else { returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; } - } else if(file.meta.ImageWidth < 770) { //file will be encoded if the resolution is 480p or 576p + } else if(file.video_resolution === "480p" || file.video_resolution === "576p") { //file will be encoded if the resolution is 480p or 576p var min_transcode_size = ((min_bitrate/4) * duration * 0.125)/1000000; //minimum size in GB for transcode min_transcode_size = min_transcode_size.toFixed(2); @@ -324,7 +326,7 @@ function error_fix(file) { for (var i = 0; i < file.ffProbeData.streams.length; i++) { //these subtitle codecs don't fit in a mkv container - if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "eia_608" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase.includes("sub")) { + if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "eia_608" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase.includes("sub") && response.container == '.mkv') { fix.sub_codec = 1; } @@ -343,14 +345,12 @@ function encoder_string(file, avg_rate, max_rate) { var fix = error_fix(file); var sub = ``; - console.log(avg_rate); - //tree for resolution : quality - if (file.meta.ImageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) + if (file.video_resolution === "1080p" || file.video_resolution === "4KUHD") { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate}k -maxrate:v ${max_rate}k`; //-qp 26 - } else if(file.meta.ImageWidth < 1300 && file.meta.ImageWidth >= 770) { //file will be encoded if the resolution is 720p + } else if(file.video_resolution === "720p") { //file will be encoded if the resolution is 720p encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate/2}k -maxrate:v ${max_rate/2}k`; //-qp 28 - } else if(file.meta.ImageWidth < 770) { //file will be encoded if the resolution is 480p or 576p + } else if(file.video_resolution === "480p" || file.video_resolution === "576p") { //file will be encoded if the resolution is 480p or 576p encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate/4}k -maxrate:v ${max_rate/4}k`; //-qp 30 } encoder += ` -c:v hevc_nvenc -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -dn`; @@ -379,6 +379,8 @@ function encoder_string(file, avg_rate, max_rate) { function encoder_string_full(file, highres, crop, avg_rate, max_rate) { var encoder = encoder_string(file, avg_rate, max_rate); + console.log(`crop filter: ` + crop) + if (highres == 1 && crop != "0") { return crop + `,scale=-1:1920 ` + encoder; } else if (highres == 1) { From 3d71c47c55f351dd851403f0f61a08165395ef03 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 14 Feb 2020 10:39:11 +0100 Subject: [PATCH 10/15] Tags --- Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js index 10c46dc..cc4219c 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js @@ -11,6 +11,7 @@ function details() { 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`, Version: "1.3", Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js", + Tags: 'h265,hevc,nvenc h265,ffmpeg,pre-processing,configurable', Inputs: [ { name: 'bitrate', From e2cc0aaa7face2f315c4be7f8079f1c134fda416 Mon Sep 17 00:00:00 2001 From: HaveAGitGat <43864057+HaveAGitGat@users.noreply.github.com> Date: Thu, 2 Apr 2020 12:42:40 +0100 Subject: [PATCH 11/15] FFmpeg path change --- Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js index cc4219c..0554484 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js @@ -149,8 +149,8 @@ function create_crop_values(file) { //create crop value if (!fs.existsSync(`${cropfile}`)) { returns.log += `Creating crop values...\n`; - execSync(`ffmpeg -ss 300 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 > \"${cropfile}\"`); - execSync(`ffmpeg -ss 1200 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 >> \"${cropfile}\"`); + execSync(otherArguments.ffmpegPath + ` -ss 300 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 > \"${cropfile}\"`); + execSync(otherArguments.ffmpegPath + ` -ss 1200 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 >> \"${cropfile}\"`); //get data from copvalue.txt var data = fs.readFileSync(`${cropfile}`).toString().split("\n"); //full data from cropvalue.txt //get height of the supposed cropped video From 773a6c12fc5cbe51192c97571bc88afb83d66bc7 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 3 Apr 2020 18:38:54 +0200 Subject: [PATCH 12/15] Delete auto_crop script --- .../Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js | 397 ------------------ 1 file changed, 397 deletions(-) delete mode 100644 Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js b/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js deleted file mode 100644 index 0554484..0000000 --- a/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js +++ /dev/null @@ -1,397 +0,0 @@ -const fs = require('fs'); -const execSync = require('child_process').execSync; - -function details() { - return { - id: "Tdarr_Plugin_e5c3_CnT_Remove_Letterbox", - Stage: "Pre-processing", - 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`, - Version: "1.3", - Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js", - Tags: 'h265,hevc,nvenc h265,ffmpeg,pre-processing,configurable', - Inputs: [ - { - name: 'bitrate', - tooltip: `Desired bitrate for a 1080p video, minimum transcode size is based of this too!\\n 720p will be half of 1080p, 480p will be half of 720p.\\nThe default is '3000', this value is based of movies.\\nI would suggest 1500-2000 for series.\\nExample:\\n3000` - }, - { - name: 'container', - tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv` - }, - ] - } -} - -function plugin(file, librarySettings, inputs, otherArguments) { - if (inputs.bitrate == "") { - var min_bitrate = 6600; - var avg_rate = 3000; - var max_rate = 6000; - } else { - var min_bitrate = inputs.bitrate*2.2; - var avg_rate = inputs.bitrate; - var max_rate = inputs.bitrate*2; - } - - var source = file.meta.SourceFile; //source file - var dir = file.meta.Directory; //source directory - var sourcename = file.meta.FileName.substring(0, file.meta.FileName.lastIndexOf(".")); //filename without extension - var stats = fs.statSync(source); - var size = stats["size"]/1000000000; - size = size.toFixed(2); - var decoder = decoder_string(file); //decoder, before the input - var encoder = encoder_string_full(file, highres(file), crop_decider(file, create_crop_values(file).crop_height).crop, avg_rate, max_rate); //encoder - var process = 0; //decides if it should be processed - - //default values that will be returned - var response = { - processFile: false, - preset: '', - container: '.mkv', - handBrakeMode: false, - FFmpegMode: true, - reQueueAfter: true, - infoLog: '' - } - - if (inputs.container !== undefined) { - response.container = inputs.container; - console.log(`Changed container to: ` + inputs.container); - } - - var returns = { - create_crop: create_crop_values(file), - crop: crop_decider(file, create_crop_values(file).crop_height), - size: size_check(file, min_bitrate) - } - - var log = { - size: returns.size.log, - hevc: ``, - resolution: ``, - crop: returns.crop.log, - createcrop: returns.create_crop.log - } - - //filters - if (size_check(file, min_bitrate).size == 1) { - if (hevc(file) == 1) { - log.hevc = `☑ - Video is not HEVC \n`; - } else { - log.hevc += "☒ - File is already in HEVC \n" - process = 1; - } - - if (highres(file) == 1) { - process = 1; - log.resolution += `☑ - Resolution > 1080p.\n File will be transcoded to 1080p \n`; - } else { - log.resolution += `☒ - Resolution <= 1080p \n`; - } - - if (crop_decider(file, create_crop_values(file).crop_height).crop != "0") { - process = 1; - } - } - - response.infoLog += log.createcrop + - log.crop + - log.resolution + - log.size + - log.hevc; - response.preset = `${decoder}, -map 0:v:0 -map 0:a -map 0:s? ${encoder}` - - //change response - if (process == 1) { - response.processFile = true; - response.infoLog += `File will be processed\n`; - } else if (file.forceProcessing === true) { - response.processFile = true; - response.infoLog += `Force processing!\n`; - } else if (response.container !== `.` + file.container) { - response.infoLog += `Container is not correct\nMuxing to ${response.container}!\n`; - response.preset = `${decoder}, -c copy`; - response.processFile = true; - } else { - response.infoLog += `Processing not necessary\n`; - } - - return response; -} - -function highres(file) { - //if file is larger than 1080p it should be transcoded - if (file.meta.ImageWidth > 1920) { - return 1; - } else { - return 0; - } -} - -function create_crop_values(file) { - var source = file.meta.SourceFile; //source file - var dir = file.meta.Directory; //source directory - var sourcename = file.meta.FileName.substring(0, file.meta.FileName.lastIndexOf(".")); //filename without extension - var cropfile = `${dir}/${sourcename}.txt`; //location and name of the crop file - var returns = { - crop_height: 0, //return value for this function, required for crop_decider - log: `` - } - //delete old crop value if it exists - //if (fs.existsSync(`${cropfile}`)) { - // returns.log += `removing old cropvalues...\n`; - // fs.unlinkSync(`${cropfile}`); - //} - - //create crop value - if (!fs.existsSync(`${cropfile}`)) { - returns.log += `Creating crop values...\n`; - execSync(otherArguments.ffmpegPath + ` -ss 300 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 > \"${cropfile}\"`); - execSync(otherArguments.ffmpegPath + ` -ss 1200 -i \"${source}\" -frames:v 240 -vf cropdetect -f null - 2>&1 | awk \'/crop/ { print $NF }\' | tail -240 >> \"${cropfile}\"`); - //get data from copvalue.txt - var data = fs.readFileSync(`${cropfile}`).toString().split("\n"); //full data from cropvalue.txt - //get height of the supposed cropped video - //var crop_height = parseInt(data[0].substring(10, 14)); - - for (var c = 0; c < data.length; c++) { - if (parseInt(data[c].substring(10, 14)) > returns.crop_height) { - returns.crop_height = parseInt(data[c].substring(10, 14)); - returns.log += `New cropheight: ${parseInt(data[c].substring(10, 14))}\n`; - } - } - } else { - returns.log += `Crop values already exist\n`; - - var data = fs.readFileSync(`${cropfile}`).toString().split("\n"); //full data from cropvalue.txt - //get height of the supposed cropped video - //var crop_height = parseInt(data[0].substring(10, 14)); - - for (var c = 0; c < data.length; c++) { - if (parseInt(data[c].substring(10, 14)) > returns.crop_height) { - returns.crop_height = parseInt(data[c].substring(10, 14)); - returns.log += `New cropheight: ${parseInt(data[c].substring(10, 14))}\n`; - } - } - } - - return returns; -} - -function hevc(file) { - //check if the file is already hevc, it will not be transcoded if true - if ("hevc".toLowerCase().includes(file.ffProbeData.streams[0].codec_name.toLowerCase())) { - return 0; - } else { - return 1; - } -} - -function decoder_string(file) { - var decoder = ``; //decoder, before the input - - //use the correct decoder - if (file.video_codec_name == 'h263') { - decoder = `-c:v h263_cuvid` - } - else if (file.video_codec_name == 'h264') { - if (file.ffProbeData.streams[0].profile != 'High 10') { //Remove HW Decoding for High 10 Profile - decoder = `-c:v h264_cuvid` - } - } - else if (file.video_codec_name == 'mjpeg') { - decoder = `c:v mjpeg_cuvid` - } - else if (file.video_codec_name == 'mpeg1') { - decoder = `-c:v mpeg1_cuvid` - } - else if (file.video_codec_name == 'mpeg2') { - decoder = `-c:v mpeg2_cuvid` - } - else if (file.video_codec_name == 'vc1') { - decoder = `-c:v vc1_cuvid` - } - else if (file.video_codec_name == 'vp8') { - decoder = `-c:v vp8_cuvid` - } - else if (file.video_codec_name == 'vp9') { - decoder = `-c:v vp9_cuvid` - } - - return decoder; -} - -function crop_decider(file, crop_height) { - var returns = { - crop: `0`, //sets the crop filter - log: ``, - } - - for (var i = 0; i < file.ffProbeData.streams.length; i++) { - if (file.ffProbeData.streams[i].width !== undefined) { - var imageWidth = file.ffProbeData.streams[i].width; - var imageHeight = file.ffProbeData.streams[i].height; - break; - } - } - var min_crop = parseInt(imageHeight*.98); //if the crop value is larger than this the file won't be cropped - - //tree for resolution : quality - if (imageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) - //crop only if it is a larger crop than 1%; - if (crop_height < min_crop) { - var crop_hdis = parseInt((imageHeight-crop_height)/2); - if (crop_height >= 790) { - returns.crop = `-filter:0 crop=1920:${crop_height}:0:${crop_hdis}`; - returns.log += `☑ - crop is larger than 1%\n`; - } - } else { - returns.log += `☒ - Crop is not necessary\n`; - } - } else if(imageWidth < 1300 && file.meta.ImageWidth >= 770) { - //crop only if it is a larger crop than 1%; - if (crop_height < min_crop) { - var crop_hdis = parseInt((imageHeight-crop_height)/2); - if (crop_height >= 530) { - returns.crop = `-filter:0 crop=1280:${crop_height}:0:${crop_hdis}`; - returns.log += `☑ - crop is larger than 1%\n`; - } - } else { - returns.log += `☒ - Crop is not necessary\n`; - } - } else if(imageWidth < 770) { //file won't be cropped at this resolution - returns.log += `No crop: Resolution < 720p\n`; - } - - return returns; -} - -function size_check(file, min_bitrate) { - var duration = file.meta.Duration; //duration of video in seconds - var source = file.meta.SourceFile; //source file - var stats = fs.statSync(source); - var size = stats["size"]/1000000000; - size = size.toFixed(2); - var returns = { - size: 0, - log: `` - } - - //tree for resolution : quality - if (file.video_resolution === "1080p" || file.video_resolution === "4KUHD") { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) - var min_transcode_size = (min_bitrate * duration * 0.125)/1000000; //minimum size in GB for transcode - min_transcode_size = min_transcode_size.toFixed(2); - - //check if file is large enough for transcode - if (size >= (min_bitrate * duration * 0.125)/1000000) { - returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`; - returns.size = 1; - } else { - returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; - } - } else if(file.video_resolution === "720p") { //file will be encoded if the resolution is 720p - var min_transcode_size = ((min_bitrate/2) * duration * 0.125)/1000000; //minimum size in GB for transcode - min_transcode_size = min_transcode_size.toFixed(2); - - //check if file is large enough for transcode - if (size >= ((min_bitrate/2) * duration * 0.125)/1000000) { - returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`; - returns.size = 1; - } else { - returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; - } - } else if(file.video_resolution === "480p" || file.video_resolution === "576p") { //file will be encoded if the resolution is 480p or 576p - var min_transcode_size = ((min_bitrate/4) * duration * 0.125)/1000000; //minimum size in GB for transcode - min_transcode_size = min_transcode_size.toFixed(2); - - //check if file is large enough for transcode - if (size >= ((min_bitrate/4) * duration * 0.125)/1000000) { - returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`; - returns.size = 1; - } else { - returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`; - } - } - - return returns; -} - -function error_fix(file) { - var fix = { - sub_codec: 0, //changes to 1 if unwanted codec is found - muxing: 0 - } - - for (var i = 0; i < file.ffProbeData.streams.length; i++) { - - //these subtitle codecs don't fit in a mkv container - if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "eia_608" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase.includes("sub") && response.container == '.mkv') { - fix.sub_codec = 1; - } - - //mitigate TrueHD audio causing Too many packets error - if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "truehd" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "dts" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" ) { - fix.muxing = 1; - } - - } - - return fix; -} - -function encoder_string(file, avg_rate, max_rate) { - var encoder = ``; //encoder - var fix = error_fix(file); - var sub = ``; - - //tree for resolution : quality - if (file.video_resolution === "1080p" || file.video_resolution === "4KUHD") { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled) - encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate}k -maxrate:v ${max_rate}k`; //-qp 26 - } else if(file.video_resolution === "720p") { //file will be encoded if the resolution is 720p - encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate/2}k -maxrate:v ${max_rate/2}k`; //-qp 28 - } else if(file.video_resolution === "480p" || file.video_resolution === "576p") { //file will be encoded if the resolution is 480p or 576p - encoder += ` -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 26 -b:v ${avg_rate/4}k -maxrate:v ${max_rate/4}k`; //-qp 30 - } - encoder += ` -c:v hevc_nvenc -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -dn`; - - if (fix.sub_codec == 1) { - for (var i = 0; i < file.ffProbeData.streams.length; i++) { - if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "eia_608" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase().includes("sub")) { - sub += ` -c:${i} ass`; - } else { - if (file.ffProbeData.streams[i].codec_type.toLowerCase().includes("sub")) { - sub += ` -c:${i} copy`; - } - } - } - } else { - sub = ` -c:s copy` - } - - if (fix.muxing == 1) { - encoder += ` -max_muxing_queue_size 2048`; - } - - return encoder + ` -c:a copy` + sub; -} - -function encoder_string_full(file, highres, crop, avg_rate, max_rate) { - var encoder = encoder_string(file, avg_rate, max_rate); - - console.log(`crop filter: ` + crop) - - if (highres == 1 && crop != "0") { - return crop + `,scale=-1:1920 ` + encoder; - } else if (highres == 1) { - return `-filter:0 scale=-1:1920 ` + encoder; - } else if (crop != "0") { - return crop + encoder; - } else { - return encoder; - } -} - -module.exports.details = details; -module.exports.plugin = plugin; From 333ade3cadf0e9c909c4e28711e233d6d1042944 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 3 Apr 2020 18:39:45 +0200 Subject: [PATCH 13/15] Latest updates to add subtitles --- Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js index 5ce10f7..65e7136 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js @@ -11,12 +11,15 @@ function details() { 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`, Version: "1.3", Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js", - Tags:'pre-processing,ffmpeg,subtitle only,configurable', Inputs: [ { name: 'install_packages', tooltip: `Please change this to "yes", it allows the plugin to install the required nodemodule. (iso-639-2)` }, + { + name: 'container', + tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv` + }, ] } } @@ -32,6 +35,11 @@ function plugin(file, librarySettings, inputs, otherArguments) { reQueueAfter: false, infoLog: `Searching new subtitles...\n`, } + + if (inputs.container !== undefined) { + response.container = inputs.container; + console.log(`Changed container to: ` + inputs.container); + } if (inputs.install_packages == "yes") { if (!fs.existsSync(`${otherArguments.homePath}/Tdarr/node_modules/iso-639-2`)) { @@ -126,6 +134,8 @@ function plugin(file, librarySettings, inputs, otherArguments) { response.infoLog += `No new subtitle languages were found\n`; } + //response.infoLog += `The ffmpeg string is: ${response.preset}\n` + return response } From 4c5bf97dd849ffd84a1743655d0a957897e71989 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 3 Apr 2020 18:40:43 +0200 Subject: [PATCH 14/15] Latest updates to Keep_Preferred_Audio --- ...rr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js index 95c9ca4..10326a7 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js @@ -6,35 +6,38 @@ function details() { id: "Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio", Stage: "Pre-processing", Name: "Keep Preffered Audio", - Type: "Video", + Type: "Audio", Operation:"Remove Audio", Description: "Plugin that checks for unwanted audio, per 1.104 beta you can change the languages yourself from within Tdarr!\nUntill you enter a value it keep english tracks by default.\nUndefined languages are kept to prevent videos without sound.\nIf you would like to keep track of the languages you have for each file you can use the 'special' option.\nCreated by @control#0405", - Version: "1.1", - Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js", - Tags:'pre-processing,ffmpeg,audio only,configurable', + Version: "1.2", + Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_non_English_Audio.js", Inputs: [ { name: 'languages', - tooltip: `Desired Languages you would like to keep, language format has to be according to the iso-639-2 standard: https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes\nIt could look like: "eng","dut"` + tooltip: `Desired Languages you would like to keep, language format has to be according to the iso-639-2 standard: https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes\\nExample:\\eng,dut` }, { name: 'special', - tooltip: `This is if you want a specific language to be logged to a file in your Tdarr documents folder.\nIt will add the name of the file that is being processed if this language(s) has been found.\nThe file is created the first time it finds a file with the language.\nIt could look like: "eng","dut"\nThe languages don't have to be in "languages".` - } + tooltip: `This is if you want a specific language to be logged to a file in your Tdarr documents folder.\\nIt will add the name of the file that is being processed if this language(s) has been found.\\nThe file is created the first time it finds a file with the language.\\nThe languages don't have to be in "languages".\\nExample:\\eng,dut` + }, + { + name: 'container', + tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv` + }, ] } } function plugin(file, librarySettings, inputs, otherArguments) { - if (inputs.languages == "") { + if (inputs.languages == "" || inputs.special == 'undefined') { var languages = ["eng", "en"]; //these languages should be kept, named according to ISO 639-2 language scheme } else { - var languages = inputs.languages.split(','); //these languages should be kept, named according to ISO 639-2 language scheme + var languages = inputs.languages.toLowerCase().split(','); //these languages should be kept, named according to ISO 639-2 language scheme } - if (inputs.special !== "") { - var special = inputs.special.split(','); - } else { + if (inputs.special == "" || inputs.special == 'undefined') { var special = ``; + } else { + var special = inputs.special.toLowerCase().split(','); } if (languages.length >= special.length) { var length = languages.length; @@ -59,6 +62,11 @@ function plugin(file, librarySettings, inputs, otherArguments) { infoLog: 'Removing unwanted audio...\n', }; + if (inputs.container !== undefined) { + response.container = inputs.container; + console.log(`Changed container to: ` + inputs.container); + } + for (i = 0; i < file.ffProbeData.streams.length; i++) { if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") { //check for non-english tracks @@ -86,6 +94,8 @@ function plugin(file, librarySettings, inputs, otherArguments) { response.infoLog += `Found wanted ${languages[l]}: ${i}\n`; wanted++; break; + } else if (i == length-1) { + response.infoLog += `Found unwanted: ${file.ffProbeData.streams[i].tags.language}: ${i}\n`; } } } else { @@ -103,7 +113,7 @@ function plugin(file, librarySettings, inputs, otherArguments) { } } - if (audio > wanted && wanted > 1) { + if (audio > wanted && wanted > 0) { transcode = 1; } From bc8b9474ddd3b968d978bd5b03931c6ae8e7d315 Mon Sep 17 00:00:00 2001 From: controlol <46456214+controlol@users.noreply.github.com> Date: Fri, 3 Apr 2020 18:47:11 +0200 Subject: [PATCH 15/15] Fixed link --- Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js index 10326a7..113dde9 100644 --- a/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js +++ b/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js @@ -10,7 +10,7 @@ function details() { Operation:"Remove Audio", Description: "Plugin that checks for unwanted audio, per 1.104 beta you can change the languages yourself from within Tdarr!\nUntill you enter a value it keep english tracks by default.\nUndefined languages are kept to prevent videos without sound.\nIf you would like to keep track of the languages you have for each file you can use the 'special' option.\nCreated by @control#0405", Version: "1.2", - Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_non_English_Audio.js", + Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js", Inputs: [ { name: 'languages', @@ -23,7 +23,7 @@ function details() { { name: 'container', tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv` - }, + } ] } }