diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..1b182fe --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,10 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..e46a4c0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,10 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js b/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js index df76687..58b4813 100644 --- a/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js +++ b/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js @@ -85,6 +85,19 @@ function plugin(file) { /// +if(hasSubs){ + + response.infoLog += "☒File has subs \n" + response.preset = ',-sn -map 0 -c copy' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has no subs \n" + } + if((file.meta.Title != "undefined") && !jsonString.includes("aac") && hasSubs){ response.infoLog += "☒File has title metadata and no aac and subs \n" @@ -144,19 +157,6 @@ function plugin(file) { response.infoLog += "☑File has aac track \n" } - if(hasSubs){ - - response.infoLog += "☒File has subs \n" - response.preset = ',-sn -map 0 -c copy' - response.reQueueAfter = true; - response.processFile = true; - response.FFmpegMode = true - return response - - }else{ - response.infoLog += "☑File has no subs \n" - } - response.infoLog += "☑File meets conditions! \n" return response diff --git a/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js b/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js index 9314ee1..9bd316c 100644 --- a/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js +++ b/Community/Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30.js @@ -85,6 +85,19 @@ function plugin(file) { /// +if(hasSubs){ + + response.infoLog += "☒File has subs \n" + response.preset = ',-sn -map 0 -c copy' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has no subs \n" + } + if((file.meta.Title != "undefined") && !jsonString.includes("aac") && hasSubs){ response.infoLog += "☒File has title metadata and no aac and subs \n" @@ -144,18 +157,6 @@ function plugin(file) { response.infoLog += "☑File has aac track \n" } - if(hasSubs){ - - response.infoLog += "☒File has subs \n" - response.preset = ',-sn -map 0 -c copy' - response.reQueueAfter = true; - response.processFile = true; - response.FFmpegMode = true - return response - - }else{ - response.infoLog += "☑File has no subs \n" - } response.infoLog += "☑File meets conditions! \n" 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 b2581a1..428852f 100644 --- a/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js +++ b/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js @@ -4,15 +4,19 @@ function details() { 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 and 1080p. If files are not in hevc they will be transcoded. The output container is mkv. \n\n`, - Version: "1.03", + 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`, + Version: "1.08", Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js" } } - + function plugin(file) { var transcode = 0; //if this var changes to 1 the file will be transcoded - + var bitrateprobe = 0; //bitrate from ffprobe + var bitratetarget = 0; + var bitratemax = 0; + var bitratecheck = 0; + var subcli = `-c:s copy` //default values that will be returned var response = { processFile: false, @@ -23,16 +27,18 @@ function plugin(file) { reQueueAfter: true, infoLog: '' } - + //check if the file is a video, if not the function will be stopped immediately if (file.fileMedium !== "video") { response.processFile = false response.infoLog += "☒File is not a video! \n" return response - } else { + } + else { + bitrateprobe = file.ffProbeData.streams[0].bit_rate response.infoLog += "☑File is a video! \n" } - + //check if the file is already hevc, it will not be transcoded if true and the function will be stopped immediately if (file.ffProbeData.streams[0].codec_name == 'hevc') { response.processFile = false @@ -40,130 +46,143 @@ function plugin(file) { return response } +//codec will be checked so it can be transcoded correctly + if (file.video_codec_name == 'h263') { + response.preset = `-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 + response.preset = `-c:v h264_cuvid` + } + } + else if (file.video_codec_name == 'mjpeg') { + response.preset = `c:v mjpeg_cuvid` + } + else if (file.video_codec_name == 'mpeg1') { + response.preset = `-c:v mpeg1_cuvid` + } + else if (file.video_codec_name == 'mpeg2') { + response.preset = `-c:v mpeg2_cuvid` + } +// skipping this one because it's empty +// else if (file.video_codec_name == 'mpeg4') { +// response.preset = `` +// } + else if (file.video_codec_name == 'vc1') { + response.preset = `-c:v vc1_cuvid` + } + else if (file.video_codec_name == 'vp8') { + response.preset = `-c:v vp8_cuvid` + } + else if (file.video_codec_name == 'vp9') { + response.preset = `-c:v vp9_cuvid` + } + //file will be encoded if the resolution is 480p or 576p //codec will be checked so it can be transcoded correctly - if(file.video_resolution === "480p" || file.video_resolution === "576p" ) { - if (file.video_codec_name == 'h263') { - response.preset = `-c:v h263_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` + if (file.video_resolution === "480p" || file.video_resolution === "576p" ) { + bitratecheck = 1000000; + if(bitrateprobe != null && bitrateprobe < bitratecheck) { + bitratetarget = parseInt((bitrateprobe * .8) / 1000); // Lower Bitrate to 60% of original and convert to KB + bitratemax = bitratetarget + 500; // Set max bitrate to 6MB Higher } - else if (file.video_codec_name == 'h264') { - response.preset = `-c:v h264_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mjpeg') { - response.preset = `-c:v mjpeg_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg1') { - response.preset = `-c:v mpeg1_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg2') { - response.preset = `-c:v mpeg2_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg4') { - response.preset = `,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vc1') { - response.preset = `-c:v vc1_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vp8') { - response.preset = `-c:v vp8_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vp9') { - response.preset = `-c:v vp9_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` - } else { - response.preset = `, -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -preset slow -c:a copy -c:s copy` + bitratetarget = 1000; + bitratemax = 1500; } - + response.preset += `,-map 0 -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 29 -b:v ${bitratetarget}k -maxrate:v 1500k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli} -dn`; transcode = 1; } - +//Set Subtitle Var before adding encode cli + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + try { + if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" ) { + subcli = `-c:s srt` + } + } + catch (err) { } + } //file will be encoded if the resolution is 720p //codec will be checked so it can be transcoded correctly if(file.video_resolution === "720p") { - if (file.video_codec_name == 'h263') { - response.preset = `-c:v h263_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` + bitratecheck = 2000000; + if(bitrateprobe != null && bitrateprobe < bitratecheck) { + bitratetarget = parseInt((bitrateprobe * .8) / 1000); // Lower Bitrate to 60% of original and convert to KB + bitratemax = bitratetarget + 2000; // Set max bitrate to 6MB Higher } - else if (file.video_codec_name == 'h264') { - response.preset = `-c:v h264_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mjpeg') { - response.preset = `-c:v mjpeg_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg1') { - response.preset = `-c:v mpeg1_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg2') { - response.preset = `-c:v mpeg2_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg4') { - response.preset = `,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vc1') { - response.preset = `-c:v vc1_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vp8') { - response.preset = `-c:v vp8_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vp9') { - response.preset = `-c:v vp9_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` - } else { - response.preset = `, -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -preset slow -c:a copy -c:s copy` + bitratetarget = 2000; + bitratemax = 4000; } - + response.preset += `,-map 0 -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -b:v ${bitratetarget}k -maxrate:v ${bitratemax}k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli} -dn`; transcode = 1; } - //file will be encoded if the resolution is 1080p //codec will be checked so it can be transcoded correctly if(file.video_resolution === "1080p") { - if (file.video_codec_name == 'h263') { - response.preset = `-c:v h263_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` + bitratecheck = 2500000; + if(bitrateprobe != null && bitrateprobe < bitratecheck) { + bitratetarget = parseInt((bitrateprobe * .8) / 1000); // Lower Bitrate to 60% of original and convert to KB + bitratemax = bitratetarget + 2500; // Set max bitrate to 6MB Higher } - else if (file.video_codec_name == 'h264') { - response.preset = `-c:v h264_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` + else { + bitratetarget = 2500; + bitratemax = 5000; } - else if (file.video_codec_name == 'mjpeg') { - response.preset = `-c:v mjpeg_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg1') { - response.preset = `-c:v mpeg1_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg2') { - response.preset = `-c:v mpeg2_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'mpeg4') { - response.preset = `,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vc1') { - response.preset = `-c:v vc1_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vp8') { - response.preset = `-c:v vp8_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - else if (file.video_codec_name == 'vp9') { - response.preset = `-c:v vp9_cuvid,-c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - else { - response.preset = `, -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 32 -preset slow -c:a copy -c:s copy` - } - + response.preset += `,-map 0 -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -b:v ${bitratetarget}k -maxrate:v ${bitratemax}k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli} -dn`; transcode = 1; } - +//file will be encoded if the resolution is 4K +//codec will be checked so it can be transcoded correctly + if(file.video_resolution === "4KUHD") { + bitratecheck = 14000000; + if(bitrateprobe != null && bitrateprobe < bitratecheck) { + bitratetarget = parseInt((bitrateprobe * .7) / 1000); // Lower Bitrate to 60% of original and convert to KB + bitratemax = bitratetarget + 6000; // Set max bitrate to 6MB Higher + } + else { + bitratetarget = 14000; + bitratemax = 20000; + } + response.preset += `,-map 0 -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -b:v ${bitratetarget}k -maxrate:v ${bitratemax}k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy -c:s copy -dn`; + transcode = 1; + } + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + try { + //mitigate TrueHD audio causing Too many packets error + if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "truehd" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" ) { + response.preset += ` -max_muxing_queue_size 1024` + } + } + catch (err) { } +//mitigate errors due to embeded pictures + try { + if ((file.ffProbeData.streams[i].codec_name.toLowerCase() == "png" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "bmp" || file.ffProbeData.streams[i].codec_name.toLowerCase() == "mjpeg") && file.ffProbeData.streams[i].codec_type.toLowerCase() == "video" ) { + response.preset += ` -map -0:v:1` + } + } + catch (err) { } + } //check if the file is eligible for transcoding //if true the neccessary response values will be changed if (transcode == 1) { response.processFile = true; response.FFmpegMode = true response.reQueueAfter = true; - response.infoLog += `☒File is ${file.video_resolution} but is not hevc!\n` + response.infoLog += `☒File is ${file.video_resolution}!\n` + response.infoLog += `☒File is not hevc!\n` + response.infoLog += `☒File bitrate is ${parseInt(bitrateprobe / 1000)}kb!\n` + if(bitrateprobe < bitratecheck) { + response.infoLog += `File bitrate is LOWER than the Default Target Bitrate!\n` + } + else { + response.infoLog += `File bitrate is HIGHER than the Default Target Bitrate!\n` + } + response.infoLog += `☒Target Bitrate set to ${bitratetarget}kb!\n` response.infoLog += `File is being transcoded!\n` } return response -} - + } module.exports.details = details; - module.exports.plugin = plugin; diff --git a/Community/Tdarr_Plugin_d5d4_iiDrakeii_Not_A_Video_Mjpeg_Fix.js b/Community/Tdarr_Plugin_d5d4_iiDrakeii_Not_A_Video_Mjpeg_Fix.js new file mode 100644 index 0000000..cde7642 --- /dev/null +++ b/Community/Tdarr_Plugin_d5d4_iiDrakeii_Not_A_Video_Mjpeg_Fix.js @@ -0,0 +1,76 @@ +function details() { + return { + id: "Tdarr_Plugin_d5d4_iiDrakeii_Not_A_Video_Mjpeg_Fix", + Name: "Mjpeg Stream False Not A Video Fixer", + Type: "Video", + Operation:"", + Description: `Checks if file is not a video file due to Mjpeg stream. Removes Mjpeg Stream \n\n`, + Version: "1.00", + } +} + +function plugin(file) { + var transcode = 0; //if this var changes to 1 the file will be transcoded +//default values that will be returned + var response = { + processFile: false, + preset: '', + container: '.mp4', + handBrakeMode: false, + FFmpegMode: false, + reQueueAfter: true, + infoLog: '' + } + response.container = '.' + file.container + + for (var i = 0; i < file.ffProbeData.streams.length; i++) { +//check for mjpeg streams and set the preset if mjpeg streams are found + try { + if ((file.ffProbeData.streams[i].codec_name.toLowerCase() == "mjpeg") && file.ffProbeData.streams[i].codec_type.toLowerCase() == "video" ) { + response.preset = `,-map 0 -map -0:v:1 -c:v copy -c:a copy -c:s copy` + response.infoLog = "☒File is not a video but has Mjpeg Stream! \n" + } + } + catch (err) { } + } + //If preset is not set check if file is video and stop (reque if it is a video) + if (response.preset != `,-map 0 -map -0:v:1 -c:v copy -c:a copy -c:s copy`) { + if (file.fileMedium !== "video") { + console.log("File is not video!") + response.infoLog += " File is not video\n" + response.processFile = false; + + return response + } + else { + response.infoLog += "☑File is a video Without Mjpeg! \n" + response.processFile = false + response.reQueueAfter = true + return response + } + } + //Process mjpeg removal if video found to not be a video and have mjpeg stream + else { + if (file.fileMedium !== "video") { + transcode = 1 + } + else { + response.infoLog += "☑File is a video With Mjpeg! \n" + response.processFile = false + response.reQueueAfter = true + return response + } + } +//check if the file is eligible for transcoding +//if true the neccessary response values will be changed + if (transcode == 1) { + response.processFile = true; + response.FFmpegMode = true + response.reQueueAfter = true; + response.infoLog += `Mjpeg Stream is being removed!\n` + } + + return response +} +module.exports.details = details; +module.exports.plugin = plugin; diff --git a/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js new file mode 100644 index 0000000..a81d881 --- /dev/null +++ b/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js @@ -0,0 +1,98 @@ +const fs = require('fs'); +const iso6392 = require('/home/Tdarr/Documents/node_modules/iso-639-2'); + +function details() { + return { + id: "Tdarr_Plugin_e5c3_CnT_Add_Subtitles", + Name: "Add subtitles to MKV files", + Type: "Video", + Operation:"Remux", + Description: `Add subtitles. READ THIS!! You must run "npm install iso-639-2" in the folder "/home/Tdarr/Documents" for this plugin to work. This is a plugin that will check for subtitles, they should be named according to the ISO 639-2 language code.`, + Version: "1.00", + Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js", + } +} + +function plugin(file) { + var i = 0; //int for counting lang[position] + var sub = 0; //becomes first subtitle stream + var lang = iso6392; //languages to check against + var path = file.meta.Directory; //path of media folder + var exist = 0; //if the language exists should be added this becomes 1 + var new_subs = 0 //count the new subs + var added_subs = 0; //counts the amount of subs that have been mapped + var preset_import = ''; + var preset_meta = ''; + + + //default response + var response = { + processFile: false, + preset: `,`, + container: '.mkv', + handBrakeMode: false, + FFmpegMode: false, + reQueueAfter: false, + infoLog: `Testing for subtitles...\nPath: ${path}\n`, + } + + //find first subtitle stream + while (file.ffProbeData.streams[sub].codec_type.toLowerCase() != "subtitle") { + sub++ + } + response.infoLog += `The first subtitle stream is ${sub}\n` + + for (i = 0; i < lang.length; i++) { + //check if srt exists in folder + if (fs.existsSync(`${path}/${lang[i].iso6392B}.srt`)) { + response.infoLog += `Found subtitle ${lang[i].name}\n` + + //check if language already exists + for (sub_stream = sub; sub_stream < file.ffProbeData.streams.length; sub_stream++) { + response.infoLog += `does ${lang[i].name} exist in stream ${sub_stream}?\n` + if (file.ffProbeData.streams[sub_stream].tags.language.toLowerCase() == lang[i].iso6392B) { + response.infoLog += `YES\n` + exist = 1; + } else { + response.infoLog += `NO\n` + } + } + + //add if it hasn't found the language + if (exist != 1) { + preset_import += ` -sub_charenc "UTF-8" -f srt -i "${path}/${lang[i].iso6392B}.srt"` + preset_meta += ` -metadata:s:s:${new_subs} language=${lang[i].iso6392B}` + new_subs++ + } + } else { + response.infoLog += `did not find sub ${lang[i].iso6392B}.srt\n` + } + exist = 0; + } + + response.infoLog += `${new_subs} new subs will be added\n` + response.preset += ` ${preset_import}${preset_meta} -map 0:v -map 0:a` + + //map new subs + while (added_subs < new_subs) { + added_subs++ + response.preset += ` -map ${added_subs}:s` + } + + //if new subs have been found they will be added + if (new_subs > 0) { + response.FFmpegMode = true; + response.processFile = true; + response.reQueueAfter = true; + response.preset += ` -map 0:s -c copy` + } else { + response.infoLog += `No new subtitle languages were found\n` + } + + response.infoLog += `The ffmpeg string is: ${response.preset}\n` + + return response +} + +module.exports.details = details; +module.exports.plugin = plugin; diff --git a/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js b/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js new file mode 100644 index 0000000..940f154 --- /dev/null +++ b/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js @@ -0,0 +1,162 @@ + + + +function details() { + + return { + id: "Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium", + Name: "TheRealShadoh FFmpeg Subs Medium, video MP4, audio AAC, keep subs. ", + Type: "Video", + Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'Medium' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n +`, + Version: "1.00", + Link: "https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js" + } + +} + +function plugin(file) { + + + //Must return this object + + var response = { + + processFile : false, + preset : '', + container : '.mp4', + handBrakeMode : false, + FFmpegMode : false, + reQueueAfter : false, + infoLog : '', + + } + + if (file.fileMedium !== "video"){ + + + console.log("File is not video") + + response.infoLog += "☒File is not video \n" + response.processFile = false; + + return response + + } else { + + var jsonString = JSON.stringify(file) + + + var hasSubs = false + + + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + + try { + + if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){ + + hasSubs = true + + } + } catch (err) { } + } + + + if(file.ffProbeData.streams[0].codec_name != 'h264'){ + + response.infoLog += "☒File is not in h264! \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset medium -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File is already in h264! \n" + } + + + /// + + if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has title metadata and no aac and subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + if(!jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has no aac track and has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + if(file.meta.Title != undefined && hasSubs){ + + response.infoLog += "☒File has title and has subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + + /// + if(file.meta.Title != undefined ){ + + response.infoLog += "☒File has title metadata \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + }else{ + response.infoLog += "☑File has no title metadata" + } + + if(!jsonString.includes("aac")){ + + response.infoLog += "☒File has no aac track \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has aac track \n" + } + + if(hasSubs){ + + response.infoLog += "☒File has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has no subs \n" + } + + response.infoLog += "☑File meets conditions! \n" + return response + + } +} + +module.exports.details = details; + +module.exports.plugin = plugin; diff --git a/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js b/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js new file mode 100644 index 0000000..ea42d6c --- /dev/null +++ b/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js @@ -0,0 +1,161 @@ + + + +function details() { + + return { + id: "Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast", + Name: "TheRealShadoh FFmpeg Subs Fast, video MP4, audio AAC, keep subs. ", + Type: "Video", + Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'Fast' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n +`, + Version: "1.00", + Link: "https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js" + } + +} + +function plugin(file) { + + + //Must return this object + + var response = { + + processFile : false, + preset : '', + container : '.mp4', + handBrakeMode : false, + FFmpegMode : false, + reQueueAfter : false, + infoLog : '', + + } + + if (file.fileMedium !== "video"){ + + + console.log("File is not video") + + response.infoLog += "☒File is not video \n" + response.processFile = false; + + return response + + } else { + + var jsonString = JSON.stringify(file) + + + var hasSubs = false + + + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + + try { + + if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){ + + hasSubs = true + + } + } catch (err) { } + } + + + if(file.ffProbeData.streams[0].codec_name != 'h264'){ + + response.infoLog += "☒File is not in h264! \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset fast -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File is already in h264! \n" + } + + + /// + + if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has title metadata and no aac and subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + if(!jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has no aac track and has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + if(file.meta.Title != undefined && hasSubs){ + + response.infoLog += "☒File has title and has subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + /// + if(file.meta.Title != undefined ){ + + response.infoLog += "☒File has title metadata \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + }else{ + response.infoLog += "☑File has no title metadata" + } + + if(!jsonString.includes("aac")){ + + response.infoLog += "☒File has no aac track \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has aac track \n" + } + + if(hasSubs){ + + response.infoLog += "☒File has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has no subs \n" + } + + response.infoLog += "☑File meets conditions! \n" + return response + + } +} + +module.exports.details = details; + +module.exports.plugin = plugin; diff --git a/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js b/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js new file mode 100644 index 0000000..acb940d --- /dev/null +++ b/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js @@ -0,0 +1,162 @@ + + + +function details() { + + return { + id: "Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow", + Name: "TheRealShadoh FFmpeg Subs Slow, video MP4, audio AAC, keep subs. ", + Type: "Video", + Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'Slow' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n +`, + Version: "1.00", + Link: "https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js" + } + +} + +function plugin(file) { + + + //Must return this object + + var response = { + + processFile : false, + preset : '', + container : '.mp4', + handBrakeMode : false, + FFmpegMode : false, + reQueueAfter : false, + infoLog : '', + + } + + if (file.fileMedium !== "video"){ + + + console.log("File is not video") + + response.infoLog += "☒File is not video \n" + response.processFile = false; + + return response + + } else { + + var jsonString = JSON.stringify(file) + + + var hasSubs = false + + + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + + try { + + if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){ + + hasSubs = true + + } + } catch (err) { } + } + + + if(file.ffProbeData.streams[0].codec_name != 'h264'){ + + response.infoLog += "☒File is not in h264! \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset slow -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File is already in h264! \n" + } + + + /// + + if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has title metadata and no aac and subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + if(!jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has no aac track and has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + if(file.meta.Title != undefined && hasSubs){ + + response.infoLog += "☒File has title and has subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + + /// + if(file.meta.Title != undefined ){ + + response.infoLog += "☒File has title metadata \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + }else{ + response.infoLog += "☑File has no title metadata" + } + + if(!jsonString.includes("aac")){ + + response.infoLog += "☒File has no aac track \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has aac track \n" + } + + if(hasSubs){ + + response.infoLog += "☒File has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has no subs \n" + } + + response.infoLog += "☑File meets conditions! \n" + return response + + } +} + +module.exports.details = details; + +module.exports.plugin = plugin; diff --git a/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast.js b/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast.js new file mode 100644 index 0000000..e954cf2 --- /dev/null +++ b/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast.js @@ -0,0 +1,162 @@ + + + +function details() { + + return { + id: "Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast", + Name: "TheRealShadoh FFmpeg Subs VeryFast, video MP4, audio AAC, keep subs. ", + Type: "Video", + Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'VeryFast' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n +`, + Version: "1.00", + Link: "https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_Veryfast.js" + } + +} + +function plugin(file) { + + + //Must return this object + + var response = { + + processFile : false, + preset : '', + container : '.mp4', + handBrakeMode : false, + FFmpegMode : false, + reQueueAfter : false, + infoLog : '', + + } + + if (file.fileMedium !== "video"){ + + + console.log("File is not video") + + response.infoLog += "☒File is not video \n" + response.processFile = false; + + return response + + } else { + + var jsonString = JSON.stringify(file) + + + var hasSubs = false + + + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + + try { + + if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){ + + hasSubs = true + + } + } catch (err) { } + } + + + if(file.ffProbeData.streams[0].codec_name != 'h264'){ + + response.infoLog += "☒File is not in h264! \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset veryfast -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File is already in h264! \n" + } + + + /// + + if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has title metadata and no aac and subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + if(!jsonString.includes("aac") && hasSubs){ + + response.infoLog += "☒File has no aac track and has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + if(file.meta.Title != undefined && hasSubs){ + + response.infoLog += "☒File has title and has subs \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + } + + + + /// + if(file.meta.Title != undefined ){ + + response.infoLog += "☒File has title metadata \n" + response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + }else{ + response.infoLog += "☑File has no title metadata" + } + + if(!jsonString.includes("aac")){ + + response.infoLog += "☒File has no aac track \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has aac track \n" + } + + if(hasSubs){ + + response.infoLog += "☒File has subs \n" + response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text' + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true + return response + + }else{ + response.infoLog += "☑File has no subs \n" + } + + response.infoLog += "☑File meets conditions! \n" + return response + + } +} + +module.exports.details = details; + +module.exports.plugin = plugin; diff --git a/README.md b/README.md index f86269c..9083939 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ For the plugin link, I'll add this once you create a PR to community plugins. } - Please see the bottom of this README for the structure of an example file object: + Please see the bottom of this README for the structure of an example file object. To see a specific file's details, search for the file in the search tab and click the 'i' info button. 6.Once you have finished configuring your plugin,