make-only-subtitle-default
HaveAGitGat 6 years ago
parent d28272f6d4
commit 9c8ac98728

@ -0,0 +1,4 @@
node_modules/
.github/
# npx prettier@2.0.5 . --write

@ -7,172 +7,184 @@ function details() {
Operation: "Transcode",
Description: `Files not in H265 will be transcoded into H265 using Nvidia GPU with ffmpeg, settings are dependant on file bitrate, working by the logic that H265 can support the same ammount of data at half the bitrate of H264. NVDEC & NVENC compatable GPU required. \n\n`,
Version: "2.4",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js",
Tags: 'pre-processing,ffmpeg,video only,nvenc h265,configurable',
Inputs: [{
name: 'container',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js",
Tags: "pre-processing,ffmpeg,video only,nvenc h265,configurable",
Inputs: [
{
name: "container",
tooltip: `Specify output container of file, ensure that all stream types you may have are supported by your chosen container. mkv is recommended.
\\nExample:\\n
mkv
\\nExample:\\n
mp4`
mp4`,
},
{
name: 'bitrate_cutoff',
name: "bitrate_cutoff",
tooltip: `Specify bitrate cutoff, files with a current bitrate lower then this will not be transcoded. Rate is in kbps. Leave empty to disable.
\\nExample:\\n
6000
\\nExample:\\n
4000`
4000`,
},
{
name: 'enable_10bit',
name: "enable_10bit",
tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
]
}
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
preset: "",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
infoLog: "",
};
// Check if inputs.container has been configured. If it hasn't then exit plugin.
if (inputs.container == "") {
response.infoLog += "☒Container has not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.processFile = false
return response
response.infoLog +=
"☒Container has not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false;
return response;
} else {
response.container = '.' + inputs.container
response.container = "." + inputs.container;
}
// Check if file is MKV, if so then add extra argument to drop data. MKV does not support data streams.
if (inputs.container == "mkv") {
extraArguments += "-map -0:d "
extraArguments += "-map -0:d ";
}
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
response.processFile = false
response.infoLog += "☒File is not a video. \n"
return response
response.processFile = false;
response.infoLog += "☒File is not a video. \n";
return response;
}
// Check if duration info is filled, if so times it by 0.0166667 to get time in minutes. If not filled then get duration of stream 0 and do the same.
if (typeof file.meta.Duration != 'undefined') {
var duration = (file.meta.Duration * 0.0166667)
if (typeof file.meta.Duration != "undefined") {
var duration = file.meta.Duration * 0.0166667;
} else {
var duration = (file.ffProbeData.streams[0].duration * 0.0166667)
var duration = file.ffProbeData.streams[0].duration * 0.0166667;
}
// Set up required variables.
var videoIdx = 0
var extraArguments = ""
var bitrateSettings = ""
var videoIdx = 0;
var extraArguments = "";
var bitrateSettings = "";
// Work out currentBitrate using "Bitrate = file size / (number of minutes * .0075)" - Used from here https://blog.frame.io/2017/03/06/calculate-video-bitrates/
var currentBitrate = ~~(file.file_size / (duration * 0.0075))
var currentBitrate = ~~(file.file_size / (duration * 0.0075));
// Use the same calculation used for currentBitrate but divide it in half to get targetBitrate. Logic of h265 can be half the bitrate as h264 without losing quality.
var targetBitrate = ~~((file.file_size / (duration * 0.0075)) / 2)
var targetBitrate = ~~(file.file_size / (duration * 0.0075) / 2);
// Allow some leeway under and over the targetBitrate.
var minimumBitrate = ~~(targetBitrate * 0.7)
var maximumBitrate = ~~(targetBitrate * 1.3)
var minimumBitrate = ~~(targetBitrate * 0.7);
var maximumBitrate = ~~(targetBitrate * 1.3);
// If targetBitrate comes out as 0 then something has gone wrong and bitrates could not be calculcated. Cancel plugin completely.
if (targetBitrate == "0") {
response.processFile = false
response.infoLog += "☒Target bitrate could not be calculated. Skipping this plugin. \n"
return response
response.processFile = false;
response.infoLog +=
"☒Target bitrate could not be calculated. Skipping this plugin. \n";
return response;
}
// Check if inputs.bitrate cutoff has something entered (Entered means user actually wants something to happen, empty would disable this).
if (inputs.bitrate_cutoff != "") {
// Checks if currentBitrate is below inputs.bitrate_cutoff, if so then cancel plugin without touching original files.
if (currentBitrate <= inputs.bitrate_cutoff) {
response.processFile = false
response.infoLog += `☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff}. Nothing to do, cancelling plugin. \n`
return response
response.processFile = false;
response.infoLog += `☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff}. Nothing to do, cancelling plugin. \n`;
return response;
}
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
// If set to true then add 10bit argument
extraArguments += `-pix_fmt p010le `
extraArguments += `-pix_fmt p010le `;
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is a video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "video") {
// Check if codec of stream is mjpeg, if so then remove this "video" stream. mjpeg are usually imbedded pictures that can cause havoc with plugins.
if (file.ffProbeData.streams[i].codec_name == 'mjpeg') {
extraArguments += `-map -v:${videoIdx} `
if (file.ffProbeData.streams[i].codec_name == "mjpeg") {
extraArguments += `-map -v:${videoIdx} `;
}
// Check if codec of stream is hevc AND check if file.container matches inputs.container. If so nothing for plugin to do.
if (file.ffProbeData.streams[i].codec_name == 'hevc' && file.container == inputs.container) {
response.processFile = false
response.infoLog += `☑File is already hevc & in ${inputs.container}. \n`
return response
if (
file.ffProbeData.streams[i].codec_name == "hevc" &&
file.container == inputs.container
) {
response.processFile = false;
response.infoLog += `☑File is already hevc & in ${inputs.container}. \n`;
return response;
}
// Check if codec of stream is hevc AND check if file.container does NOT match inputs.container. If so remux file.
if (file.ffProbeData.streams[i].codec_name == 'hevc' && file.container != '${inputs.container}') {
response.infoLog += `☒File is hevc but is not in ${inputs.container} container. Remuxing. \n`
response.preset = `, -map 0 -c copy ${extraArguments}`
if (
file.ffProbeData.streams[i].codec_name == "hevc" &&
file.container != "${inputs.container}"
) {
response.infoLog += `☒File is hevc but is not in ${inputs.container} container. Remuxing. \n`;
response.preset = `, -map 0 -c copy ${extraArguments}`;
response.processFile = true;
return response
return response;
}
// Increment videoIdx.
videoIdx++
videoIdx++;
}
}
// Set bitrateSettings variable using bitrate information calulcated earlier.
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`;
// Print to infoLog information around file & bitrate settings.
response.infoLog += `Container for output selected as ${inputs.container}. \n Current bitrate = ${~~(file.file_size / (duration * 0.0075))} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n`
response.infoLog += `Container for output selected as ${
inputs.container
}. \n Current bitrate = ${~~(
file.file_size /
(duration * 0.0075)
)} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n`;
// 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') { //if a h264 coded video is not HDR
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`
} 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`
}
response.preset += `,-map 0 -c:v hevc_nvenc -rc:v vbr_hq -cq:v 19 ${bitrateSettings} -spatial_aq:v 1 -rc-lookahead:v 32 -c:a copy -c:s copy -max_muxing_queue_size 4096 ${extraArguments}`
response.processFile = true
response.infoLog += `☒File is not hevc. Transcoding. \n`
return response
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") {
//if a h264 coded video is not HDR
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`;
} 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`;
}
response.preset += `,-map 0 -c:v hevc_nvenc -rc:v vbr_hq -cq:v 19 ${bitrateSettings} -spatial_aq:v 1 -rc-lookahead:v 32 -c:a copy -c:s copy -max_muxing_queue_size 4096 ${extraArguments}`;
response.processFile = true;
response.infoLog += `☒File is not hevc. Transcoding. \n`;
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,151 +7,162 @@ function details() {
Operation: "Transcode",
Description: `Files not in H265 will be transcoded into H265 using CPU with ffmpeg, settings are dependant on file bitrate, working by the logic that H265 can support the same ammount of data at half the bitrate of H264. \n\n`,
Version: "1.3",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js",
Tags: 'pre-processing,ffmpeg,video only,configurable,h265',
Inputs: [{
name: 'container',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js",
Tags: "pre-processing,ffmpeg,video only,configurable,h265",
Inputs: [
{
name: "container",
tooltip: `Specify output container of file, ensure that all stream types you may have are supported by your chosen container. mkv is recommended.
\\nExample:\\n
mkv
\\nExample:\\n
mp4`
mp4`,
},
{
name: 'bitrate_cutoff',
name: "bitrate_cutoff",
tooltip: `Specify bitrate cutoff, files with a current bitrate lower then this will not be transcoded. Rate is in kbps. Leave empty to disable.
\\nExample:\\n
6000
\\nExample:\\n
4000`
4000`,
},
{
name: 'enable_10bit',
name: "enable_10bit",
tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
]
}
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
preset: "",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
infoLog: "",
};
// Check if inputs.container has been configured. If it hasn't then exit plugin.
if (inputs.container == "") {
response.infoLog += "☒Container has not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.processFile = false
return response
response.infoLog +=
"☒Container has not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false;
return response;
} else {
response.container = '.' + inputs.container
response.container = "." + inputs.container;
}
// Check if file is MKV, if so then add extra argument to drop data. MKV does not support data streams.
if (inputs.container == "mkv") {
extraArguments += "-map -0:d "
extraArguments += "-map -0:d ";
}
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
response.processFile = false
response.infoLog += "☒File is not a video. \n"
return response
response.processFile = false;
response.infoLog += "☒File is not a video. \n";
return response;
}
// Check if duration info is filled, if so times it by 0.0166667 to get time in minutes. If not filled then get duration of stream 0 and do the same.
if (typeof file.meta.Duration != 'undefined') {
var duration = (file.meta.Duration * 0.0166667)
if (typeof file.meta.Duration != "undefined") {
var duration = file.meta.Duration * 0.0166667;
} else {
var duration = (file.ffProbeData.streams[0].duration * 0.0166667)
var duration = file.ffProbeData.streams[0].duration * 0.0166667;
}
// Set up required variables.
var videoIdx = -1
var extraArguments = ""
var bitrateSettings = ""
var videoIdx = -1;
var extraArguments = "";
var bitrateSettings = "";
// Work out currentBitrate using "Bitrate = file size / (number of minutes * .0075)" - Used from here https://blog.frame.io/2017/03/06/calculate-video-bitrates/
var currentBitrate = ~~(file.file_size / (duration * 0.0075))
var currentBitrate = ~~(file.file_size / (duration * 0.0075));
// Use the same calculation used for currentBitrate but divide it in half to get targetBitrate. Logic of h265 can be half the bitrate as h264 without losing quality.
var targetBitrate = ~~((file.file_size / (duration * 0.0075)) / 2)
var targetBitrate = ~~(file.file_size / (duration * 0.0075) / 2);
// Allow some leeway under and over the targetBitrate.
var minimumBitrate = ~~(targetBitrate * 0.7)
var maximumBitrate = ~~(targetBitrate * 1.3)
var minimumBitrate = ~~(targetBitrate * 0.7);
var maximumBitrate = ~~(targetBitrate * 1.3);
// If targetBitrate comes out as 0 then something has gone wrong and bitrates could not be calculcated. Cancel plugin completely.
if (targetBitrate == "0") {
response.processFile = false
response.infoLog += "☒Target bitrate could not be calculated. Skipping this plugin. \n"
return response
response.processFile = false;
response.infoLog +=
"☒Target bitrate could not be calculated. Skipping this plugin. \n";
return response;
}
// Check if inputs.bitrate cutoff has something entered (Entered means user actually wants something to happen, empty would disable this).
if (inputs.bitrate_cutoff != "") {
// Checks if currentBitrate is below inputs.bitrate_cutoff, if so then cancel plugin without touching original files.
if (currentBitrate <= inputs.bitrate_cutoff) {
response.processFile = false
response.infoLog += `☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff}. Nothing to do, cancelling plugin. \n`
return response
response.processFile = false;
response.infoLog += `☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff}. Nothing to do, cancelling plugin. \n`;
return response;
}
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
// If set to true then add 10bit argument
extraArguments += `-pix_fmt p010le `
extraArguments += `-pix_fmt p010le `;
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is a video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "video") {
// Check if codec of stream is mjpeg, if so then remove this "video" stream. mjpeg are usually imbedded pictures that can cause havoc with plugins.
if (file.ffProbeData.streams[i].codec_name == 'mjpeg') {
extraArguments += `-map -v:${videoIdx} `
if (file.ffProbeData.streams[i].codec_name == "mjpeg") {
extraArguments += `-map -v:${videoIdx} `;
}
// Check if codec of stream is hevc AND check if file.container matches inputs.container. If so nothing for plugin to do.
if (file.ffProbeData.streams[i].codec_name == 'hevc' && file.container == inputs.container) {
response.processFile = false
response.infoLog += `☑File is already hevc & in ${inputs.container}. \n`
return response
if (
file.ffProbeData.streams[i].codec_name == "hevc" &&
file.container == inputs.container
) {
response.processFile = false;
response.infoLog += `☑File is already hevc & in ${inputs.container}. \n`;
return response;
}
// Check if codec of stream is hevc AND check if file.container does NOT match inputs.container. If so remux file.
if (file.ffProbeData.streams[i].codec_name == 'hevc' && file.container != '${inputs.container}') {
response.infoLog += `☒File is hevc but is not in ${inputs.container} container. Remuxing. \n`
response.preset = `, -map 0 -c copy ${extraArguments}`
if (
file.ffProbeData.streams[i].codec_name == "hevc" &&
file.container != "${inputs.container}"
) {
response.infoLog += `☒File is hevc but is not in ${inputs.container} container. Remuxing. \n`;
response.preset = `, -map 0 -c copy ${extraArguments}`;
response.processFile = true;
return response
return response;
}
// Increment videoIdx.
videoIdx++
videoIdx++;
}
}
// Set bitrateSettings variable using bitrate information calulcated earlier.
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`;
// Print to infoLog information around file & bitrate settings.
response.infoLog += `Container for output selected as ${inputs.container}. \n Current bitrate = ${~~(file.file_size / (duration * 0.0075))} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n`
response.preset += `,-map 0 -c:v libx265 ${bitrateSettings} -c:a copy -c:s copy -max_muxing_queue_size 4096 ${extraArguments}`
response.processFile = true
response.infoLog += `☒File is not hevc. Transcoding. \n`
return response
response.infoLog += `Container for output selected as ${
inputs.container
}. \n Current bitrate = ${~~(
file.file_size /
(duration * 0.0075)
)} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n`;
response.preset += `,-map 0 -c:v libx265 ${bitrateSettings} -c:a copy -c:s copy -max_muxing_queue_size 4096 ${extraArguments}`;
response.processFile = true;
response.infoLog += `☒File is not hevc. Transcoding. \n`;
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,110 +7,119 @@ function details() {
Operation: "Clean",
Description: `This plugin removes title metadata from video/audio/subtitles, if it exists. Video checking is mandatory, audio and subtitles are optional.\n\n`,
Version: "1.2",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js",
Tags: 'pre-processing,ffmpeg,configurable',
Inputs: [{
name: 'clean_audio',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js",
Tags: "pre-processing,ffmpeg,configurable",
Inputs: [
{
name: "clean_audio",
tooltip: `Specify if audio titles should be checked & cleaned. Optional.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
{
name: 'clean_subtitles',
name: "clean_subtitles",
tooltip: `Specify if subtitle titles should be checked & cleaned. Optional.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
]
}
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
container: '.' + file.container,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
}
infoLog: "",
};
// Set up required variables.
var ffmpegCommandInsert = ''
var videoIdx = 0
var audioIdx = 0
var subtitleIdx = 0
var convert = false
var ffmpegCommandInsert = "";
var videoIdx = 0;
var audioIdx = 0;
var subtitleIdx = 0;
var convert = false;
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
console.log("File is not video")
response.infoLog += "☒File is not video \n"
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
}
// Check if overall file metadata title is not empty, if it's not empty set to "".
if (typeof file.meta.Title != 'undefined') try {
ffmpegCommandInsert += ` -metadata title="" `
convert = true
if (typeof file.meta.Title != "undefined")
try {
ffmpegCommandInsert += ` -metadata title="" `;
convert = true;
} catch (err) {}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) try {
for (var i = 0; i < file.ffProbeData.streams.length; i++)
try {
// Check if stream is a video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "video") {
// Check if stream title is not empty, if it's nto empty set to "".
if (typeof file.ffProbeData.streams[i].tags.title != 'undefined') {
response.infoLog += `☒Video stream title is not empty, most likely junk metadata. Removing title from stream ${i} \n`
ffmpegCommandInsert += ` -metadata:s:v:${videoIdx} title="" `
convert = true
if (typeof file.ffProbeData.streams[i].tags.title != "undefined") {
response.infoLog += `☒Video stream title is not empty, most likely junk metadata. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:v:${videoIdx} title="" `;
convert = true;
}
// Increment videoIdx.
videoIdx++
videoIdx++;
}
// Check if title metadata of audio stream has more then 3 full stops. If so then it's likely to be junk metadata so remove.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && inputs.clean_audio.toLowerCase() == "true") {
if (file.ffProbeData.streams[i].tags.title.split('.').length - 1 > 3) {
response.infoLog += `☒More then 3 full stops detected in audio title, likely to be junk metadata. Removing title from stream ${i} \n`
ffmpegCommandInsert += ` -metadata:s:a:${audioIdx} title="" `
convert = true
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
inputs.clean_audio.toLowerCase() == "true"
) {
if (file.ffProbeData.streams[i].tags.title.split(".").length - 1 > 3) {
response.infoLog += `☒More then 3 full stops detected in audio title, likely to be junk metadata. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:a:${audioIdx} title="" `;
convert = true;
}
// Increment audioIdx.
audioIdx++
audioIdx++;
}
// Check if title metadata of subtitle stream has more then 3 full stops. If so then it's likely to be junk metadata so remove.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" && inputs.clean_subtitles.toLowerCase() == "true") {
if (file.ffProbeData.streams[i].tags.title.split('.').length - 1 > 3) {
response.infoLog += `☒More then 3 full stops detected in subtitle title, likely to be junk metadata. Removing title from stream ${i} \n`
ffmpegCommandInsert += ` -metadata:s:s:${subtitleIdx} title="" `
convert = true
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" &&
inputs.clean_subtitles.toLowerCase() == "true"
) {
if (file.ffProbeData.streams[i].tags.title.split(".").length - 1 > 3) {
response.infoLog += `☒More then 3 full stops detected in subtitle title, likely to be junk metadata. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:s:${subtitleIdx} title="" `;
convert = true;
}
// Increment subtitleIdx.
subtitleIdx++
subtitleIdx++;
}
} catch (err) {}
// Convert file if convert variable is set to true.
if (convert == true) {
response.infoLog += "☒File has title metadata. Removing \n"
response.preset = `,${ffmpegCommandInsert} -c copy -map 0 -max_muxing_queue_size 4096`
response.infoLog += "☒File has title metadata. Removing \n";
response.preset = `,${ffmpegCommandInsert} -c copy -map 0 -max_muxing_queue_size 4096`;
response.reQueueAfter = true;
response.processFile = true;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,10 +7,12 @@ function details() {
Operation: "Clean",
Description: `This plugin keeps only specified language audio tracks & can tags those that have an unknown language. \n\n`,
Version: "2.2",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js",
Tags: 'pre-processing,ffmpeg,audio only,configurable',
Inputs: [{
name: 'language',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js",
Tags: "pre-processing,ffmpeg,audio only,configurable",
Inputs: [
{
name: "language",
tooltip: `Specify language tag/s here for the audio tracks you'd like to keep, recommended to keep "und" as this stands for undertermined, some files may not have the language specified. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nExample:\\n
eng
@ -19,169 +21,201 @@ function details() {
eng,und
\\nExample:\\n
eng,und,jap`
eng,und,jap`,
},
{
name: 'commentary',
name: "commentary",
tooltip: `Specify if audio tracks that contain commentary/description should be removed.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
{
name: 'tag_language',
name: "tag_language",
tooltip: `Specify a single language for audio tracks with no language or unknown language to be tagged with, leave empty to disable, you must have "und" in your list of languages to keep for this to function. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nExample:\\n
eng
\\nExample:\\n
por`
por`,
},
{
name: 'tag_title',
name: "tag_title",
tooltip: `Specify audio tracks with no title to be tagged with the number of channels they contain. Do NOT use this with mp4, as mp4 does not support title tags.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
]
}
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
container: '.' + file.container,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
}
infoLog: "",
};
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
console.log("File is not video")
response.infoLog += "☒File is not video \n"
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
}
// Check if inputs.language has been configured. If it hasn't then exit plugin.
if (inputs.language == "") {
response.infoLog += "☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.infoLog +=
"☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false;
return response
return response;
}
// Set up required variables.
var language = inputs.language.split(",")
var ffmpegCommandInsert = ''
var convert = false
var audioIdx = 0
var audioStreamsRemoved = 0
var audioStreamCount = file.ffProbeData.streams.filter(row => (row.codec_type.toLowerCase() == "audio")).length;
var language = inputs.language.split(",");
var ffmpegCommandInsert = "";
var convert = false;
var audioIdx = 0;
var audioStreamsRemoved = 0;
var audioStreamCount = file.ffProbeData.streams.filter(
(row) => row.codec_type.toLowerCase() == "audio"
).length;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
// Catch error here incase the language metadata is completely missing.
try {
// Check if stream is audio AND checks if the tracks language code does not match any of the languages entered in inputs.language.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && language.indexOf(file.ffProbeData.streams[i].tags.language.toLowerCase()) === -1) {
audioStreamsRemoved++
ffmpegCommandInsert += `-map -0:a:${audioIdx} `
response.infoLog += `☒Audio stream detected as being an unwanted language, removing. Audio stream 0:a:${audioIdx} - ${file.ffProbeData.streams[i].tags.language.toLowerCase()} \n`
convert = true
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
language.indexOf(
file.ffProbeData.streams[i].tags.language.toLowerCase()
) === -1
) {
audioStreamsRemoved++;
ffmpegCommandInsert += `-map -0:a:${audioIdx} `;
response.infoLog += `☒Audio stream detected as being an unwanted language, removing. Audio stream 0:a:${audioIdx} - ${file.ffProbeData.streams[
i
].tags.language.toLowerCase()} \n`;
convert = true;
}
} catch (err) {}
// Catch error here incase the title metadata is completely missing.
try {
// Check if inputs.commentary is set to true AND if stream is audio AND then checks for stream titles with the following "commentary, description, sdh". Removing any streams that are applicable.
if (inputs.commentary.toLowerCase() == "true" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && (file.ffProbeData.streams[i].tags.title.toLowerCase().includes('commentary') || file.ffProbeData.streams[i].tags.title.toLowerCase().includes('description') || file.ffProbeData.streams[i].tags.title.toLowerCase().includes('sdh'))) {
audioStreamsRemoved++
ffmpegCommandInsert += `-map -0:a:${audioIdx} `
response.infoLog += `☒Audio stream detected as being Commentary or Description, removing. Audio stream 0:a:${audioIdx} - ${file.ffProbeData.streams[i].tags.title}. \n`
convert = true
if (
inputs.commentary.toLowerCase() == "true" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
(file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("commentary") ||
file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("description") ||
file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh"))
) {
audioStreamsRemoved++;
ffmpegCommandInsert += `-map -0:a:${audioIdx} `;
response.infoLog += `☒Audio stream detected as being Commentary or Description, removing. Audio stream 0:a:${audioIdx} - ${file.ffProbeData.streams[i].tags.title}. \n`;
convert = true;
}
} catch (err) {}
// Check if inputs.tag_language has something entered (Entered means user actually wants something to happen, empty would disable this) AND checks that stream is audio.
if (inputs.tag_language != "" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
if (
inputs.tag_language != "" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
// Catch error here incase the metadata is completely missing.
try {
// Look for audio with "und" as metadata language.
if (file.ffProbeData.streams[i].tags.language.toLowerCase().includes('und')) {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `
response.infoLog += `☒Audio stream detected as having unknown language tagged, tagging as ${inputs.tag_language}. \n`
convert = true
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes("und")
) {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Audio stream detected as having unknown language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
} catch (err) {}
// Checks if the tags metadata is completely missing, if so this would cause playback to show language as "undefined". No catch error here otherwise it would never detect the metadata as missing.
if (typeof file.ffProbeData.streams[i].tags == 'undefined') {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `
response.infoLog += `☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`
convert = true
if (typeof file.ffProbeData.streams[i].tags == "undefined") {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
// Checks if the tags.language metadata is completely missing, if so this would cause playback to show language as "undefined". No catch error here otherwise it would never detect the metadata as missing.
else {
if (typeof file.ffProbeData.streams[i].tags.language == 'undefined') {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `
response.infoLog += `☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`
convert = true
if (typeof file.ffProbeData.streams[i].tags.language == "undefined") {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
}
}
try {
// Check if title metadata is missing from any streams AND inputs.tag_title set to true AND if stream type is audio. Add title to any applicable streams.
if (typeof file.ffProbeData.streams[i].tags.title == 'undefined' && inputs.tag_title.toLowerCase() == "true" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
if (
typeof file.ffProbeData.streams[i].tags.title == "undefined" &&
inputs.tag_title.toLowerCase() == "true" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
if (file.ffProbeData.streams[i].channels == "8") {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="7.1" `
response.infoLog += `☒Audio stream detected as 8 channel audio track with no title, tagging title. Audio stream 0:a:${audioIdx} tagged as "7.1" \n`
convert = true
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="7.1" `;
response.infoLog += `☒Audio stream detected as 8 channel audio track with no title, tagging title. Audio stream 0:a:${audioIdx} tagged as "7.1" \n`;
convert = true;
}
if (file.ffProbeData.streams[i].channels == "6") {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="5.1" `
response.infoLog += `☒Audio stream detected as 6 channel audio track with no title, tagging title. Audio stream 0:a:${audioIdx} tagged as "5.1" \n`
convert = true
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="5.1" `;
response.infoLog += `☒Audio stream detected as 6 channel audio track with no title, tagging title. Audio stream 0:a:${audioIdx} tagged as "5.1" \n`;
convert = true;
}
if (file.ffProbeData.streams[i].channels == "2") {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="2.0" `
response.infoLog += `☒Audio stream detected as 2 channel audio track with no title, tagging title. Audio stream 0:a:${audioIdx} tagged as "2.0" \n`
convert = true
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="2.0" `;
response.infoLog += `☒Audio stream detected as 2 channel audio track with no title, tagging title. Audio stream 0:a:${audioIdx} tagged as "2.0" \n`;
convert = true;
}
}
} catch (err) {}
// Check if stream type is audio and increment audioIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
}
// Failsafe to cancel processing if all streams would be removed following this plugin. We don't want no audio.
if (audioStreamsRemoved == audioStreamCount) {
response.infoLog += "☒Cancelling plugin otherwise all audio tracks would be removed. \n"
response.processFile = false
return response
response.infoLog +=
"☒Cancelling plugin otherwise all audio tracks would be removed. \n";
response.processFile = false;
return response;
}
// Convert file if convert variable is set to true.
if (convert === true) {
response.processFile = true
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`
response.container = '.' + file.container
response.reQueueAfter = true
response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`;
response.container = "." + file.container;
response.reQueueAfter = true;
} else {
response.processFile = false
response.infoLog += "☑File doesn't contain audio tracks which are unwanted or that require tagging.\n"
response.processFile = false;
response.infoLog +=
"☑File doesn't contain audio tracks which are unwanted or that require tagging.\n";
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,139 +7,166 @@ function details() {
Operation: "Clean",
Description: `This plugin keeps only specified language subtitle tracks & can tag those that have an unknown language. \n\n`,
Version: "2.2",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js",
Tags: 'pre-processing,ffmpeg,subtitle only,configurable',
Inputs: [{
name: 'language',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js",
Tags: "pre-processing,ffmpeg,subtitle only,configurable",
Inputs: [
{
name: "language",
tooltip: `Specify language tag/s here for the subtitle tracks you'd like to keep. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nExample:\\n
eng
\\nExample:\\n
eng,jap`
eng,jap`,
},
{
name: 'commentary',
name: "commentary",
tooltip: `Specify if subtitle tracks that contain commentary/description should be removed.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
{
name: 'tag_language',
name: "tag_language",
tooltip: `Specify a single language for subtitle tracks with no language or unknown language to be tagged with, leave empty to disable. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nExample:\\n
eng
\\nExample:\\n
por`
por`,
},
]
}
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
container: '.' + file.container,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
}
infoLog: "",
};
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
console.log("File is not video")
response.infoLog += "☒File is not video \n"
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
}
// Check if inputs.language has been configured. If it hasn't then exit plugin.
if (inputs.language == "") {
response.infoLog += "☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.infoLog +=
"☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false;
return response
return response;
}
// Set up required variables.
var language = inputs.language.split(",")
var ffmpegCommandInsert = ''
var subtitleIdx = 0
var convert = false
var language = inputs.language.split(",");
var ffmpegCommandInsert = "";
var subtitleIdx = 0;
var convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
// Catch error here incase the language metadata is completely missing.
try {
// Check if stream is subtitle AND checks if the tracks language code does not match any of the languages entered in inputs.language.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" && language.indexOf(file.ffProbeData.streams[i].tags.language.toLowerCase()) === -1) {
ffmpegCommandInsert += `-map -0:s:${subtitleIdx} `
response.infoLog += `☒Subtitle stream detected as being an unwanted language, removing. Subtitle stream 0:s:${subtitleIdx} - ${file.ffProbeData.streams[i].tags.language.toLowerCase()} \n`
convert = true
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" &&
language.indexOf(
file.ffProbeData.streams[i].tags.language.toLowerCase()
) === -1
) {
ffmpegCommandInsert += `-map -0:s:${subtitleIdx} `;
response.infoLog += `☒Subtitle stream detected as being an unwanted language, removing. Subtitle stream 0:s:${subtitleIdx} - ${file.ffProbeData.streams[
i
].tags.language.toLowerCase()} \n`;
convert = true;
}
} catch (err) {}
// Catch error here incase the title metadata is completely missing.
try {
// Check if inputs.commentary is set to true AND if stream is subtitle AND then checks for stream titles with the following "commentary, description, sdh". Removing any streams that are applicable.
if (inputs.commentary.toLowerCase() == "true" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" && (file.ffProbeData.streams[i].tags.title.toLowerCase().includes('commentary') || file.ffProbeData.streams[i].tags.title.toLowerCase().includes('description') || file.ffProbeData.streams[i].tags.title.toLowerCase().includes('sdh'))) {
ffmpegCommandInsert += `-map -0:s:${subtitleIdx} `
response.infoLog += `☒Subtitle stream detected as being Commentary or Description, removing. Subtitle stream 0:s:${SubtitleIdx} - ${file.ffProbeData.streams[i].tags.title}. \n`
convert = true
if (
inputs.commentary.toLowerCase() == "true" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" &&
(file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("commentary") ||
file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("description") ||
file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh"))
) {
ffmpegCommandInsert += `-map -0:s:${subtitleIdx} `;
response.infoLog += `☒Subtitle stream detected as being Commentary or Description, removing. Subtitle stream 0:s:${SubtitleIdx} - ${file.ffProbeData.streams[i].tags.title}. \n`;
convert = true;
}
} catch (err) {}
// Check if inputs.tag_language has something entered (Entered means user actually wants something to happen, empty would disable this) AND checks that stream is subtitle.
if (inputs.tag_language != "" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
if (
inputs.tag_language != "" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
// Catch error here incase the metadata is completely missing.
try {
// Look for subtitle with "und" as metadata language.
if (file.ffProbeData.streams[i].tags.language.toLowerCase().includes('und')) {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `
response.infoLog += `☒Subtitle stream detected as having unknown language tagged, tagging as ${inputs.tag_language}. \n`
convert = true
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes("und")
) {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Subtitle stream detected as having unknown language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
} catch (err) {}
// Checks if the tags metadata is completely missing, if so this would cause playback to show language as "undefined". No catch error here otherwise it would never detect the metadata as missing.
if (typeof file.ffProbeData.streams[i].tags == 'undefined') {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `
response.infoLog += `☒Subtitle stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`
convert = true
if (typeof file.ffProbeData.streams[i].tags == "undefined") {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Subtitle stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
// Checks if the tags.language metadata is completely missing, if so this would cause playback to show language as "undefined". No catch error here otherwise it would never detect the metadata as missing.
else {
if (typeof file.ffProbeData.streams[i].tags.language == 'undefined') {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `
response.infoLog += `☒Subtitle stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`
convert = true
if (typeof file.ffProbeData.streams[i].tags.language == "undefined") {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Subtitle stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
}
}
// Check if stream type is subtitle and increment subtitleIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
subtitleIdx++
subtitleIdx++;
}
}
// Convert file if convert variable is set to true.
if (convert === true) {
response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`
response.container = '.' + file.container
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`;
response.container = "." + file.container;
response.reQueueAfter = true;
} else {
response.processFile = false;
response.infoLog += "☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n"
response.infoLog +=
"☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n";
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -8,61 +8,63 @@ function details() {
Description: `This plugin can convert any 2.0 audio track/s to AAC and can create downmixed audio tracks. \n\n`,
Version: "2.1",
Link: "",
Tags: 'pre-processing,ffmpeg,audio only,configurable',
Inputs: [{
name: 'aac_stereo',
Tags: "pre-processing,ffmpeg,audio only,configurable",
Inputs: [
{
name: "aac_stereo",
tooltip: `Specify if any 2.0 audio tracks should be converted to aac for maximum compatability with devices. Optional.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
{
name: 'downmix',
name: "downmix",
tooltip: `Specify if downmixing should be used to create extra audio tracks. I.e if you have an 8ch but no 2ch or 6ch, create the missing audio tracks from the 8 ch. Likewise if you only have 6ch, create the missing 2ch from it. Optional.
\\nExample:\\n
true
\\nExample:\\n
false`
false`,
},
]
}
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
container: '.' + file.container,
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: '',
}
infoLog: "",
};
// Check if both inputs.aac_stereo AND inputs.downmix have been left empty. If they have then exit plugin.
if (inputs && inputs.aac_stereo == "" && inputs.downmix == "") {
response.infoLog += "☒Neither aac_stereo or downmix options have been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.processFile = false
return response
response.infoLog +=
"☒Neither aac_stereo or downmix options have been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false;
return response;
}
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
console.log("File is not video")
response.infoLog += "☒File is not video. \n"
console.log("File is not video");
response.infoLog += "☒File is not video. \n";
response.processFile = false;
return response
return response;
}
// Set up required variables.
var ffmpegCommandInsert = ''
var audioIdx = 0
var has2Channel = false
var has6Channel = false
var has8Channel = false
var convert = false
var ffmpegCommandInsert = "";
var audioIdx = 0;
var has2Channel = false;
var has6Channel = false;
var has8Channel = false;
var convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
@ -70,13 +72,13 @@ function plugin(file, librarySettings, inputs) {
// Go through all audio streams and check if 2,6 & 8 channel tracks exist or not.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
if (file.ffProbeData.streams[i].channels == "2") {
has2Channel = true
has2Channel = true;
}
if (file.ffProbeData.streams[i].channels == "6") {
has6Channel = true
has6Channel = true;
}
if (file.ffProbeData.streams[i].channels == "8") {
has8Channel = true
has8Channel = true;
}
}
} catch (err) {}
@ -91,16 +93,26 @@ function plugin(file, librarySettings, inputs) {
// Check if inputs.downmix is set to true.
if (inputs.downmix.toLowerCase() == "true") {
// Check if file has 8 channel audio but no 6 channel, if so then create extra downmix from the 8 channel.
if (has8Channel == true && has6Channel == false && file.ffProbeData.streams[i].channels == "8") {
ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} ac3 -ac 6 -metadata:s:a:${audioIdx} title="5.1 " `
response.infoLog += "☒Audio track is 8 channel, no 6 channel exists. Creating 6 channel from 8 channel. \n"
convert = true
if (
has8Channel == true &&
has6Channel == false &&
file.ffProbeData.streams[i].channels == "8"
) {
ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} ac3 -ac 6 -metadata:s:a:${audioIdx} title="5.1 " `;
response.infoLog +=
"☒Audio track is 8 channel, no 6 channel exists. Creating 6 channel from 8 channel. \n";
convert = true;
}
// Check if file has 6 channel audio but no 2 channel, if so then create extra downmix from the 6 channel.
if (has6Channel == true && has2Channel == false && file.ffProbeData.streams[i].channels == "6") {
ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} aac -ac 2 -metadata:s:a:${audioIdx} title="2.0 " `
response.infoLog += "☒Audio track is 6 channel, no 2 channel exists. Creating 2 channel from 6 channel. \n"
convert = true
if (
has6Channel == true &&
has2Channel == false &&
file.ffProbeData.streams[i].channels == "6"
) {
ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} aac -ac 2 -metadata:s:a:${audioIdx} title="2.0 " `;
response.infoLog +=
"☒Audio track is 6 channel, no 2 channel exists. Creating 2 channel from 6 channel. \n";
convert = true;
}
}
} catch (err) {}
@ -110,28 +122,30 @@ function plugin(file, librarySettings, inputs) {
// Check if inputs.aac_stereo is set to true.
if (inputs.aac_stereo.toLowerCase() == "true") {
// Check if codec_name for stream is NOT aac AND check if channel ammount is 2.
if (file.ffProbeData.streams[i].codec_name != "aac" && file.ffProbeData.streams[i].channels == "2") {
ffmpegCommandInsert += `-c:a:${audioIdx} aac `
response.infoLog += "☒Audio track is 2 channel but is not AAC. Converting. \n"
convert = true
if (
file.ffProbeData.streams[i].codec_name != "aac" &&
file.ffProbeData.streams[i].channels == "2"
) {
ffmpegCommandInsert += `-c:a:${audioIdx} aac `;
response.infoLog +=
"☒Audio track is 2 channel but is not AAC. Converting. \n";
convert = true;
}
}
} catch (err) {}
audioIdx++
audioIdx++;
}
}
// Convert file if convert variable is set to true.
if (convert == true) {
response.processFile = true;
response.preset = `, -map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} -strict -2 -c:s copy -max_muxing_queue_size 4096 `
response.preset = `, -map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} -strict -2 -c:s copy -max_muxing_queue_size 4096 `;
} else {
response.infoLog += "☑File contains all required audio formats. \n"
response.infoLog += "☑File contains all required audio formats. \n";
response.processFile = false;
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,30 +7,31 @@ function details() {
Operation: "Order",
Description: `Orders streams into Video first, then Audio (2ch, 6ch, 8ch) and finally Subtitles. \n\n`,
Version: "1.1",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js",
Tags: 'pre-processing,ffmpeg,'
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js",
Tags: "pre-processing,ffmpeg,",
};
}
function plugin(file) {
var response = {
processFile: false,
preset: '',
container: '.' + file.container,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
infoLog: '',
}
infoLog: "",
};
// Set up required variables.
var ffmpegCommandInsert = ''
var videoIdx = 0
var audioIdx = 0
var audio2Idx = 0
var audio6Idx = 0
var audio8Idx = 0
var subtitleIdx = 0
var convert = false
var ffmpegCommandInsert = "";
var videoIdx = 0;
var audioIdx = 0;
var audio2Idx = 0;
var audio6Idx = 0;
var audio8Idx = 0;
var subtitleIdx = 0;
var convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
@ -39,55 +40,55 @@ function plugin(file) {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "video") {
// Check if audioIdx or subtitleIdx do NOT equal 0, if they do then it means a audio or subtitle track has already appeared before the video track so file needs to be organized.
if (audioIdx != "0" || subtitleIdx != "0") {
convert = true
response.infoLog += "☒ Video not first. \n"
convert = true;
response.infoLog += "☒ Video not first. \n";
}
// Increment videoIdx.
videoIdx++
videoIdx++;
}
// Check if stream is audio.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
// Check if subtitleIdx does NOT equal 0, if it does then it means a subtitle track has already appeared before an audio track so file needs to be organized.
if (subtitleIdx != "0") {
convert = true
response.infoLog += "☒ Audio not second. \n"
convert = true;
response.infoLog += "☒ Audio not second. \n";
}
// Increment audioIdx.
audioIdx++
audioIdx++;
// Check if audio track is 2 channel.
if (file.ffProbeData.streams[i].channels == "2") {
// Check if audio6Idx or audio8Idx do NOT equal 0, if they do then it means a 6 channel or 8 channel audio track has already appeared before the 2 channel audio track so file needs to be organized.
if (audio6Idx != "0" || audio8Idx != "0") {
convert = true
response.infoLog += "☒ Audio 2ch not first. \n"
convert = true;
response.infoLog += "☒ Audio 2ch not first. \n";
}
// Increment audio2Idx.
audio2Idx++
audio2Idx++;
}
// Check if audio track is 6 channel.
if (file.ffProbeData.streams[i].channels == "6") {
// Check if audio8Idx does NOT equal 0, if it does then it means a 8 channel audio track has already appeared before the 6 channel audio track so file needs to be organized.
if (audio8Idx != "0") {
convert = true
response.infoLog += "☒ Audio 6ch not second. \n"
convert = true;
response.infoLog += "☒ Audio 6ch not second. \n";
}
// Increment audio6Idx.
audio6Idx++
audio6Idx++;
}
// Check if audio track is 8 channel.
if (file.ffProbeData.streams[i].channels == "8") {
// Increment audio8Idx.
audio8Idx++
audio8Idx++;
}
}
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
// Increment subtitleIdx
subtitleIdx++
subtitleIdx++;
}
} catch (err) {}
}
@ -96,8 +97,11 @@ function plugin(file) {
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is video AND is not a mjpeg.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "video" && file.ffProbeData.streams[i].codec_name.toLowerCase() != "mjpeg") {
ffmpegCommandInsert += `-map 0:${i} `
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "video" &&
file.ffProbeData.streams[i].codec_name.toLowerCase() != "mjpeg"
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
}
@ -106,8 +110,11 @@ function plugin(file) {
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is audio AND 2 channel.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].channels == "2") {
ffmpegCommandInsert += `-map 0:${i} `
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].channels == "2"
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
}
@ -116,8 +123,11 @@ function plugin(file) {
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is audio AND 6 channel.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].channels == "6") {
ffmpegCommandInsert += `-map 0:${i} `
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].channels == "6"
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
}
@ -126,8 +136,11 @@ function plugin(file) {
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is audio AND 8 channel.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].channels == "8") {
ffmpegCommandInsert += `-map 0:${i} `
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].channels == "8"
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
}
@ -136,8 +149,13 @@ function plugin(file) {
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is audio AND not 2, 6 or 8 channel.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].channels != "2" && file.ffProbeData.streams[i].channels != "6" && file.ffProbeData.streams[i].channels != "8") {
ffmpegCommandInsert += `-map 0:${i} `
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].channels != "2" &&
file.ffProbeData.streams[i].channels != "6" &&
file.ffProbeData.streams[i].channels != "8"
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
}
@ -147,7 +165,7 @@ function plugin(file) {
try {
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
ffmpegCommandInsert += `-map 0:${i} `
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
}
@ -155,15 +173,15 @@ function plugin(file) {
// Convert file if convert variable is set to true.
if (convert == true) {
response.processFile = true;
response.preset = `,${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`
response.preset = `,${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`;
response.reQueueAfter = true;
response.infoLog += "☒ Streams are out of order, reorganizing streams. Video, Audio, Subtitles. \n"
response.infoLog +=
"☒ Streams are out of order, reorganizing streams. Video, Audio, Subtitles. \n";
} else {
response.infoLog += "☑ Streams are in expected order. \n "
response.infoLog += "☑ Streams are in expected order. \n ";
response.processFile = false;
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,58 +7,63 @@ function details() {
Operation: "Clean",
Description: `Identify any unwanted image formats in the file and remove those streams. MJPEG & PNG \n\n`,
Version: "1.1",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js",
Tags: 'pre-processing,ffmpeg,video only'
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js",
Tags: "pre-processing,ffmpeg,video only",
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
preset: "",
handBrakeMode: false,
container: '.' + file.container,
container: "." + file.container,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
infoLog: "",
};
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
response.processFile = false
response.infoLog += "☒File is not a video. \n"
return response
response.processFile = false;
response.infoLog += "☒File is not a video. \n";
return response;
}
// Set up required variables.
var videoIdx = 0
var extraArguments = ""
var convert = false
var videoIdx = 0;
var extraArguments = "";
var convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "video") {
// Check if stream codec is mjpeg or png. Remove if so.
if (file.ffProbeData.streams[i].codec_name == 'mjpeg' || file.ffProbeData.streams[i].codec_name == 'png') {
convert = true
extraArguments += `-map -v:${videoIdx} `
if (
file.ffProbeData.streams[i].codec_name == "mjpeg" ||
file.ffProbeData.streams[i].codec_name == "png"
) {
convert = true;
extraArguments += `-map -v:${videoIdx} `;
}
// Increment videoIdx.
videoIdx++
videoIdx++;
}
}
// Convert file if convert variable is set to true.
if (convert === true) {
response.preset += `,-map 0 -c copy -max_muxing_queue_size 4096 ${extraArguments}`
response.infoLog += `☒File has image format stream, removing. \n`
response.preset += `,-map 0 -c copy -max_muxing_queue_size 4096 ${extraArguments}`;
response.infoLog += `☒File has image format stream, removing. \n`;
response.processFile = true;
} else {
response.processFile = false;
response.infoLog += "☑File doesn't contain any unwanted image format streams.\n"
response.infoLog +=
"☑File doesn't contain any unwanted image format streams.\n";
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,11 +7,13 @@ module.exports.details = function details() {
Operation: "",
Description: `Send request for file to be scanned by plex_autoscan. https://github.com/l3uddz/plex_autoscan \n\n`,
Version: "1.1",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_MigzPlex_Autoscan.js",
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_MigzPlex_Autoscan.js",
Tags: "3rd party,post-processing,configurable",
Inputs: [{
name: 'autoscan_address',
Inputs: [
{
name: "autoscan_address",
tooltip: `
Enter the IP address/URL for autoscan. Must include http(s)://
@ -19,66 +21,74 @@ module.exports.details = function details() {
http://192.168.0.10
\\nExample:\\n
https://subdomain.domain.tld`
https://subdomain.domain.tld`,
},
{
name: 'autoscan_port',
name: "autoscan_port",
tooltip: `
Enter the port Autoscan is using, default is 3468
\\nExample:\\n
3468`
3468`,
},
{
name: 'autoscan_passkey',
name: "autoscan_passkey",
tooltip: `
Enter the autoscan passkey.
\\nExample:\\n
9c4b81fe234e4d6eb9011cefe514d915`
9c4b81fe234e4d6eb9011cefe514d915`,
},
]
}
}
],
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
// Check if all inputs have been configured. If they haven't then exit plugin.
if (inputs && inputs.autoscan_address == "" && inputs.autoscan_port == "" && inputs.autoscan_passkey == "") {
response.infoLog += "☒Autoscan options have not been configured, please configure all options. Skipping this plugin. \n"
if (
inputs &&
inputs.autoscan_address == "" &&
inputs.autoscan_port == "" &&
inputs.autoscan_passkey == ""
) {
response.infoLog +=
"☒Autoscan options have not been configured, please configure all options. Skipping this plugin. \n";
response.processFile = false;
return response
return response;
}
// Take variable inputs and turn them into read only variable
const request = require('request')
const ADDRESS = inputs.autoscan_address
const PORT = inputs.autoscan_port
const PASSKEY = inputs.autoscan_passkey
const request = require("request");
const ADDRESS = inputs.autoscan_address;
const PORT = inputs.autoscan_port;
const PASSKEY = inputs.autoscan_passkey;
// Set up required variables.
var response = ""
filepath = `${file.file}`
var response = "";
filepath = `${file.file}`;
// Set content of request/post.
request.post({
request.post(
{
headers: {
'content-type': 'application/json'
"content-type": "application/json",
},
url: `${ADDRESS}:${PORT}/${PASSKEY}`,
form: {
"eventType": "Manual",
"filepath": `${filepath}`
}
}, (error, res, body) => {
eventType: "Manual",
filepath: `${filepath}`,
},
},
(error, res, body) => {
if (error) {
console.error(error)
console.error(error);
}
console.log(`statusCode: ${res.statusCode}`)
console.log(body)
})
console.log("request next")
console.log(request.post)
console.log(`statusCode: ${res.statusCode}`);
console.log(body);
}
);
console.log("request next");
console.log(request.post);
};

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta",
Stage: "Pre-processing",
@ -11,72 +7,52 @@ function details() {
Description: `[Contains built-in filter] This plugin removes metadata (if a title exists). The output container is mp4. \n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta.js",
Tags:'pre-processing,ffmpeg',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta.js",
Tags: "pre-processing,ffmpeg",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file)
var jsonString = JSON.stringify(file);
///
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n"
response.preset = ',-map_metadata -1 -map 0 -c copy'
response.infoLog += "☒File has title metadata \n";
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_a9hd_FFMPEG_Transcode_Specific_Audio_Stream_Codecs",
Stage: "Pre-processing",
@ -12,10 +8,10 @@ module.exports.details = function details() {
Description: `[TESTING][Contains built-in filter] Transcode audio streams with specific codecs into another codec. \n\n`,
Version: "1.00",
Link: "",
Tags:'pre-processing,audio only,ffmpeg,configurable',
Tags: "pre-processing,audio only,ffmpeg,configurable",
Inputs: [
{
name: 'codecs_to_transcode',
name: "codecs_to_transcode",
tooltip: `Specifiy the codecs which you'd like to transcode
\\nExample:\\n
@ -30,10 +26,10 @@ module.exports.details = function details() {
`
`,
},
{
name: 'codec',
name: "codec",
tooltip: `Specify the codec you'd like to transcode into:
\\n aac
@ -52,98 +48,74 @@ module.exports.details = function details() {
`
}
]
}
}
`,
},
],
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
infoLog: "",
};
if (inputs.codecs_to_transcode === undefined || inputs.codec === undefined) {
response.processFile = false;
response.infoLog += "☒ Inputs not entered! \n";
return response;
}
if (inputs.codecs_to_transcode === undefined
|| inputs.codec === undefined
) {
var encoder = inputs.codec;
response.processFile = false
response.infoLog += "☒ Inputs not entered! \n"
return response
if (encoder == "mp3") {
encoder = `libmp3lame`;
} else if (encoder == "dts") {
encoder = `dca`;
}
var codecs_to_transcode = inputs.codecs_to_transcode.split(",");
var hasStreamsToTranscode = false;
var encoder = inputs.codec
if (encoder == 'mp3') {
encoder = `libmp3lame`
} else if (encoder == 'dts') {
encoder = `dca`
}
var codecs_to_transcode = inputs.codecs_to_transcode.split(',')
var hasStreamsToTranscode = false
var ffmpegCommand = `, -c copy -map 0:v `
var ffmpegCommand = `, -c copy -map 0:v `;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].codec_name &&
codecs_to_transcode.includes(file.ffProbeData.streams[i].codec_name.toLowerCase())
codecs_to_transcode.includes(
file.ffProbeData.streams[i].codec_name.toLowerCase()
)
) {
ffmpegCommand += ` -map 0:${i} -c:${i} ${encoder} `
hasStreamsToTranscode = true
ffmpegCommand += ` -map 0:${i} -c:${i} ${encoder} `;
hasStreamsToTranscode = true;
}
}
ffmpegCommand += ` -map 0:s? -map 0:d? `;
ffmpegCommand += ` -map 0:s? -map 0:d? `
console.log
console.log;
if (hasStreamsToTranscode == false) {
response.processFile = false
response.infoLog += "☑ File does not have any streams that need to be transcoded! \n"
return response
response.processFile = false;
response.infoLog +=
"☑ File does not have any streams that need to be transcoded! \n";
return response;
} else {
response.processFile = true;
response.preset = ffmpegCommand
response.container = '.' + file.container
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = ffmpegCommand;
response.container = "." + file.container;
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒ File has streams which aren't in desired codec! \n`
return response
response.infoLog += `☒ File has streams which aren't in desired codec! \n`;
return response;
}
}
};

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta",
Stage: "Pre-processing",
@ -11,121 +7,98 @@ function details() {
Description: `[Contains built-in filter] If the file is not in h265 it will be trancoded into h265 with FFmpeg using the following command '-e x265 -q 22 --encoder-preset slow --all-audio --all-subtitles copy:aac -E fdk_aac -Q 4 -x aq-mode=3'. If no aac, aac track will be added. Subtitles are kept. Metadata is removed.\n\n
`,
Version: "1.01",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta.js",
Tags:'pre-processing,ffmpeg,h265,',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta.js",
Tags: "pre-processing,ffmpeg,h265,",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
if(file.ffProbeData.streams[0].codec_name != 'hevc'){
if (file.ffProbeData.streams[0].codec_name != "hevc") {
response.processFile = true;
response.preset = ', -map 0 -c copy -c:v:0 libx265 -preset:v slow -pix_fmt yuv420p10le -x265-params "crf=22:aq-mode=3"'
response.container = '.mkv'
response.FFmpegMode = true
response.preset =
', -map 0 -c copy -c:v:0 libx265 -preset:v slow -pix_fmt yuv420p10le -x265-params "crf=22:aq-mode=3"';
response.container = ".mkv";
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in hevc! \n"
return response
response.infoLog += "☒File is not in hevc! \n";
return response;
} else {
response.infoLog += "☑File is already in hevc! \n"
response.infoLog += "☑File is already in hevc! \n";
}
var audioIdx = -1
var ffmpegCommandInsert = ''
var hasnonAACTrack = false
var audioIdx = -1;
var ffmpegCommandInsert = "";
var hasnonAACTrack = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].codec_name !== 'aac' && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" ) {
ffmpegCommandInsert += ` -c:a:${audioIdx} aac -vbr 4 `
hasnonAACTrack = true
if (
file.ffProbeData.streams[i].codec_name !== "aac" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
ffmpegCommandInsert += ` -c:a:${audioIdx} aac -vbr 4 `;
hasnonAACTrack = true;
}
} catch (err) {}
}
var ffmpegCommand = `,-map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} -c:s copy -c:d copy`
var ffmpegCommand = `,-map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} -c:s copy -c:d copy`;
if (hasnonAACTrack == true) {
response.processFile = true;
response.preset = ffmpegCommand
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = ffmpegCommand;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒ File has audio which is not in aac! \n"
return response
response.infoLog += "☒ File has audio which is not in aac! \n";
return response;
} else {
response.infoLog += "☑ All audio streams are in aac! \n"
response.infoLog += "☑ All audio streams are in aac! \n";
}
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n"
response.preset = ',-metadata title="" -metadata comment="" -map 0 -c copy'
response.container = '.mkv'
response.infoLog += "☒File has title metadata \n";
response.preset =
',-metadata title="" -metadata comment="" -map 0 -c copy';
response.container = ".mkv";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3",
Stage: "Pre-processing",
@ -11,92 +7,73 @@ function details() {
Description: `[Contains built-in filter] If the file has surround sound tracks not in ac3, they will be converted to ac3. \n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3.js",
Tags:'pre-processing,ffmpeg,audio only,',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3.js",
Tags: "pre-processing,ffmpeg,audio only,",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var audioIdx = -1
var ffmpegCommandInsert = ''
var hasnonAC3SurroundTrack = false
var audioIdx = -1;
var ffmpegCommandInsert = "";
var hasnonAC3SurroundTrack = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if ( file.ffProbeData.streams[i].channels >= 6 && file.ffProbeData.streams[i].codec_name !== 'ac3' && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" ) {
ffmpegCommandInsert += ` -c:a:${audioIdx} ac3 `
hasnonAC3SurroundTrack = true
if (
file.ffProbeData.streams[i].channels >= 6 &&
file.ffProbeData.streams[i].codec_name !== "ac3" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
ffmpegCommandInsert += ` -c:a:${audioIdx} ac3 `;
hasnonAC3SurroundTrack = true;
}
} catch (err) {}
}
var ffmpegCommand = `,-map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} -c:s copy -c:d copy`
var ffmpegCommand = `,-map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} -c:s copy -c:d copy`;
if (hasnonAC3SurroundTrack == true) {
response.processFile = true;
response.preset = ffmpegCommand
response.container = '.' + file.container
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = ffmpegCommand;
response.container = "." + file.container;
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒ File has surround audio which is not in ac3! \n"
return response
response.infoLog += "☒ File has surround audio which is not in ac3! \n";
return response;
} else {
response.infoLog += "☑ All surround audio streams are in aac! \n"
response.infoLog += "☑ All surround audio streams are in aac! \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,5 +1,4 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_c0r1_SetDefaultAudioStream",
Stage: "Pre-processing",
@ -8,12 +7,13 @@ module.exports.details = function details() {
Operation: "Transcode",
Description: `This plugin will set an audio channel (2.0, 5.1, 7.1) to default and remove default from all other audio streams \n\n`,
Version: "0.1.0a",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_c0r1_SetDefaultAudioStream.js",
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_c0r1_SetDefaultAudioStream.js",
Tags: "audio only,ffmpeg,configurable",
Inputs: [
{
name: 'channels',
name: "channels",
tooltip: `Desired audio channel number.
\\nExample:\\n
@ -26,37 +26,35 @@ module.exports.details = function details() {
\\nExample:\\n
8`
8`,
},
]
}
}
],
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
container: '.' + file.container,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
infoLog: '',
}
var shouldProcess = false
var defaultAudioStreams = 0
var matchingAudioStreams = 0
var defaultSet = false
var ffmpegCommandInsert = ''
infoLog: "",
};
var shouldProcess = false;
var defaultAudioStreams = 0;
var matchingAudioStreams = 0;
var defaultSet = false;
var ffmpegCommandInsert = "";
// Check if default audio stream matches user's channel selection
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
if(file.ffProbeData.streams[i].codec_type.toLowerCase() === "audio" &&
file.ffProbeData.streams[i].channels == inputs.channels)
{
matchingAudioStreams++
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() === "audio" &&
file.ffProbeData.streams[i].channels == inputs.channels
) {
matchingAudioStreams++;
if (file.ffProbeData.streams[i].disposition.default === 1) {
defaultAudioStreams++;
}
@ -65,18 +63,16 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
// build command
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
if(file.ffProbeData.streams[i].codec_type.toLowerCase() === "audio")
{
if(file.ffProbeData.streams[i].channels == inputs.channels)
{
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === "audio") {
if (file.ffProbeData.streams[i].channels == inputs.channels) {
if (!defaultSet) {
ffmpegCommandInsert += `-disposition:${i} default `
defaultSet = true
ffmpegCommandInsert += `-disposition:${i} default `;
defaultSet = true;
} else {
ffmpegCommandInsert += `-disposition:${i} 0 `
ffmpegCommandInsert += `-disposition:${i} 0 `;
}
} else {
ffmpegCommandInsert += `-disposition:${i} 0 `
ffmpegCommandInsert += `-disposition:${i} 0 `;
}
}
}
@ -85,25 +81,31 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
// when there is either no default or more than 1 default stream set
if (matchingAudioStreams >= 1 && defaultAudioStreams !== 1) {
shouldProcess = true;
response.infoLog += "☒ Matching audio stream is not set to default. \n"
response.infoLog += "☒ Matching audio stream is not set to default. \n";
}
if (shouldProcess) {
response.processFile = true;
response.reQueueAfter = true;
response.preset = `,-map 0 -c copy ${ffmpegCommandInsert}`;
response.infoLog += "☒ Setting " + inputs.channels + " channel matching audio stream to default. Remove default from all other audio streams \n"
response.infoLog +=
"☒ Setting " +
inputs.channels +
" channel matching audio stream to default. Remove default from all other audio streams \n";
} else {
if (matchingAudioStreams < 1) {
response.infoLog += "☑ No " + inputs.channels + " channel audio stream exists. \n "
response.infoLog +=
"☑ No " + inputs.channels + " channel audio stream exists. \n ";
} else if (defaultAudioStreams === 1) {
response.infoLog += "☑ Default " + inputs.channels + " channel audio stream already exists. \n "
response.infoLog +=
"☑ Default " +
inputs.channels +
" channel audio stream already exists. \n ";
} else {
response.infoLog += "☑ Unexpected: Did not process \n "
response.infoLog += "☑ Unexpected: Did not process \n ";
}
response.processFile = false;
}
return response
}
return response;
};

@ -7,9 +7,10 @@ function details() {
Operation: "Transcode",
Description: `[Contains built-in filter] This plugin uses different FFMPEG NVENC transcoding settings for 480p,576p,720p,1080p and 4KUHD. If files are not in hevc they will be transcoded. The output container is mkv. \n\n`,
Version: "1.09",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js",
Tags:'pre-processing,ffmpeg,video only,nvenc h265',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV.js",
Tags: "pre-processing,ffmpeg,video only,nvenc h265",
};
}
function plugin(file) {
@ -19,102 +20,107 @@ function plugin(file) {
var bitratemax = 0;
var bitratecheck = 0;
var subcli = `-c:s copy`;
var maxmux = '';
var map = '-map 0'
var maxmux = "";
var map = "-map 0";
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mkv',
preset: "",
container: ".mkv",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: true,
infoLog: '',
infoLog: "",
maxmux: false,
}
};
//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 {
bitrateprobe = file.ffProbeData.streams[0].bit_rate
response.infoLog += "☑File is a video! \n"
response.processFile = false;
response.infoLog += "☒File is not a video! \n";
return response;
} 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
response.infoLog += "☑File is already in hevc! \n"
return response
if (file.ffProbeData.streams[0].codec_name == "hevc") {
response.processFile = false;
response.infoLog += "☑File is already in hevc! \n";
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`
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`
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`;
}
//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`
if (
file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
subcli = `-c:s srt`;
}
}
catch (err) { }
} catch (err) {}
//mitigate TrueHD audio causing Too many packets error
try {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "truehd" || (file.ffProbeData.streams[i].codec_name.toLowerCase() == "dts" && file.ffProbeData.streams[i].profile.toLowerCase() == "dts-hd ma") || file.ffProbeData.streams[i].codec_name.toLowerCase() == "aac" && file.ffProbeData.streams[i].sample_rate.toLowerCase() == "44100" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" ) {
maxmux = ` -max_muxing_queue_size 9999`
}
}
catch (err) { }
if (
file.ffProbeData.streams[i].codec_name.toLowerCase() == "truehd" ||
(file.ffProbeData.streams[i].codec_name.toLowerCase() == "dts" &&
file.ffProbeData.streams[i].profile.toLowerCase() == "dts-hd ma") ||
(file.ffProbeData.streams[i].codec_name.toLowerCase() == "aac" &&
file.ffProbeData.streams[i].sample_rate.toLowerCase() == "44100" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio")
) {
maxmux = ` -max_muxing_queue_size 9999`;
}
} 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" ) {
map = `-map 0:v:0 -map 0:a -map 0:s?`
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"
) {
map = `-map 0:v:0 -map 0:a -map 0:s?`;
}
}
catch (err) { }
} catch (err) {}
}
//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") {
bitratecheck = 1000000;
if (bitrateprobe != null && bitrateprobe < bitratecheck) {
bitratetarget = parseInt((bitrateprobe * .8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratetarget = parseInt((bitrateprobe * 0.8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 500; // Set max bitrate to 6MB Higher
}
else {
} else {
bitratetarget = 1000;
bitratemax = 1500;
}
@ -127,10 +133,9 @@ function plugin(file) {
if (file.video_resolution === "720p") {
bitratecheck = 2000000;
if (bitrateprobe != null && bitrateprobe < bitratecheck) {
bitratetarget = parseInt((bitrateprobe * .8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratetarget = parseInt((bitrateprobe * 0.8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 2000; // Set max bitrate to 6MB Higher
}
else {
} else {
bitratetarget = 2000;
bitratemax = 4000;
}
@ -142,10 +147,9 @@ function plugin(file) {
if (file.video_resolution === "1080p") {
bitratecheck = 2500000;
if (bitrateprobe != null && bitrateprobe < bitratecheck) {
bitratetarget = parseInt((bitrateprobe * .8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratetarget = parseInt((bitrateprobe * 0.8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 2500; // Set max bitrate to 6MB Higher
}
else {
} else {
bitratetarget = 2500;
bitratemax = 5000;
}
@ -157,10 +161,9 @@ function plugin(file) {
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
bitratetarget = parseInt((bitrateprobe * 0.7) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 6000; // Set max bitrate to 6MB Higher
}
else {
} else {
bitratetarget = 14000;
bitratemax = 20000;
}
@ -171,22 +174,23 @@ function plugin(file) {
//if true the neccessary response values will be changed
if (transcode == 1) {
response.processFile = true;
response.FFmpegMode = true
response.FFmpegMode = true;
response.reQueueAfter = true;
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`
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 += `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`
response.infoLog += `☒Target Bitrate set to ${bitratetarget}kb!\n`;
response.infoLog += `File is being transcoded!\n`;
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -7,8 +7,8 @@ function details() {
Operation: "",
Description: `Checks if file is not a video file due to Mjpeg stream. Removes Mjpeg Stream \n\n`,
Version: "1.00",
Tags:'pre-processing,ffmpeg,'
}
Tags: "pre-processing,ffmpeg,",
};
}
function plugin(file) {
@ -16,63 +16,63 @@ function plugin(file) {
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: true,
infoLog: ''
}
response.container = '.' + file.container
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"
}
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) { }
} 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"
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
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
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.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `Mjpeg Stream is being removed!\n`
response.infoLog += `Mjpeg Stream is being removed!\n`;
}
return response
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -2,15 +2,17 @@ function details() {
return {
id: "Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4",
Stage: "Pre-processing",
Name: "Dallas FFmpeg h264 mp4. Video: h264/mp4, Subs: Convert to mov_text or drop, Audio: aac",
Name:
"Dallas FFmpeg h264 mp4. Video: h264/mp4, Subs: Convert to mov_text or drop, Audio: aac",
Type: "Video",
Description: `This plugin transcodes into H264 with an MP4 container using the FFmpeg preset you select (slow,medium,fast,veryfast). It maintains all compatible subtitles and audio tracks. Drops picture tracks such as mjpeg\n\n`,
Version: "1.00",
Link: "https://github.com/JackDallas/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js",
Tags:'pre-processing,ffmpeg,h264,video only,configurable',
Link:
"https://github.com/JackDallas/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js",
Tags: "pre-processing,ffmpeg,h264,video only,configurable",
Inputs: [
{
name: 'FFmpeg_preset',
name: "FFmpeg_preset",
tooltip: `Select the FFmpeg preset you wish to use,(slow,medium,fast,veryfast).
\\nExample:\\n
@ -23,24 +25,21 @@ function details() {
fast
\\nExample:\\n
veryfast`
}
]
veryfast`,
},
],
};
}
const presets = [
"slow", "medium", "fast", "veryfast"
];
const presets = ["slow", "medium", "fast", "veryfast"];
// Normalizes the preset or if invalid returns null
function getPreset(preset) {
if (!preset)
return null;
if (!preset) return null;
preset = preset.toLowerCase();
// Strip Spaces
preset = preset.replace(/\s+/g, '');
preset = preset.replace(/\s+/g, "");
if (presets.includes(preset)) {
return preset;
@ -55,16 +54,16 @@ const BAD = false;
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
infoLog: "",
addInfo(status, info) {
this.infoLog += (status ? "☑" : "☒") + " " + info + "\n";
}
}
},
};
// Check the file is a video
if (file.fileMedium !== "video") {
@ -78,12 +77,15 @@ function plugin(file, librarySettings, inputs) {
let preset = getPreset(inputs.FFmpeg_preset);
if (preset === null) {
response.addInfo(BAD, `Invalid Preset, \"${inputs.FFmpeg_preset}\" please select from (slow,medium,fast,veryfast)`);
response.addInfo(
BAD,
`Invalid Preset, \"${inputs.FFmpeg_preset}\" please select from (slow,medium,fast,veryfast)`
);
throw `Error: Invalid Preset, \"${inputs.FFmpeg_preset}\" please select from (slow,medium,fast,veryfast) \n`
throw `Error: Invalid Preset, \"${inputs.FFmpeg_preset}\" please select from (slow,medium,fast,veryfast) \n`;
}
var jsonString = JSON.stringify(file)
var jsonString = JSON.stringify(file);
var hasSubs = false;
var hasBadSubs = false;
@ -94,12 +96,15 @@ function plugin(file, librarySettings, inputs) {
try {
let streamData = file.ffProbeData.streams[i];
if (streamData.codec_type.toLowerCase() == "subtitle") {
if (streamData.codec_name === "hdmv_pgs_subtitle" || streamData.codec_name === "dvd_subtitle") {
if (
streamData.codec_name === "hdmv_pgs_subtitle" ||
streamData.codec_name === "dvd_subtitle"
) {
hasBadSubs = true;
// Drop incompatible subs
subMap += " -map -0:" + streamData.index + " ";
} else if (streamData.codec_name != "mov_text") {
hasSubs = true
hasSubs = true;
// Keep compatible subs
subMap += " -map 0:" + streamData.index + " ";
}
@ -112,9 +117,13 @@ function plugin(file, librarySettings, inputs) {
if (hasBadSubs)
response.addInfo(BAD, "File contains unsupported sub(s), dropping these!");
if (file.ffProbeData.streams[0].codec_name != 'h264') {
if (file.ffProbeData.streams[0].codec_name != "h264") {
response.addInfo(BAD, "File is not in h264!");
response.preset = ', -map_metadata -1 -map 0:V ' + subMap + ' -map 0:a -c:v libx264 -preset medium -c:a aac -strict -2 ' + subType;
response.preset =
", -map_metadata -1 -map 0:V " +
subMap +
" -map 0:a -c:v libx264 -preset medium -c:a aac -strict -2 " +
subType;
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
@ -123,18 +132,26 @@ function plugin(file, librarySettings, inputs) {
response.addInfo(GOOD, "File is already in h264!");
}
if ((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs) {
if (file.meta.Title != undefined && !jsonString.includes("aac") && hasSubs) {
response.addInfo(BAD, "File has title metadata and no aac and subs");
response.preset = ', -map_metadata -1 -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a aac -strict -2 ' + subType;
response.preset =
", -map_metadata -1 -map 0:v " +
subMap +
" -map 0:a -c:v copy -c:a aac -strict -2 " +
subType;
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.addInfo(BAD, "File has no aac track and has subs");
response.preset = ', -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a aac -strict -2 ' + subType;
response.preset =
", -map 0:v " +
subMap +
" -map 0:a -c:v copy -c:a aac -strict -2 " +
subType;
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
@ -143,7 +160,11 @@ function plugin(file, librarySettings, inputs) {
if (file.meta.Title != undefined && hasSubs) {
response.addInfo(BAD, "File has title and has subs");
response.preset = ', -map_metadata -1 -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a copy ' + subType;
response.preset =
", -map_metadata -1 -map 0:v " +
subMap +
" -map 0:a -c:v copy -c:a copy " +
subType;
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
@ -152,7 +173,11 @@ function plugin(file, librarySettings, inputs) {
if (file.meta.Title != undefined) {
response.addInfo(BAD, "File has title metadata");
response.preset = ', -map_metadata -1 -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a copy ' + subType;
response.preset =
", -map_metadata -1 -map 0:v " +
subMap +
" -map 0:a -c:v copy -c:a copy " +
subType;
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
@ -163,7 +188,11 @@ function plugin(file, librarySettings, inputs) {
if (!jsonString.includes("aac")) {
response.addInfo(BAD, "File has no aac track");
response.preset = ', -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a aac -strict -2 ' + subType;
response.preset =
", -map 0:v " +
subMap +
" -map 0:a -c:v copy -c:a aac -strict -2 " +
subType;
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
@ -178,16 +207,17 @@ function plugin(file, librarySettings, inputs) {
} else {
response.addInfo(BAD, "File has compatible subs, copying...");
}
response.preset = ', -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a copy ' + subType;
response.preset =
", -map 0:v " + subMap + " -map 0:a -c:v copy -c:a copy " + subType;
response.processFile = true;
response.FFmpegMode = true
return response
response.FFmpegMode = true;
return response;
} else {
response.addInfo(GOOD, "File has no/compatible subs");
}
response.addInfo(GOOD, "File meets conditions!");
return response
return response;
}
module.exports.details = details;

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_e3jc_Tharic_H.264_MKV_480p30_No_Subs_No_Title_Meta",
Stage: "Pre-processing",
@ -11,156 +7,123 @@ function details() {
Description: `[Contains built-in filter] This plugin removes subs, metadata (if a title exists) and makes sure the video is h264 480p mkv. \n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e3jc_Tharic_H.264_MKV_480p30_No_Subs_No_Title_Meta.js",
Tags:'pre-processing,handbrake,ffmpeg,h264'
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e3jc_Tharic_H.264_MKV_480p30_No_Subs_No_Title_Meta.js",
Tags: "pre-processing,handbrake,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
var hasSubs = false
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
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
//
if(file.ffProbeData.streams[0].codec_name != 'h264' || file.ffProbeData.streams[0].width > 720 || file.ffProbeData.streams[0].height > 480 ){
if (
file.ffProbeData.streams[0].codec_name != "h264" ||
file.ffProbeData.streams[0].width > 720 ||
file.ffProbeData.streams[0].height > 480
) {
response.processFile = true;
response.preset = '-Z "H.264 MKV 480p30"'
response.container = '.mkv'
response.handBrakeMode =true
response.FFmpegMode = false
response.preset = '-Z "H.264 MKV 480p30"';
response.container = ".mkv";
response.handBrakeMode = true;
response.FFmpegMode = false;
response.reQueueAfter = true;
response.infoLog += "☒File is not h264 480p! \n"
return response
response.infoLog += "☒File is not h264 480p! \n";
return response;
} else {
response.infoLog += "☑File is h264 480p! \n"
response.infoLog += "☑File is h264 480p! \n";
}
//
if (file.meta.Title != "undefined" && hasSubs) {
response.processFile = true;
response.preset = ',-sn -map_metadata -1 -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-sn -map_metadata -1 -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has title and has subs \n"
return response
response.infoLog += "☒File has title and has subs \n";
return response;
} else {
response.infoLog += "☑File has no title and has no subs \n"
response.infoLog += "☑File has no title and has no subs \n";
}
if (file.meta.Title != undefined) {
response.processFile = true;
response.preset = ',-map_metadata -1 -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has title metadata \n"
return response
response.infoLog += "☒File has title metadata \n";
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
if (hasSubs) {
response.processFile = true;
response.preset = ',-sn -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-sn -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has subs \n"
return response
response.infoLog += "☒File has subs \n";
return response;
} else {
response.infoLog += "☑File has no subs \n"
response.infoLog += "☑File has no subs \n";
}
if( file.container != 'mkv'){
if (file.container != "mkv") {
response.processFile = true;
response.preset = ', -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ", -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in mkv container! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n"
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_e3jd_Tharic_H.264_MKV_720p30_No_Subs_No_Title_Meta",
Stage: "Pre-processing",
@ -11,156 +7,123 @@ function details() {
Description: `[Contains built-in filter] This plugin removes subs, metadata (if a title exists) and makes sure the video is h264 720p mkv. \n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e3jd_Tharic_H.264_MKV_720p30_No_Subs_No_Title_Meta.js",
Tags:'pre-processing,handbrake,ffmpeg,h264'
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e3jd_Tharic_H.264_MKV_720p30_No_Subs_No_Title_Meta.js",
Tags: "pre-processing,handbrake,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
var hasSubs = false
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
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
//
if(file.ffProbeData.streams[0].codec_name != 'h264' || file.ffProbeData.streams[0].width > 1280 || file.ffProbeData.streams[0].height > 720 ){
if (
file.ffProbeData.streams[0].codec_name != "h264" ||
file.ffProbeData.streams[0].width > 1280 ||
file.ffProbeData.streams[0].height > 720
) {
response.processFile = true;
response.preset = '-Z "H.264 MKV 720p30"'
response.container = '.mkv'
response.handBrakeMode =true
response.FFmpegMode = false
response.preset = '-Z "H.264 MKV 720p30"';
response.container = ".mkv";
response.handBrakeMode = true;
response.FFmpegMode = false;
response.reQueueAfter = true;
response.infoLog += "☒File is not h264 720p! \n"
return response
response.infoLog += "☒File is not h264 720p! \n";
return response;
} else {
response.infoLog += "☑File is h264 720p! \n"
response.infoLog += "☑File is h264 720p! \n";
}
//
if (file.meta.Title != "undefined" && hasSubs) {
response.processFile = true;
response.preset = ',-sn -map_metadata -1 -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-sn -map_metadata -1 -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has title and has subs \n"
return response
response.infoLog += "☒File has title and has subs \n";
return response;
} else {
response.infoLog += "☑File has no title and has no subs \n"
response.infoLog += "☑File has no title and has no subs \n";
}
if (file.meta.Title != undefined) {
response.processFile = true;
response.preset = ',-map_metadata -1 -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has title metadata \n"
return response
response.infoLog += "☒File has title metadata \n";
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
if (hasSubs) {
response.processFile = true;
response.preset = ',-sn -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-sn -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has subs \n"
return response
response.infoLog += "☒File has subs \n";
return response;
} else {
response.infoLog += "☑File has no subs \n"
response.infoLog += "☑File has no subs \n";
}
if( file.container != 'mkv'){
if (file.container != "mkv") {
response.processFile = true;
response.preset = ', -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ", -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in mkv container! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n"
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_e3je_Tharic_H.264_MKV_1080p30_No_Subs_No_Title_Meta",
Stage: "Pre-processing",
@ -11,156 +7,123 @@ function details() {
Description: `[Contains built-in filter] This plugin removes subs, metadata (if a title exists) and makes sure the video is h264 1080p mkv. \n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e3je_Tharic_H.264_MKV_1080p30_No_Subs_No_Title_Meta.js",
Tags:'pre-processing,handbrake,ffmpeg,h264'
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e3je_Tharic_H.264_MKV_1080p30_No_Subs_No_Title_Meta.js",
Tags: "pre-processing,handbrake,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
var hasSubs = false
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
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
//
if(file.ffProbeData.streams[0].codec_name != 'h264' || file.ffProbeData.streams[0].width > 1920 || file.ffProbeData.streams[0].height > 1080 ){
if (
file.ffProbeData.streams[0].codec_name != "h264" ||
file.ffProbeData.streams[0].width > 1920 ||
file.ffProbeData.streams[0].height > 1080
) {
response.processFile = true;
response.preset = '-Z "H.264 MKV 1080p30"'
response.container = '.mkv'
response.handBrakeMode =true
response.FFmpegMode = false
response.preset = '-Z "H.264 MKV 1080p30"';
response.container = ".mkv";
response.handBrakeMode = true;
response.FFmpegMode = false;
response.reQueueAfter = true;
response.infoLog += "☒File is not h264 1080p! \n"
return response
response.infoLog += "☒File is not h264 1080p! \n";
return response;
} else {
response.infoLog += "☑File is h264 1080p!"
response.infoLog += "☑File is h264 1080p!";
}
//
if (file.meta.Title != "undefined" && hasSubs) {
response.processFile = true;
response.preset = ',-sn -map_metadata -1 -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-sn -map_metadata -1 -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has title and has subs \n"
return response
response.infoLog += "☒File has title and has subs \n";
return response;
} else {
response.infoLog += "☑File has no title and has no subs \n"
response.infoLog += "☑File has no title and has no subs \n";
}
if (file.meta.Title != undefined) {
response.processFile = true;
response.preset = ',-map_metadata -1 -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has title metadata \n"
return response
response.infoLog += "☒File has title metadata \n";
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
if (hasSubs) {
response.processFile = true;
response.preset = ',-sn -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ",-sn -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File has subs \n"
return response
response.infoLog += "☒File has subs \n";
return response;
} else {
response.infoLog += "☑File has no subs \n"
response.infoLog += "☑File has no subs \n";
}
if( file.container != 'mkv'){
if (file.container != "mkv") {
response.processFile = true;
response.preset = ', -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode =false
response.FFmpegMode = true
response.preset = ", -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in mkv container! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n"
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,5 +1,5 @@
const fs = require('fs');
const execSync = require('child_process').execSync;
const fs = require("fs");
const execSync = require("child_process").execSync;
function details() {
return {
@ -10,19 +10,20 @@ function details() {
Operation: "Remux",
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',
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) \\nExample:\\n yes`
name: "install_packages",
tooltip: `Please change this to "yes", it allows the plugin to install the required nodemodule. (iso-639-2) \\nExample:\\n yes`,
},
{
name: 'container',
tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv`
name: "container",
tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv`,
},
]
}
],
};
}
function plugin(file, librarySettings, inputs, otherArguments) {
@ -30,12 +31,12 @@ function plugin(file, librarySettings, inputs, otherArguments) {
var response = {
processFile: false,
preset: `,`,
container: '.mkv',
container: ".mkv",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: `Searching new subtitles...\n`,
}
};
if (inputs.container !== undefined) {
response.container = inputs.container;
@ -43,18 +44,20 @@ function plugin(file, librarySettings, inputs, otherArguments) {
}
if (inputs.install_packages == "yes") {
if (!fs.existsSync(`${otherArguments.homePath}/Tdarr/node_modules/iso-639-2`)) {
if (
!fs.existsSync(`${otherArguments.homePath}/Tdarr/node_modules/iso-639-2`)
) {
execSync(`cd ${otherArguments.homePath}/Tdarr \n npm install iso-639-2`);
}
} else {
response.infoLog = `Please take a look at the input options\n A extra nodemodule is required.`
response.infoLog = `Please take a look at the input options\n A extra nodemodule is required.`;
return response;
}
if (fs.existsSync(`/home/Tdarr/Documents/Tdarr/node_modules/iso-639-2`)) {
var iso6392 = require('/home/Tdarr/Documents/Tdarr/node_modules/iso-639-2');
var iso6392 = require("/home/Tdarr/Documents/Tdarr/node_modules/iso-639-2");
} else {
response.infoLog += `Nodemodule iso-639-2 isn't installed!\nTry Again`
response.infoLog += `Nodemodule iso-639-2 isn't installed!\nTry Again`;
return response;
}
@ -64,10 +67,10 @@ function plugin(file, librarySettings, inputs, otherArguments) {
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 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 = '';
var preset_import = "";
var preset_meta = "";
//find first subtitle stream
while (found_subtitle_stream == 0 && sub < file.ffProbeData.streams.length) {
@ -86,10 +89,18 @@ function plugin(file, librarySettings, inputs, otherArguments) {
if (found_subtitle_stream == 1) {
//check if language already exists
for (sub_stream = sub; sub_stream < file.ffProbeData.streams.length; sub_stream++) {
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) {
if (file.ffProbeData.streams[sub_stream].tags.language.toLowerCase() == lang[i].iso6392B) {
if (
file.ffProbeData.streams[
sub_stream
].tags.language.toLowerCase() == lang[i].iso6392B
) {
//response.infoLog += `YES\n`
exist = 1;
response.infoLog += `Language already exists in stream ${sub_stream}\n It will not be added\n`;
@ -113,7 +124,7 @@ function plugin(file, librarySettings, inputs, otherArguments) {
exist = 0;
}
response.preset += ` ${preset_import}${preset_meta} -map 0:v -map 0:a`
response.preset += ` ${preset_import}${preset_meta} -map 0:v -map 0:a`;
//map new subs
while (added_subs < new_subs) {
@ -137,7 +148,7 @@ function plugin(file, librarySettings, inputs, otherArguments) {
//response.infoLog += `The ffmpeg string is: ${response.preset}\n`
return response
return response;
}
module.exports.details = details;

@ -1,5 +1,5 @@
const exec = require('child_process').exec;
const fs = require('fs');
const exec = require("child_process").exec;
const fs = require("fs");
function details() {
return {
@ -8,37 +8,39 @@ function details() {
Name: "Keep Preffered Audio",
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",
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_Keep_Preferred_Audio.js",
Tags: 'pre-processing,ffmpeg,configurable,audio only',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio.js",
Tags: "pre-processing,ffmpeg,configurable,audio only",
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\\nExample:\\eng,dut`
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\\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.\\nThe languages don't have to be in "languages".\\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.\\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`
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 == "" || typeof inputs.special == 'undefined') {
if (inputs.languages == "" || typeof 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.toLowerCase().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 == "" || typeof inputs.special == 'undefined') {
if (inputs.special == "" || typeof inputs.special == "undefined") {
var special = ``;
} else {
var special = inputs.special.toLowerCase().split(',');
var special = inputs.special.toLowerCase().split(",");
}
if (languages.length >= special.length) {
var length = languages.length;
@ -47,7 +49,10 @@ function plugin(file, librarySettings, inputs, otherArguments) {
}
console.log(languages);
var transcode = 0; //if this becomes '1' it will be transcoded
var sourcename = file.meta.FileName.substring(0, file.meta.FileName.lastIndexOf(".")); //filename without extension
var sourcename = file.meta.FileName.substring(
0,
file.meta.FileName.lastIndexOf(".")
); //filename without extension
var specialcheck = ``; //contains the txt string if special language was found
var wanted = 0;
var audio = 0;
@ -56,11 +61,11 @@ function plugin(file, librarySettings, inputs, otherArguments) {
var response = {
processFile: false,
preset: `, -map 0:v`,
container: '.mkv',
container: ".mkv",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: 'Removing unwanted audio...\n',
infoLog: "Removing unwanted audio...\n",
};
if (inputs.container !== undefined) {
@ -73,18 +78,42 @@ function plugin(file, librarySettings, inputs, otherArguments) {
//check for non-english tracks
console.log(`Audio track ${i}`);
console.log("type: " + typeof file.ffProbeData.streams[i].tags);
if (typeof file.ffProbeData.streams[i].tags !== 'undefined' || file.ffProbeData.streams[i].tags) {
console.log("Type: " + typeof file.ffProbeData.streams[i].tags.language)
if (typeof file.ffProbeData.streams[i].tags.language !== 'undefined' || file.ffProbeData.streams[i].tags.language) {
if (
typeof file.ffProbeData.streams[i].tags !== "undefined" ||
file.ffProbeData.streams[i].tags
) {
console.log(
"Type: " + typeof file.ffProbeData.streams[i].tags.language
);
if (
typeof file.ffProbeData.streams[i].tags.language !== "undefined" ||
file.ffProbeData.streams[i].tags.language
) {
for (l = 0; l < length; l++) {
if (file.ffProbeData.streams[i].tags.language == special[l]) {
if (!fs.existsSync(otherArguments.homePath + `/Tdarr/special_audio_${special[l]}.txt`)) { //create txt file if it doesn't exist yet
exec(`echo "${sourcename}" >> ${otherArguments.homePath}/Tdarr/special_audio_${special[l]}.txt`); //first file will be added and file is created
if (
!fs.existsSync(
otherArguments.homePath +
`/Tdarr/special_audio_${special[l]}.txt`
)
) {
//create txt file if it doesn't exist yet
exec(
`echo "${sourcename}" >> ${otherArguments.homePath}/Tdarr/special_audio_${special[l]}.txt`
); //first file will be added and file is created
console.log(`added to txt: ` + sourcename);
} else {
specialcheck = fs.readFileSync(otherArguments.homePath + `/Tdarr/special_audio_${special[l]}.txt`).toString(); //create string from existing file
if (!specialcheck.includes(sourcename)) { //only add the filename if it wasn't added already
exec(`echo "${sourcename}" >> ${otherArguments.homePath}/Tdarr/special_audio_${special[l]}.txt`);
specialcheck = fs
.readFileSync(
otherArguments.homePath +
`/Tdarr/special_audio_${special[l]}.txt`
)
.toString(); //create string from existing file
if (!specialcheck.includes(sourcename)) {
//only add the filename if it wasn't added already
exec(
`echo "${sourcename}" >> ${otherArguments.homePath}/Tdarr/special_audio_${special[l]}.txt`
);
console.log(`added to txt: ` + sourcename);
}
}
@ -93,7 +122,9 @@ function plugin(file, librarySettings, inputs, otherArguments) {
response.infoLog += `Found special ${special[l]}: ${i}\n`;
wanted++;
break;
} else if (file.ffProbeData.streams[i].tags.language == languages[l]) {
} else if (
file.ffProbeData.streams[i].tags.language == languages[l]
) {
response.preset += ` -map 0:${i}`;
response.infoLog += `Found wanted ${languages[l]}: ${i}\n`;
wanted++;
@ -131,7 +162,7 @@ function plugin(file, librarySettings, inputs, otherArguments) {
response.infoLog += `No unwanted audio found!\n`;
}
return response
return response;
}
module.exports.details = details;

@ -1,5 +1,5 @@
const fs = require('fs');
const execSync = require('child_process').execSync;
const fs = require("fs");
const execSync = require("child_process").execSync;
function details() {
return {
@ -10,23 +10,24 @@ function details() {
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: 'pre-processing,ffmpeg,nvenc h265,configurable,h265,video only',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js",
Tags: "pre-processing,ffmpeg,nvenc h265,configurable,h265,video only",
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: "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`
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 == "" || inputs.bitrate == 'undefined') {
if (inputs.bitrate == "" || inputs.bitrate == "undefined") {
var min_bitrate = 6600;
var avg_rate = 3000;
var max_rate = 6000;
@ -39,13 +40,13 @@ function plugin(file, librarySettings, inputs, otherArguments) {
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mkv',
preset: "",
container: ".mkv",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
infoLog: "",
};
if (inputs.container !== undefined) {
response.container = inputs.container;
@ -57,22 +58,30 @@ function plugin(file, librarySettings, inputs, otherArguments) {
var size = stats["size"] / 1000000000;
size = size.toFixed(2);
var decoder = decoder_string(file); //decoder, before the input
var encoder = encoder_string_full(highres(file), crop_decider(file, generate_crop_values(file, otherArguments).crop_height).crop, encoder_string(file, avg_rate, max_rate, response.container)); //encoder
var encoder = encoder_string_full(
highres(file),
crop_decider(file, generate_crop_values(file, otherArguments).crop_height)
.crop,
encoder_string(file, avg_rate, max_rate, response.container)
); //encoder
var process = 0; //decides if it should be processed
var returns = {
create_crop: generate_crop_values(file, otherArguments),
crop: crop_decider(file, generate_crop_values(file, otherArguments).crop_height),
size: size_check(file, min_bitrate)
}
crop: crop_decider(
file,
generate_crop_values(file, otherArguments).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
}
createcrop: returns.create_crop.log,
};
//filters
if (size_check(file, min_bitrate).size == 1) {
@ -80,7 +89,7 @@ function plugin(file, librarySettings, inputs, otherArguments) {
log.hevc = `☑ - Video is not HEVC \n`;
process = 1;
} else {
log.hevc += "☒ - File is already in HEVC \n"
log.hevc += "☒ - File is already in HEVC \n";
}
if (highres(file) == 1) {
@ -90,17 +99,17 @@ function plugin(file, librarySettings, inputs, otherArguments) {
log.resolution += `☒ - Resolution <= 1080p \n`;
}
if (crop_decider(file, generate_crop_values(file, otherArguments).crop_height).crop != "0") {
if (
crop_decider(file, generate_crop_values(file, otherArguments).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}`
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) {
@ -128,18 +137,25 @@ function highres(file) {
function generate_crop_values(file, otherArguments) {
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 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: ``
}
log: ``,
};
//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}\"`);
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}\"`
);
} else {
returns.log += `Crop values already exist\n`;
}
@ -163,7 +179,11 @@ function generate_crop_values(file, otherArguments) {
function hevc(file) {
//check if the file is already hevc, it will not be transcoded if true
if (file.ffProbeData.streams[0].codec_name) {
if ("hevc".toLowerCase().includes(file.ffProbeData.streams[0].codec_name.toLowerCase())) {
if (
"hevc"
.toLowerCase()
.includes(file.ffProbeData.streams[0].codec_name.toLowerCase())
) {
return 0;
} else {
return 1;
@ -175,31 +195,25 @@ 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`
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;
@ -209,7 +223,7 @@ 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) {
@ -219,10 +233,11 @@ function crop_decider(file, crop_height) {
}
}
var min_crop = parseInt(imageHeight*.98); //if the crop value is larger than this the file won't be cropped
var min_crop = parseInt(imageHeight * 0.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)
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);
@ -244,7 +259,8 @@ function crop_decider(file, crop_height) {
} else {
returns.log += `☒ - Crop is not necessary\n`;
}
} else if(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`;
}
@ -259,11 +275,12 @@ function size_check(file, min_bitrate) {
size = size.toFixed(2);
var returns = {
size: 0,
log: ``
}
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)
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);
@ -274,7 +291,8 @@ function size_check(file, min_bitrate) {
} 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
} 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);
@ -285,7 +303,11 @@ function size_check(file, min_bitrate) {
} 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
} 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);
@ -304,19 +326,32 @@ function size_check(file, min_bitrate) {
function error_fix(file, container) {
var fix = {
sub_codec: 0, //changes to 1 if unwanted codec is found
muxing: 0
}
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 && file.ffProbeData.streams[i].codec_type) {
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") && container == '.mkv') {
if (
file.ffProbeData.streams[i].codec_name &&
file.ffProbeData.streams[i].codec_type
) {
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") &&
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" ) {
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;
}
}
@ -331,13 +366,24 @@ function encoder_string(file, avg_rate, max_rate, container) {
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)
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
} else { //fallback option to 1080p quality
} 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
} else {
//fallback option to 1080p quality
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
}
encoder += ` -c:v hevc_nvenc -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -dn`;
@ -345,11 +391,21 @@ function encoder_string(file, avg_rate, max_rate, container) {
if (fix.sub_codec == 1) {
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
if (file.ffProbeData.streams[i].codec_name) {
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"))
) {
sub += ` -c:${i} ass`;
} else {
if (file.ffProbeData.streams[i].codec_type) {
if (file.ffProbeData.streams[i].codec_type.toLowerCase().includes("sub")) {
if (
file.ffProbeData.streams[i].codec_type
.toLowerCase()
.includes("sub")
) {
sub += ` -c:${i} copy`;
}
}
@ -357,7 +413,7 @@ function encoder_string(file, avg_rate, max_rate, container) {
}
}
} else {
sub = ` -c:s copy`
sub = ` -c:s copy`;
}
if (fix.muxing == 1) {
@ -381,7 +437,7 @@ function encoder_string_full(highres, crop, encoder) {
}
function execCommand(cmd) {
const exec = require('child_process').exec;
const exec = require("child_process").exec;
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs",
Stage: "Pre-processing",
@ -10,192 +6,181 @@ function details() {
Type: "Video",
Description: `[Contains built-in filter] This plugin for 4K video removes subs. If no AC3 track exists, it adds one (max 5.1 channels). If only an AC3 commentary track exists, it adds a new AC3 main track (max 5.1 channels). The output container is the same as the original file. \n\n`,
Version: "1.04",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs.js",
Tags:'pre-processing,ffmpeg',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs.js",
Tags: "pre-processing,ffmpeg",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.container = '.' + file.container
response.FFmpegMode = true
infoLog: "",
};
response.container = "." + file.container;
response.FFmpegMode = true;
if (file.fileMedium !== "video" || file.video_resolution !== "4KUHD") {
console.log("File is not a 4K video");
console.log("File is not a 4K video")
response.infoLog += "☒File is not a 4K video \n"
response.infoLog += "☒File is not a 4K video \n";
response.processFile = false;
return response
return response;
} else {
var ac3TrackCount = 0;
var AC3CommentaryCount = 0;
var hasSubs = false;
var ac3TrackCount = 0
var AC3CommentaryCount = 0
var hasSubs = false
var commentaryStreamIdx = false
var audioIdx = -1
var commentaryStreamIdx = false;
var audioIdx = -1;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
//keep track of audio streams for when removing commentary track
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
//check if commentary track and assing audio stream number
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].tags.title.toLowerCase().includes("commentary")) {
commentaryStreamIdx = audioIdx
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("commentary")
) {
commentaryStreamIdx = audioIdx;
}
} catch (err) {}
//check if commentary AC3 track
try {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "ac3" && file.ffProbeData.streams[i].tags.title.toLowerCase().includes("commentary")) {
AC3CommentaryCount++
if (
file.ffProbeData.streams[i].codec_name.toLowerCase() == "ac3" &&
file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("commentary")
) {
AC3CommentaryCount++;
}
} catch (err) {}
//check if AC3 track
try {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "ac3") {
ac3TrackCount++
ac3TrackCount++;
}
} catch (err) {}
//check if subs track
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
hasSubs = true
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
var hasOnlyAC3TrackCommentaries
var hasOnlyAC3TrackCommentaries;
if (ac3TrackCount > 0 && AC3CommentaryCount == ac3TrackCount) {
hasOnlyAC3TrackCommentaries = true
hasOnlyAC3TrackCommentaries = true;
} else {
hasOnlyAC3TrackCommentaries = false
hasOnlyAC3TrackCommentaries = false;
}
var hasNoAC3Track
var hasNoAC3Track;
if (ac3TrackCount == 0) {
hasNoAC3Track = true
hasNoAC3Track = true;
} else {
hasNoAC3Track = false
hasNoAC3Track = false;
}
//max 5.1 audio in AC3 output
var channels = file.ffProbeData.streams[1].channels
var channels = file.ffProbeData.streams[1].channels;
if (channels > 6) {
channels = 6
channels = 6;
}
if (hasOnlyAC3TrackCommentaries && hasSubs) {
response.infoLog += "☒File has no AC3 main track (has AC3 commentary) and has subs \n"
response.preset = ',-sn -map 0:v -map 0:a:0 -map 0:a -map 0:d? -c copy -c:a:0 ac3 -ac ' + channels
response.infoLog +=
"☒File has no AC3 main track (has AC3 commentary) and has subs \n";
response.preset =
",-sn -map 0:v -map 0:a:0 -map 0:a -map 0:d? -c copy -c:a:0 ac3 -ac " +
channels;
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
}
if (hasNoAC3Track && hasSubs) {
response.infoLog += "☒File has no AC3 main track and has subs \n"
response.preset = ',-sn -map 0:v -map 0:a:0 -map 0:a -map 0:d? -c copy -c:a:0 ac3 -ac ' + channels
response.infoLog += "☒File has no AC3 main track and has subs \n";
response.preset =
",-sn -map 0:v -map 0:a:0 -map 0:a -map 0:d? -c copy -c:a:0 ac3 -ac " +
channels;
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
}
if (commentaryStreamIdx !== false) {
response.infoLog += `☒File has AC3 commentary track in stream ${commentaryStreamIdx} \n`
response.preset = `,-map 0 -map -0:a:${commentaryStreamIdx} -codec copy`
response.infoLog += `☒File has AC3 commentary track in stream ${commentaryStreamIdx} \n`;
response.preset = `,-map 0 -map -0:a:${commentaryStreamIdx} -codec copy`;
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
}
if (!!hasOnlyAC3TrackCommentaries == true) {
response.infoLog += "☒File has no AC3 main track (has AC3 commentary)! \n"
response.preset = ',-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ac3 -ac ' + channels
response.infoLog +=
"☒File has no AC3 main track (has AC3 commentary)! \n";
response.preset =
",-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ac3 -ac " +
channels;
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File does not have only AC3 track commentaries! \n"
response.infoLog += "☑File does not have only AC3 track commentaries! \n";
}
if (hasNoAC3Track) {
response.infoLog += "☒File has no AC3 track! \n"
response.preset = ',-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ac3 -ac ' + channels
response.infoLog += "☒File has no AC3 track! \n";
response.preset =
",-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ac3 -ac " +
channels;
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has AC3 track! \n"
response.infoLog += "☑File has AC3 track! \n";
}
if (hasSubs) {
response.infoLog += "☒File has subs! \n"
response.preset = ',-sn -map 0 -c copy'
response.infoLog += "☒File has subs! \n";
response.preset = ",-sn -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has no subs \n"
response.infoLog += "☑File has no subs \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle",
Stage: "Pre-processing",
@ -11,211 +7,164 @@ function details() {
Description: `[Contains built-in filter] This plugin removes subs, metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (English or any) doesn't exist. The output container is mp4. \n\n
`,
Version: "1.07",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle.js",
Tags:'pre-processing,ffmpeg',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle.js",
Tags: "pre-processing,ffmpeg",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var hasPreferredLangTrack = false;
var hasPreferredLangInRequiredCodecs = false;
var hasAnyInRequiredCodecs = false;
var audioIdx = -1;
var engTrackIdx = -1;
var hasPreferredLangTrack = false
var hasPreferredLangInRequiredCodecs = false
var hasAnyInRequiredCodecs = false
var audioIdx = -1
var engTrackIdx = -1
var requiredAudioCodecs = "aac"
var preferredLangTrack = "eng"
var preferredCodec = "aac"
var hasSubs = false
var requiredAudioCodecs = "aac";
var preferredLangTrack = "eng";
var preferredCodec = "aac";
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
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) {
hasAnyInRequiredCodecs = true
if (
requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)
) {
hasAnyInRequiredCodecs = true;
}
} catch (err) {}
try {
if ((requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) && file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack)) {
hasPreferredLangInRequiredCodecs = true
if (
requiredAudioCodecs.includes(
file.ffProbeData.streams[i].codec_name
) &&
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack)
) {
hasPreferredLangInRequiredCodecs = true;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack) && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
hasPreferredLangTrack = true
engTrackIdx = audioIdx
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack) &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
hasPreferredLangTrack = true;
engTrackIdx = audioIdx;
}
} catch (err) {}
}
if (hasPreferredLangInRequiredCodecs) {
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`;
} else if (hasPreferredLangTrack) {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2 -strict -2`
response.container = '.mp4'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2 -strict -2`;
response.container = ".mp4";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`
return response
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`;
return response;
} else if (!hasAnyInRequiredCodecs) {
if (audioIdx == -1) {
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`;
} else {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2 -strict -2`
response.container = '.mp4'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2 -strict -2`;
response.container = ".mp4";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`
return response
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`;
return response;
}
}
if (file.meta.Title != "undefined" && hasSubs) {
response.infoLog += "☒File has title and has subs \n"
response.preset = ',-sn -map_metadata -1 -c:v copy -c:a copy'
response.infoLog += "☒File has title and has subs \n";
response.preset = ",-sn -map_metadata -1 -c:v copy -c:a copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n"
response.preset = ',-map_metadata -1 -c:v copy -c:a copy'
response.infoLog += "☒File has title metadata \n";
response.preset = ",-map_metadata -1 -c:v copy -c:a copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
if (hasSubs) {
response.infoLog += "☒File has subs \n"
response.preset = ',-sn -c:v copy -c:a copy'
response.infoLog += "☒File has subs \n";
response.preset = ",-sn -c:v copy -c:a copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has no subs \n"
response.infoLog += "☑File has no subs \n";
}
if( file.container != 'mp4'){
response.infoLog += "☒File is not in mp4 container! \n"
response.preset = ', -c:v copy -c:a copy'
if (file.container != "mp4") {
response.infoLog += "☒File is not in mp4 container! \n";
response.preset = ", -c:v copy -c:a copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File is in mp4 container! \n"
response.infoLog += "☑File is in mp4 container! \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle",
Stage: "Pre-processing",
@ -11,93 +7,70 @@ function details() {
Description: `[Contains built-in filter] This plugin removes metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (any) doesn't exist. The output container is mp4. \n\n
`,
Version: "1.01",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle.js",
Tags:'pre-processing,ffmpeg',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle.js",
Tags: "pre-processing,ffmpeg",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
if (file.container != 'mp4') {
response.infoLog += "☒File is not in mp4 container! \n"
response.preset = ', -map 0 -c copy'
if (file.container != "mp4") {
response.infoLog += "☒File is not in mp4 container! \n";
response.preset = ", -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File is in mp4 container! \n"
response.infoLog += "☑File is in mp4 container! \n";
}
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n"
response.preset = ',-map_metadata -1 -map 0 -c copy'
response.infoLog += "☒File has title metadata \n";
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
if (!jsonString.includes("aac")) {
response.infoLog += "☒File has no aac track"
response.preset = ',-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 aac -b:a:0 192k -ac 2'
response.infoLog += "☒File has no aac track";
response.preset =
",-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 aac -b:a:0 192k -ac 2";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has aac track \n"
response.infoLog += "☑File has aac track \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,5 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_lmg1_Reorder_Streams",
Stage: "Pre-processing",
@ -8,59 +7,48 @@ function details() {
Description: `[Contains built-in filter] This plugin will move the video stream to the front so Tdarr will recognize the codec correctly.\n\n`,
Version: "1.00",
Link: "https://github.com/luigi311/Tdarr_Plugin_lmg1_Reorder_Streams",
Tags:'pre-processing,ffmpeg',
}
Tags: "pre-processing,ffmpeg",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += " File is not video\n"
response.infoLog += " File is not video\n";
response.processFile = false;
return response
return response;
} else {
response.FFmpegMode = true;
response.container = "." + file.container;
response.FFmpegMode = true
response.container = '.' + file.container
if(file.ffProbeData.streams[0].codec_type != 'video') {
response.infoLog += "Video is not in the first stream"
response.preset = ',-map 0:v? -map 0:a? -map 0:s? -map 0:d? -map 0:t? -c copy'
if (file.ffProbeData.streams[0].codec_type != "video") {
response.infoLog += "Video is not in the first stream";
response.preset =
",-map 0:v? -map 0:a? -map 0:s? -map 0:d? -map 0:t? -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "File has video in first stream\n"
response.infoLog += "File has video in first stream\n";
}
response.infoLog += " File meets conditions!\n"
return response
response.infoLog += " File meets conditions!\n";
return response;
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta",
Stage: "Pre-processing",
@ -11,63 +7,50 @@ function details() {
Description: `[Contains built-in filter] This plugin removes metadata (if a title exists). The output container is the same as the original. \n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta.js",
Tags:'pre-processing,ffmpeg',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta.js",
Tags: "pre-processing,ffmpeg",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.container = '.' + file.container
response.FFmpegMode = true
infoLog: "",
};
response.container = "." + file.container;
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
// var jsonString = JSON.stringify(file)
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n"
response.preset = ',-map_metadata -1 -map 0 -c copy'
response.infoLog += "☒File has title metadata \n";
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -8,8 +8,8 @@ function details() {
Description: `[Contains built-in filter] High Quality FFMPEG transcoding settings for Animation. Converts all audio to AAC 512K. Preserves track names, metadata and attachments/fonts. Proper use of x265-params. CRF 18. Preset medium. 10-Bit Video encoding. Skips h.265 encoded videos. The output container is mkv. \n\n`,
Version: "1.1",
Link: "",
Tags:"pre-processing,ffmpeg,h265,aac,10bit,anime,"
}
Tags: "pre-processing,ffmpeg,h265,aac,10bit,anime,",
};
}
function plugin(file) {
@ -18,33 +18,34 @@ function plugin(file) {
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mkv',
preset: "",
container: ".mkv",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
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
response.processFile = false;
response.infoLog += "☒File is not a video! \n";
return response;
} else {
response.infoLog += "☑File is a video! \n"
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
response.infoLog += "☑File is already in hevc! \n"
return response
if (file.ffProbeData.streams[0].codec_name == "hevc") {
response.processFile = false;
response.infoLog += "☑File is already in hevc! \n";
return response;
}
//Transcoding options
{
response.preset = ',-map 0 -c:s copy -movflags use_metadata_tags -c:a aac -b:a 512k -c:v:0 libx265 -preset medium -x265-params crf=18:tune=animation:qcomp=0.7:aq-strength=1.1 -pix_fmt yuv420p10le -f matroska'
response.preset =
",-map 0 -c:s copy -movflags use_metadata_tags -c:a aac -b:a 512k -c:v:0 libx265 -preset medium -x265-params crf=18:tune=animation:qcomp=0.7:aq-strength=1.1 -pix_fmt yuv420p10le -f matroska";
transcode = 1;
}
@ -52,13 +53,13 @@ function plugin(file) {
//if true the neccessary response values will be changed
if (transcode == 1) {
response.processFile = true;
response.FFmpegMode = true
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File is ${file.video_resolution} but is not hevc!\n`
response.infoLog += `☒File will be transcoded!\n`
response.infoLog += `☒File is ${file.video_resolution} but is not hevc!\n`;
response.infoLog += `☒File will be transcoded!\n`;
}
return response
return response;
}
module.exports.details = details;

@ -8,8 +8,8 @@ function details() {
Description: `[Contains built-in filter] This plugin uses different FFmpeg 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.01",
Link: "",
Tags:"pre-processing,ffmpeg,h265,video only,"
}
Tags: "pre-processing,ffmpeg,h265,video only,",
};
}
function plugin(file) {
@ -18,62 +18,63 @@ function plugin(file) {
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mkv',
preset: "",
container: ".mkv",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
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
response.processFile = false;
response.infoLog += "☒File is not a video! \n";
return response;
} else {
response.infoLog += "☑File is a video! \n"
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
response.infoLog += "☑File is already in hevc! \n"
return response
if (file.ffProbeData.streams[0].codec_name == "hevc") {
response.processFile = false;
response.infoLog += "☑File is already in hevc! \n";
return response;
}
//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 = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'h264') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'mjpeg') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'mpeg1') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'mpeg2') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'mpeg4') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'vc1') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'vp8') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else if (file.video_codec_name == 'vp9') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
}
else {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27'
if (file.video_codec_name == "h263") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "h264") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "mjpeg") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "mpeg1") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "mpeg2") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "mpeg4") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "vc1") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "vp8") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else if (file.video_codec_name == "vp9") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
} else {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 27";
}
transcode = 1;
@ -82,35 +83,36 @@ function plugin(file) {
//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 = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'h264') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'mjpeg') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'mpeg1') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'mpeg2') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'mpeg4') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'vc1') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'vp8') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else if (file.video_codec_name == 'vp9') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
}
else {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25'
if (file.video_codec_name == "h263") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "h264") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "mjpeg") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "mpeg1") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "mpeg2") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "mpeg4") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "vc1") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "vp8") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else if (file.video_codec_name == "vp9") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
} else {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 25";
}
transcode = 1;
@ -119,35 +121,36 @@ function plugin(file) {
//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 = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'h264') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'mjpeg') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'mpeg1') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'mpeg2') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'mpeg4') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'vc1') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'vp8') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else if (file.video_codec_name == 'vp9') {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
}
else {
response.preset = ',-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23'
if (file.video_codec_name == "h263") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "h264") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "mjpeg") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "mpeg1") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "mpeg2") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "mpeg4") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "vc1") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "vp8") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else if (file.video_codec_name == "vp9") {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
} else {
response.preset =
",-map 0:v -map 0:s? -c:s srt -map 0:a -c copy -c:v:0 libx265 -preset fast -crf 23";
}
transcode = 1;
@ -157,13 +160,13 @@ function plugin(file) {
//if true the neccessary response values will be changed
if (transcode == 1) {
response.processFile = true;
response.FFmpegMode = true
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File is ${file.video_resolution} but is not hevc!\n`
response.infoLog += `☒File will be transcoded!\n`
response.infoLog += `☒File is ${file.video_resolution} but is not hevc!\n`;
response.infoLog += `☒File will be transcoded!\n`;
}
return response
return response;
}
module.exports.details = details;

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_s710_nick_h265_nvenc_4K",
Stage: "Pre-processing",
@ -11,166 +7,144 @@ function details() {
Description: `[Contains built-in filter] This plugin transcodes all 4K videos to h265 using nvenc (if not in h265 already). For 4K and files in other resolutions: If not in mkv the file is remuxed into mkv. If the English language track is not in AC3,EAC3 or DTS then an AC3 track is added.\n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s710_nick_h265_nvenc_4K.js",
Tags:'pre-processing,ffmpeg,nvenc h265',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s710_nick_h265_nvenc_4K.js",
Tags: "pre-processing,ffmpeg,nvenc h265",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
response.container = ".mkv";
var jsonString = JSON.stringify(file)
response.container = '.mkv'
if (file.ffProbeData.streams[0].codec_name == 'hevc' || file.video_resolution !== "4KUHD") {
var hasPreferredLangTrack = false
var hasPreferredLangInRequiredCodecs = false
var hasAnyInRequiredCodecs = false
var audioIdx = -1
var engTrackIdx = -1
var requiredAudioCodecs = "ac3,eac3,dts"
var preferredLangTrack = "eng"
var preferredCodec = "ac3"
if (
file.ffProbeData.streams[0].codec_name == "hevc" ||
file.video_resolution !== "4KUHD"
) {
var hasPreferredLangTrack = false;
var hasPreferredLangInRequiredCodecs = false;
var hasAnyInRequiredCodecs = false;
var audioIdx = -1;
var engTrackIdx = -1;
var requiredAudioCodecs = "ac3,eac3,dts";
var preferredLangTrack = "eng";
var preferredCodec = "ac3";
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) {
hasAnyInRequiredCodecs = true
if (
requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)
) {
hasAnyInRequiredCodecs = true;
}
} catch (err) {}
try {
if ((requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) && file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack)) {
hasPreferredLangInRequiredCodecs = true
if (
requiredAudioCodecs.includes(
file.ffProbeData.streams[i].codec_name
) &&
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack)
) {
hasPreferredLangInRequiredCodecs = true;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack) && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
hasPreferredLangTrack = true
engTrackIdx = audioIdx
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack) &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
hasPreferredLangTrack = true;
engTrackIdx = audioIdx;
}
} catch (err) {}
}
if (hasPreferredLangInRequiredCodecs) {
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`;
} else if (hasPreferredLangTrack) {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`
return response
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`;
return response;
} else if (!hasAnyInRequiredCodecs) {
if (audioIdx == -1) {
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`;
} else {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`
return response
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`;
return response;
}
}
if (file.container != 'mkv') {
if (file.container != "mkv") {
response.processFile = true;
response.preset = ', -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = ", -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in mkv container! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n"
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
return response
return response;
} else {
response.processFile = true;
response.preset = '-Z "H.265 MKV 2160p60" --all-audio --all-subtitles'
response.container = '.mkv'
response.handBrakeMode = true
response.FFmpegMode = false
response.preset = '-Z "H.265 MKV 2160p60" --all-audio --all-subtitles';
response.container = ".mkv";
response.handBrakeMode = true;
response.FFmpegMode = false;
response.reQueueAfter = true;
response.infoLog += "☒ 4K file isn't in hevc! \n"
return response
response.infoLog += "☒ 4K file isn't in hevc! \n";
return response;
}
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_s7x8_winsome_h265",
Stage: "Pre-processing",
@ -11,166 +7,141 @@ function details() {
Description: `[Contains built-in filter] This plugin transcodes all videos to h265 (if not in h265 already) and remuxes if not in mkv. If the English language track is not in AC3,EAC3 or DTS then an AC3 track is added.\n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s7x8_winsome_h265.js",
Tags:'pre-processing,handbrake,ffmpeg,h265',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s7x8_winsome_h265.js",
Tags: "pre-processing,handbrake,ffmpeg,h265",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
response.container = ".mkv";
var jsonString = JSON.stringify(file)
response.container = '.mkv'
if (file.ffProbeData.streams[0].codec_name == 'hevc') {
var hasPreferredLangTrack = false
var hasPreferredLangInRequiredCodecs = false
var hasAnyInRequiredCodecs = false
var audioIdx = -1
var engTrackIdx = -1
var requiredAudioCodecs = "ac3,eac3,dts"
var preferredLangTrack = "eng"
var preferredCodec = "ac3"
if (file.ffProbeData.streams[0].codec_name == "hevc") {
var hasPreferredLangTrack = false;
var hasPreferredLangInRequiredCodecs = false;
var hasAnyInRequiredCodecs = false;
var audioIdx = -1;
var engTrackIdx = -1;
var requiredAudioCodecs = "ac3,eac3,dts";
var preferredLangTrack = "eng";
var preferredCodec = "ac3";
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) {
hasAnyInRequiredCodecs = true
if (
requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)
) {
hasAnyInRequiredCodecs = true;
}
} catch (err) {}
try {
if ((requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) && file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack)) {
hasPreferredLangInRequiredCodecs = true
if (
requiredAudioCodecs.includes(
file.ffProbeData.streams[i].codec_name
) &&
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack)
) {
hasPreferredLangInRequiredCodecs = true;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack) && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
hasPreferredLangTrack = true
engTrackIdx = audioIdx
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack) &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
hasPreferredLangTrack = true;
engTrackIdx = audioIdx;
}
} catch (err) {}
}
if (hasPreferredLangInRequiredCodecs) {
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`;
} else if (hasPreferredLangTrack) {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`
return response
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`;
return response;
} else if (!hasAnyInRequiredCodecs) {
if (audioIdx == -1) {
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`;
} else {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`
return response
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`;
return response;
}
}
if (file.container != 'mkv') {
if (file.container != "mkv") {
response.processFile = true;
response.preset = ', -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = ", -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in mkv container! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n"
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
return response
return response;
} else {
response.processFile = true;
response.preset = '-Z "H.265 MKV 2160p60" --all-audio --all-subtitles'
response.container = '.mkv'
response.handBrakeMode = true
response.FFmpegMode = false
response.preset = '-Z "H.265 MKV 2160p60" --all-audio --all-subtitles';
response.container = ".mkv";
response.handBrakeMode = true;
response.FFmpegMode = false;
response.reQueueAfter = true;
response.infoLog += "☒File isn't in hevc! \n"
return response
response.infoLog += "☒File isn't in hevc! \n";
return response;
}
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_s7x9_winsome_h265_10bit",
Stage: "Pre-processing",
@ -11,167 +7,142 @@ function details() {
Description: `[Contains built-in filter] This plugin transcodes all videos to h265 10 bit (if not in h265 already) and remuxes if not in mkv. If the English language track is not in AC3,EAC3 or DTS then an AC3 track is added.\n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s7x9_winsome_h265_10bit.js",
Tags:'pre-processing,handbrake,ffmpeg,h265',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s7x9_winsome_h265_10bit.js",
Tags: "pre-processing,handbrake,ffmpeg,h265",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video"
response.infoLog += "☒File is not video";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
response.container = ".mkv";
var jsonString = JSON.stringify(file)
response.container = '.mkv'
if (file.ffProbeData.streams[0].codec_name == 'hevc') {
var hasPreferredLangTrack = false
var hasPreferredLangInRequiredCodecs = false
var hasAnyInRequiredCodecs = false
var audioIdx = -1
var engTrackIdx = -1
var requiredAudioCodecs = "ac3,eac3,dts"
var preferredLangTrack = "eng"
var preferredCodec = "ac3"
if (file.ffProbeData.streams[0].codec_name == "hevc") {
var hasPreferredLangTrack = false;
var hasPreferredLangInRequiredCodecs = false;
var hasAnyInRequiredCodecs = false;
var audioIdx = -1;
var engTrackIdx = -1;
var requiredAudioCodecs = "ac3,eac3,dts";
var preferredLangTrack = "eng";
var preferredCodec = "ac3";
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) {
hasAnyInRequiredCodecs = true
if (
requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)
) {
hasAnyInRequiredCodecs = true;
}
} catch (err) {}
try {
if ((requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) && file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack)) {
hasPreferredLangInRequiredCodecs = true
if (
requiredAudioCodecs.includes(
file.ffProbeData.streams[i].codec_name
) &&
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack)
) {
hasPreferredLangInRequiredCodecs = true;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack) && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
hasPreferredLangTrack = true
engTrackIdx = audioIdx
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack) &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
hasPreferredLangTrack = true;
engTrackIdx = audioIdx;
}
} catch (err) {}
}
if (hasPreferredLangInRequiredCodecs) {
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`;
} else if (hasPreferredLangTrack) {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`
return response
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`;
return response;
} else if (!hasAnyInRequiredCodecs) {
if (audioIdx == -1) {
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`;
} else {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`
return response
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`;
return response;
}
}
if (file.container != 'mkv') {
if (file.container != "mkv") {
response.processFile = true;
response.preset = ', -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = ", -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in mkv container! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n"
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
return response
return response;
} else {
response.processFile = true;
response.preset = '-Z "H.265 MKV 2160p60" -e x265_10bit --all-audio --all-subtitles'
response.container = '.mkv'
response.handBrakeMode = true
response.FFmpegMode = false
response.preset =
'-Z "H.265 MKV 2160p60" -e x265_10bit --all-audio --all-subtitles';
response.container = ".mkv";
response.handBrakeMode = true;
response.FFmpegMode = false;
response.reQueueAfter = true;
response.infoLog += "☒File isn't in hevc! \n"
return response
response.infoLog += "☒File isn't in hevc! \n";
return response;
}
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_s7x9_winsome_h265_nvenc",
Stage: "Pre-processing",
@ -11,167 +7,142 @@ function details() {
Description: `[Contains built-in filter] This plugin transcodes all videos to h265 using nvenc (if not in h265 already) and remuxes if not in mkv. If the English language track is not in AC3,EAC3 or DTS then an AC3 track is added.\n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s7x9_winsome_h265_nvenc.js",
Tags:'pre-processing,handbrake,ffmpeg,nvenc h265',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_s7x9_winsome_h265_nvenc.js",
Tags: "pre-processing,handbrake,ffmpeg,nvenc h265",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
response.container = ".mkv";
var jsonString = JSON.stringify(file)
response.container = '.mkv'
if (file.ffProbeData.streams[0].codec_name == 'hevc') {
var hasPreferredLangTrack = false
var hasPreferredLangInRequiredCodecs = false
var hasAnyInRequiredCodecs = false
var audioIdx = -1
var engTrackIdx = -1
var requiredAudioCodecs = "ac3,eac3,dts"
var preferredLangTrack = "eng"
var preferredCodec = "ac3"
if (file.ffProbeData.streams[0].codec_name == "hevc") {
var hasPreferredLangTrack = false;
var hasPreferredLangInRequiredCodecs = false;
var hasAnyInRequiredCodecs = false;
var audioIdx = -1;
var engTrackIdx = -1;
var requiredAudioCodecs = "ac3,eac3,dts";
var preferredLangTrack = "eng";
var preferredCodec = "ac3";
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) {
hasAnyInRequiredCodecs = true
if (
requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)
) {
hasAnyInRequiredCodecs = true;
}
} catch (err) {}
try {
if ((requiredAudioCodecs.includes(file.ffProbeData.streams[i].codec_name)) && file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack)) {
hasPreferredLangInRequiredCodecs = true
if (
requiredAudioCodecs.includes(
file.ffProbeData.streams[i].codec_name
) &&
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack)
) {
hasPreferredLangInRequiredCodecs = true;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].tags.language.toLowerCase().includes(preferredLangTrack) && file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
hasPreferredLangTrack = true
engTrackIdx = audioIdx
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes(preferredLangTrack) &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio"
) {
hasPreferredLangTrack = true;
engTrackIdx = audioIdx;
}
} catch (err) {}
}
if (hasPreferredLangInRequiredCodecs) {
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`
response.infoLog += `☑File already has ${preferredLangTrack} language track in ${requiredAudioCodecs}! \n`;
} else if (hasPreferredLangTrack) {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:${engTrackIdx} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`
return response
response.infoLog += `☒File has ${preferredLangTrack} language track but not in ${requiredAudioCodecs}! \n`;
return response;
} else if (!hasAnyInRequiredCodecs) {
if (audioIdx == -1) {
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`
response.infoLog += `☒File does not have any audio streams. Can't create ${preferredCodec} track. \n`;
} else {
response.processFile = true;
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `,-map 0:v -map 0:a:0 -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${preferredCodec} -b:a:0 192k -ac 2`;
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`
return response
response.infoLog += `☒File has no language track in ${requiredAudioCodecs}. No ${preferredLangTrack} track marked so transcoding audio track 1 into ${preferredCodec}! \n`;
return response;
}
}
if (file.container != 'mkv') {
if (file.container != "mkv") {
response.processFile = true;
response.preset = ', -map 0 -c copy'
response.container = '.mkv'
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = ", -map 0 -c copy";
response.container = ".mkv";
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File is not in mkv container! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n"
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
return response
return response;
} else {
response.processFile = true;
response.preset = '-Z "H.265 MKV 2160p60" --all-audio --all-subtitles -e nvenc_h265'
response.container = '.mkv'
response.handBrakeMode = true
response.FFmpegMode = false
response.preset =
'-Z "H.265 MKV 2160p60" --all-audio --all-subtitles -e nvenc_h265';
response.container = ".mkv";
response.handBrakeMode = true;
response.FFmpegMode = false;
response.reQueueAfter = true;
response.infoLog += "☒File isn't in hevc! \n"
return response
response.infoLog += "☒File isn't in hevc! \n";
return response;
}
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_sdd3_Remove_Commentary_Tracks",
Stage: "Pre-processing",
@ -11,90 +7,76 @@ function details() {
Operation: "Remux",
Description: `[Contains built-in filter] If commentary tracks are detected, they will be removed. \n\n`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_sdd3_Remove_Commentary_Tracks.js",
Tags:'pre-processing,ffmpeg,audio only',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_sdd3_Remove_Commentary_Tracks.js",
Tags: "pre-processing,ffmpeg,audio only",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
response.processFile = false
response.infoLog += "☒File is not a video! \n"
return response
response.processFile = false;
response.infoLog += "☒File is not a video! \n";
return response;
} else {
response.infoLog += "☑File is a video! \n"
response.infoLog += "☑File is a video! \n";
}
var audioIdx = -1
var hasCommentaryTrack = false
var ffmpegCommandInsert = ""
var audioIdx = -1;
var hasCommentaryTrack = false;
var ffmpegCommandInsert = "";
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
//keep track of audio streams for when removing commentary track
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
//check if commentary track and passing audio stream number
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].tags.title.toLowerCase().includes("commentary")) {
ffmpegCommandInsert += ` -map -0:a:${audioIdx}`
hasCommentaryTrack = true
}
} catch (err) {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("commentary")
) {
ffmpegCommandInsert += ` -map -0:a:${audioIdx}`;
hasCommentaryTrack = true;
}
} catch (err) {}
}
if (hasCommentaryTrack === true) {
response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy`
response.container = '.' + file.container
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy`;
response.container = "." + file.container;
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File contains commentary tracks. Removing! \n"
return response
response.infoLog += "☒File contains commentary tracks. Removing! \n";
return response;
} else {
response.infoLog += "☑File doesn't contain commentary tracks! \n"
response.infoLog += "☑File doesn't contain commentary tracks! \n";
}
response.processFile = false
response.infoLog += "☑File meets conditions! \n"
return response
response.processFile = false;
response.infoLog += "☑File meets conditions! \n";
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio",
Stage: "Pre-processing",
@ -11,111 +7,99 @@ function details() {
Description: `[Contains built-in filter] This plugin removes audio tracks which are not English or are not undefined. It ensures at least 1 audio track is left in any language. \n\n
`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio.js",
Tags:'pre-processing,ffmpeg,audio only',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio.js",
Tags: "pre-processing,ffmpeg,audio only",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: '',
container: '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: '',
}
response.FFmpegMode = true
infoLog: "",
};
response.FFmpegMode = true;
//check if files is video
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
}
var ffmpegCommandInsert = ''
var audioIdx = -1
var hasNonEngTrack = false
var audioStreamsRemoved = 0
var ffmpegCommandInsert = "";
var audioIdx = -1;
var hasNonEngTrack = false;
var audioStreamsRemoved = 0;
//count number of audio streams
var audioStreamCount = file.ffProbeData.streams.filter(row => (row.codec_type.toLowerCase() == "audio")).length;
var audioStreamCount = file.ffProbeData.streams.filter(
(row) => row.codec_type.toLowerCase() == "audio"
).length;
console.log("audioStreamCount:" + audioStreamCount)
console.log("audioStreamCount:" + audioStreamCount);
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
//check if current stream is audio, update audioIdx if so
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && !(file.ffProbeData.streams[i].tags.language.toLowerCase().includes('eng') || file.ffProbeData.streams[i].tags.language.toLowerCase().includes('und'))) {
audioStreamsRemoved++
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
!(
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes("eng") ||
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes("und")
)
) {
audioStreamsRemoved++;
if (audioStreamsRemoved == audioStreamCount) {
break;
}
ffmpegCommandInsert += ` -map -0:a:${audioIdx}`
hasNonEngTrack = true
ffmpegCommandInsert += ` -map -0:a:${audioIdx}`;
hasNonEngTrack = true;
}
} catch (err) {}
}
if (hasNonEngTrack === true) {
response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy`
response.container = '.' + file.container
response.handBrakeMode = false
response.FFmpegMode = true
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy`;
response.container = "." + file.container;
response.handBrakeMode = false;
response.FFmpegMode = true;
response.reQueueAfter = true;
response.infoLog += "☒File contains tracks which are not english or undefined. Removing! \n"
return response
response.infoLog +=
"☒File contains tracks which are not english or undefined. Removing! \n";
return response;
} else {
response.infoLog += "☑File doesn't contain tracks which are not english or undefined! \n"
response.infoLog +=
"☑File doesn't contain tracks which are not english or undefined! \n";
}
response.processFile = false;
return response
return response;
}
module.exports.details = details;

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_x7ab_Remove_Subs",
Stage: "Pre-processing",
@ -10,77 +6,60 @@ function details() {
Type: "Video",
Description: `[Contains built-in filter] This plugin removes subtitles if detected. The output container is the same as the original. \n\n`,
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_x7ab_Remove_Subs.js",
Tags:'pre-processing,ffmpeg,subtitle only',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_x7ab_Remove_Subs.js",
Tags: "pre-processing,ffmpeg,subtitle only",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
response.FFmpegMode = true;
response.container = "." + file.container;
response.FFmpegMode = true
response.container = '.' + file.container
var hasSubs = false
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
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
if (hasSubs) {
response.infoLog += "☒File has subs \n"
response.preset = ',-sn -map 0 -c copy'
response.infoLog += "☒File has subs \n";
response.preset = ",-sn -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
return response;
} else {
response.infoLog += "☑File has no subs \n"
response.infoLog += "☑File has no subs \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,86 +1,62 @@
function details() {
return {
id: "Tdarr_Plugin_x7ac_Remove_Closed_Captions",
Stage: "Pre-processing",
Name: "Remove closed captions",
Type: "Video",
Operation: "Remux",
Description: "[Contains built-in filter] If detected, closed captions (XDS,608,708) will be removed.",
Description:
"[Contains built-in filter] If detected, closed captions (XDS,608,708) will be removed.",
Version: "1.00",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js",
Tags:'pre-processing,ffmpeg,subtitle only',
}
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js",
Tags: "pre-processing,ffmpeg,subtitle only",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: true,
infoLog : '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
if (file.hasClosedCaptions === true) {
response = {
processFile: true,
preset: ',-map 0 -codec copy -bsf:v "filter_units=remove_types=6"',
container : '.' + file.container ,
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog : '☒This file has closed captions \n',
}
return response
infoLog: "☒This file has closed captions \n",
};
return response;
} else {
response.infoLog += "☑Closed captions have not been detected on this file \n"
response.infoLog +=
"☑Closed captions have not been detected on this file \n";
response.processFile = false;
return response
return response;
}
}
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium",
Stage: "Pre-processing",
@ -11,148 +7,135 @@ function details() {
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",
Tags:'pre-processing,ffmpeg,h264',
}
Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js",
Tags: "pre-processing,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
var hasSubs = false
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
let streamData = file.ffProbeData.streams[i];
if(streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_name != "mov_text"){
hasSubs = true
if (
streamData.codec_type.toLowerCase() == "subtitle" &&
streamData.codec_name != "mov_text"
) {
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'
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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n"
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'
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
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.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
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.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
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n"
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.infoLog += "☒File has incompatible subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.processFile = true;
response.FFmpegMode = true
return response
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n"
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_z18s_rename_files_based_on_codec",
Stage: "Post-processing",
@ -13,60 +9,61 @@ module.exports.details = function details() {
Version: "1.00",
Link: "",
Tags: "post-processing",
}
}
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
try {
var fs = require('fs');
var path = require('path');
if (fs.existsSync(path.join(process.cwd() , '/npm'))) {
var rootModules = path.join(process.cwd() , '/npm/node_modules/')
var fs = require("fs");
var path = require("path");
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
var rootModules = ''
var rootModules = "";
}
var fsextra = require(rootModules+'fs-extra')
var fsextra = require(rootModules + "fs-extra");
var fileNameOld = file._id
var fileNameOld = file._id;
if (file.ffProbeData.streams[0].codec_name == 'hevc' && file._id.includes('264')) {
if (
file.ffProbeData.streams[0].codec_name == "hevc" &&
file._id.includes("264")
) {
file._id = file._id.replace("264", "265");
file.file = file.file.replace("264", "265");
}
if (file.ffProbeData.streams[0].codec_name == 'h264' && file._id.includes('265')) {
if (
file.ffProbeData.streams[0].codec_name == "h264" &&
file._id.includes("265")
) {
file._id = file._id.replace("265", "264");
file.file = file.file.replace("265", "264");
}
if (file.ffProbeData.streams[0].codec_name == 'h264' && file._id.includes('hevc')) {
if (
file.ffProbeData.streams[0].codec_name == "h264" &&
file._id.includes("hevc")
) {
file._id = file._id.replace("hevc", "264");
file.file = file.file.replace("hevc", "264");
}
if (fileNameOld != file._id) {
fsextra.moveSync(fileNameOld, file._id, {
overwrite: true
})
overwrite: true,
});
var response = {
file,
removeFromDB: false,
updateDB: true,
}
return response
};
return response;
}
} catch (err) { console.log(err) }
} catch (err) {
console.log(err);
}
};

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast",
Stage: "Pre-processing",
@ -11,148 +7,136 @@ function details() {
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",
Tags:'pre-processing,ffmpeg,h264',
}
Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js",
Tags: "pre-processing,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
var hasSubs = false
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
let streamData = file.ffProbeData.streams[i];
if(streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_name != "mov_text"){
hasSubs = true
if (
streamData.codec_type.toLowerCase() == "subtitle" &&
streamData.codec_name != "mov_text"
) {
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'
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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n"
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'
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
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.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
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.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
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n"
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.infoLog += "☒File has incompatible 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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n"
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,8 +1,4 @@
function details() {
return {
id: "Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow",
Stage: "Pre-processing",
@ -11,149 +7,136 @@ function details() {
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",
Tags:'pre-processing,ffmpeg,h264',
}
Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js",
Tags: "pre-processing,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
var hasSubs = false
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
let streamData = file.ffProbeData.streams[i];
if(streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_name != "mov_text"){
hasSubs = true
if (
streamData.codec_type.toLowerCase() == "subtitle" &&
streamData.codec_name != "mov_text"
) {
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'
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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n"
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'
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
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.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
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.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
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n"
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.infoLog += "☒File has incompatible 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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n"
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,159 +1,143 @@
function details() {
return {
id: "Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast",
Stage: "Pre-processing",
Name: "TheRealShadoh FFmpeg Subs VeryFast, video MP4, audio AAC, keep subs. ",
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",
Tags:'pre-processing,ffmpeg,h264',
}
Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_Veryfast.js",
Tags: "pre-processing,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset : '',
container : '.mp4',
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog : '',
}
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
console.log("File is not video")
response.infoLog += "☒File is not video \n"
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file);
var jsonString = JSON.stringify(file)
var hasSubs = false
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
let streamData = file.ffProbeData.streams[i];
if(streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_name != "mov_text"){
hasSubs = true
if (
streamData.codec_type.toLowerCase() == "subtitle" &&
streamData.codec_name != "mov_text"
) {
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'
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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n"
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'
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
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.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
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.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
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n"
response.infoLog += "☑File has no title metadata \n";
}
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.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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n"
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.infoLog += "☒File has incompatible 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
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n"
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -56,10 +56,8 @@ 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. 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,
For community plugins:
@ -69,7 +67,6 @@ For the plugin link, I'll add this once you create a PR to community plugins.
For local plugins:
Add them to 'User\Documents\Tdarr\Plugins\Local'. In Tdarr, select 'Local' in the plugin section of the library you're in and add your local plugin id.
Example file object:
var file = {
_id: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
@ -312,6 +309,3 @@ Add them to 'User\Documents\Tdarr\Plugins\Local'. In Tdarr, select 'Local' in th
processingStatus: false,
video_codec_name: 'h264',
video_resolution: '720p' }

@ -1,8 +1,4 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_aaaa_Pre_Proc_Example",
Stage: "Pre-processing", //Preprocessing or Post-processing. Determines when the plugin will be executed.
@ -14,9 +10,10 @@ module.exports.details = function details() {
Link: "https://github.com/HaveAGitGat/Tdarr_Plugin_aaaa_Pre_Proc_Example",
Tags: "ffmpeg,h265", //Provide tags to categorise your plugin in the plugin browser.Tag options: h265,hevc,h264,nvenc h265,nvenc h264,video only,audio only,subtitle only,handbrake,ffmpeg,radarr,sonarr,pre-processing,post-processing,configurable
Inputs: [ //(Optional) Inputs you'd like the user to enter to allow your plugin to be easily configurable from the UI
Inputs: [
//(Optional) Inputs you'd like the user to enter to allow your plugin to be easily configurable from the UI
{
name: 'language',
name: "language",
tooltip: `Enter one language tag here for the language of the subtitles you'd like to keep.
\\nExample:\\n
@ -28,41 +25,36 @@ module.exports.details = function details() {
\\nExample:\\n
de` //Each line following `Example:` will be clearly formatted. \\n used for line breaks
de`, //Each line following `Example:` will be clearly formatted. \\n used for line breaks
},
{
name: 'channels',
name: "channels",
tooltip: `Desired audio channel number.
\\nExample:\\n
2`
2`,
},
]
}
}
],
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
//Must return this object at some point in the function else plugin will fail.
var response = {
processFile: false, //If set to false, the file will be skipped. Set to true to have the file transcoded.
preset: '', //HandBrake/FFmpeg CLI arguments you'd like to use.
preset: "", //HandBrake/FFmpeg CLI arguments you'd like to use.
//For FFmpeg, the input arguments come first followed by a comma, followed by the output argument.
// Examples
//HandBrake
// '-Z "Very Fast 1080p30"'
//FFmpeg
// '-sn,-map_metadata -1 -c:v copy -c:a copy'
container: '.mp4', // The container of the transcoded output file.
container: ".mp4", // The container of the transcoded output file.
handBrakeMode: false, //Set whether to use HandBrake or FFmpeg for transcoding
FFmpegMode: false,
reQueueAfter: true, //Leave as true. File will be re-qeued afterwards and pass through the plugin filter again to make sure it meets conditions.
infoLog: '', //This will be shown when the user clicks the 'i' (info) button on a file in the output queue if
infoLog: "", //This will be shown when the user clicks the 'i' (info) button on a file in the output queue if
//it has been skipped.
// Give reasons why it has been skipped ('File has no title metadata, File meets conditions!')
@ -70,75 +62,68 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
file,
removeFromDB: false, //Tell Tdarr to remove file from database if true
updateDB: false, //Change file object above and update database if true
}
console.log(inputs.language) //eng if user entered 'eng' in input box in Tdarr plugin UI
console.log(inputs.channels) //2 if user entered '2' in input box in Tdarr plugin UI
};
console.log(inputs.language); //eng if user entered 'eng' in input box in Tdarr plugin UI
console.log(inputs.channels); //2 if user entered '2' in input box in Tdarr plugin UI
//Here we specify that we want the output file container to be the same as the current container.
response.container = '.' + file.container
response.container = "." + file.container;
//We will use FFmpeg for this procedure.
response.FFmpegMode = true
response.FFmpegMode = true;
//Check if file has title metadata
if (file.meta.Title != undefined) {
//if so, remove it
response.infoLog += " File has title metadata"
response.preset = ',-map_metadata -1 -c:v copy -c:a copy'
response.processFile = true
return response
response.infoLog += " File has title metadata";
response.preset = ",-map_metadata -1 -c:v copy -c:a copy";
response.processFile = true;
return response;
} else {
response.infoLog += " File has no title metadata"
}
response.infoLog += " File meets conditions!"
return response
response.infoLog += " File has no title metadata";
}
response.infoLog += " File meets conditions!";
return response;
};
module.exports.onTranscodeSuccess = function onTranscodeSuccess(file, librarySettings, inputs) {
console.log('Transcode success! Now do some stuff with the newly scanned file.')
module.exports.onTranscodeSuccess = function onTranscodeSuccess(
file,
librarySettings,
inputs
) {
console.log(
"Transcode success! Now do some stuff with the newly scanned file."
);
//Optional response if you need to modify database
var response = {
file,
removeFromDB: false,
updateDB: false,
}
return response
}
module.exports.onTranscodeError = function onTranscodeError(file, librarySettings, inputs) {
};
console.log('Transcode fail! Now do some stuff with the original file.')
return response;
};
module.exports.onTranscodeError = function onTranscodeError(
file,
librarySettings,
inputs
) {
console.log("Transcode fail! Now do some stuff with the original file.");
//Optional response if you need to modify database
var response = {
file,
removeFromDB: false,
updateDB: false,
}
return response
}
};
return response;
};
//Example file object:
// {

@ -1,8 +1,4 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_zzzz_Post_Proc_Example",
Stage: "Post-processing", //Preprocessing or Post-processing. Determines when the plugin will be executed. This plugin does some stuff after all plugins have been executed
@ -14,9 +10,10 @@ module.exports.details = function details() {
Link: "https://github.com/HaveAGitGat/Tdarr_Plugin_aaaa_Post_Proc_Example",
Tags: "ffmpeg,h265", //Provide tags to categorise your plugin in the plugin browser.Tag options: h265,hevc,h264,nvenc h265,nvenc h264,video only,audio only,subtitle only,handbrake,ffmpeg,radarr,sonarr,pre-processing,post-processing,configurable
Inputs: [ //(Optional) Inputs you'd like the user to enter to allow your plugin to be easily configurable from the UI
Inputs: [
//(Optional) Inputs you'd like the user to enter to allow your plugin to be easily configurable from the UI
{
name: 'language',
name: "language",
tooltip: `Enter one language tag here for the language of the subtitles you'd like to keep.
\\nExample:\\n
@ -26,37 +23,33 @@ module.exports.details = function details() {
fr
\\nExample:\\n
de` //Each line following `Example:` will be clearly formatted. \\n used for line breaks
de`, //Each line following `Example:` will be clearly formatted. \\n used for line breaks
},
{
name: 'channels',
name: "channels",
tooltip: `Desired audio channel number.
\\nExample:\\n
2`
2`,
},
]
}
}
],
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
console.log('Transcode success! Now do some stuff with the newly scanned file.')
console.log(
"Transcode success! Now do some stuff with the newly scanned file."
);
//Optional response if you need to modify database
var response = {
file,
removeFromDB: false,
updateDB: false,
}
return response
}
};
return response;
};
//Example file object:
// {

@ -1,14 +1,21 @@
var fs = require('fs');
var fs = require("fs");
var path = require("path");
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd() , '/npm/node_modules/')
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
var rootModules = ''
var rootModules = "";
}
const importFresh = require(rootModules+'import-fresh');
const importFresh = require(rootModules + "import-fresh");
module.exports.remuxContainer = importFresh('./library/actions/remuxContainer.js')
module.exports.transcodeStandardiseAudioCodecs = importFresh('./library/actions/transcodeStandardiseAudioCodecs.js')
module.exports.transcodeAddAudioStream = importFresh('./library/actions/transcodeAddAudioStream.js')
module.exports.transcodeKeepOneAudioStream = importFresh('./library/actions/transcodeKeepOneAudioStream.js')
module.exports.remuxContainer = importFresh(
"./library/actions/remuxContainer.js"
);
module.exports.transcodeStandardiseAudioCodecs = importFresh(
"./library/actions/transcodeStandardiseAudioCodecs.js"
);
module.exports.transcodeAddAudioStream = importFresh(
"./library/actions/transcodeAddAudioStream.js"
);
module.exports.transcodeKeepOneAudioStream = importFresh(
"./library/actions/transcodeKeepOneAudioStream.js"
);

@ -1,15 +1,20 @@
var fs = require('fs');
var fs = require("fs");
var path = require("path");
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd() , '/npm/node_modules/')
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
var rootModules = ''
var rootModules = "";
}
const importFresh = require(rootModules+'import-fresh');
const importFresh = require(rootModules + "import-fresh");
module.exports.filterByAge = importFresh('./library/filters/filterByAge.js')
module.exports.filterByCodec = importFresh('./library/filters/filterByCodec.js')
module.exports.filterByMedium = importFresh('./library/filters/filterByMedium.js')
module.exports.filterByResolution = importFresh('./library/filters/filterByResolution.js')
module.exports.filterBySize = importFresh('./library/filters/filterBySize.js')
module.exports.filterByAge = importFresh("./library/filters/filterByAge.js");
module.exports.filterByCodec = importFresh(
"./library/filters/filterByCodec.js"
);
module.exports.filterByMedium = importFresh(
"./library/filters/filterByMedium.js"
);
module.exports.filterByResolution = importFresh(
"./library/filters/filterByResolution.js"
);
module.exports.filterBySize = importFresh("./library/filters/filterBySize.js");

@ -1,11 +1,11 @@
var fs = require('fs');
var fs = require("fs");
var path = require("path");
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd() , '/npm/node_modules/')
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
var rootModules = ''
var rootModules = "";
}
const importFresh = require(rootModules+'import-fresh');
const importFresh = require(rootModules + "import-fresh");
module.exports.filters = importFresh('./filters.js')
module.exports.actions = importFresh('./actions.js')
module.exports.filters = importFresh("./filters.js");
module.exports.actions = importFresh("./actions.js");

@ -1,38 +1,25 @@
function remuxContainer(file, container) {
try {
if (file.container != container) {
var response = {
processFile: true,
note:`File is not in ${container} \n`
}
return response
note: `File is not in ${container} \n`,
};
return response;
} else {
var response = {
processFile: false,
note:`File is already in ${container} \n`
}
return response
note: `File is already in ${container} \n`,
};
return response;
}
} catch (err) {
var response = {
processFile: false,
note:`library.actions.remuxContainer error: ${err} \n`
note: `library.actions.remuxContainer error: ${err} \n`,
};
return response;
}
return response
}
}
module.exports = remuxContainer
module.exports = remuxContainer;

@ -1,7 +1,9 @@
module.exports = function transcodeAddAudioStream(file, audioEncoder, langTag, channelCount) {
module.exports = function transcodeAddAudioStream(
file,
audioEncoder,
langTag,
channelCount
) {
// response.preset = library.actions.transcodeAddAudioStream(file, 'aac', 'en', 1).preset
//Function required responses
@ -10,304 +12,265 @@ module.exports = function transcodeAddAudioStream(file, audioEncoder, langTag, c
// note
try {
var audioCodec = audioEncoder;
langTag = langTag.toLowerCase();
var audioCodec = audioEncoder
langTag = langTag.toLowerCase()
if (audioEncoder == 'dca') {
audioCodec = 'dts'
if (audioEncoder == "dca") {
audioCodec = "dts";
}
if (audioEncoder == 'libmp3lame') {
audioCodec = 'mp3'
if (audioEncoder == "libmp3lame") {
audioCodec = "mp3";
}
//Step 1: Check if the file already has the required stream codec/langtag/channel count
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) && stream.channels == channelCount) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) &&
stream.channels == channelCount
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (hasStreamAlready.length > 0) {
return {
preset: '',
preset: "",
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels\n`
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels\n`,
};
}
}
//Step 2: Check if file has streams with specified lang tag
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false
return false;
});
})
console.log("streamsWithLangTag:" + streamsWithLangTag)
console.log("streamsWithLangTag:" + streamsWithLangTag);
if (streamsWithLangTag.length != 0) {
return attemptMakeStreamLang(langTag)
return attemptMakeStreamLang(langTag);
} else {
return attemptMakeStreamUnd('und')
return attemptMakeStreamUnd("und");
}
function attemptMakeStreamLang(langTag) {
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
return first;
} else {
return second
return second;
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) && stream.channels == channelCount) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
stream.tags.language
.toLowerCase()
.includes(langTag.toLowerCase()) &&
stream.channels == channelCount
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (hasStreamAlready.length > 0) {
return {
preset: '',
preset: "",
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels \n`
}
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${channelCount}`,
processFile: true,
note: `The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}). Adding! \n`
}
note: `The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}). Adding! \n`,
};
}
} else {
console.log("here3");
console.log('here3')
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) && stream.channels == highestChannelCount.channels) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
stream.tags.language
.toLowerCase()
.includes(langTag.toLowerCase()) &&
stream.channels == highestChannelCount.channels
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (hasStreamAlready.length > 0) {
return {
preset: '',
preset: "",
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${highestChannelCount.channels} channels (Highest available) \n`
}
note: `File already has ${langTag} stream in ${audioEncoder}, ${highestChannelCount.channels} channels (Highest available) \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${highestChannelCount.channels}`,
processFile: true,
note: `The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track. \n`
}
note: `The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track. \n`,
};
}
}
}
function attemptMakeStreamUnd(langTag) {
console.log(
"No tracks with specified lang tag exist. Checking undefined tracks."
);
console.log('No tracks with specified lang tag exist. Checking undefined tracks.')
console.log(langTag)
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
console.log(langTag);
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && (stream.tags == undefined || stream.tags.language == undefined || stream.tags.language.toLowerCase().includes(langTag))) {
return true
if (
stream.codec_type == "audio" &&
(stream.tags == undefined ||
stream.tags.language == undefined ||
stream.tags.language.toLowerCase().includes(langTag))
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (streamsWithLangTag.length == 0) {
return {
preset: ``,
processFile: false,
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`
}
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`,
};
}
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
return first;
} else {
return second
return second;
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && (stream.tags == undefined || stream.tags.language == undefined || stream.tags.language.toLowerCase().includes(langTag)) && stream.channels == channelCount) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
(stream.tags == undefined ||
stream.tags.language == undefined ||
stream.tags.language.toLowerCase().includes(langTag)) &&
stream.channels == channelCount
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (hasStreamAlready.length > 0) {
return {
preset: '',
preset: "",
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels \n`
}
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${channelCount}`,
processFile: true,
note: `The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}). Adding! \n`
}
note: `The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}). Adding! \n`,
};
}
} else {
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && (stream.tags == undefined || stream.tags.language == undefined || stream.tags.language.toLowerCase().includes(langTag)) && stream.channels == highestChannelCount.channels) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
(stream.tags == undefined ||
stream.tags.language == undefined ||
stream.tags.language.toLowerCase().includes(langTag)) &&
stream.channels == highestChannelCount.channels
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (hasStreamAlready.length > 0) {
return {
preset: '',
preset: "",
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${highestChannelCount.channels} channels (Highest available) \n`
}
note: `File already has ${langTag} stream in ${audioEncoder}, ${highestChannelCount.channels} channels (Highest available) \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:a -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${highestChannelCount.channels}`,
processFile: true,
note: `The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track. \n`
note: `The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track. \n`,
};
}
}
}
}
} catch (err) {
return {
preset: '',
preset: "",
processFile: false,
note: `library.actions.transcodeAddAudioStream error: ${err} \n`
}
}
note: `library.actions.transcodeAddAudioStream error: ${err} \n`,
};
}
};

@ -1,7 +1,9 @@
module.exports = function transcodeKeepOneAudioStream(file, audioEncoder, langTag, channelCount) {
module.exports = function transcodeKeepOneAudioStream(
file,
audioEncoder,
langTag,
channelCount
) {
// response.preset = library.actions.transcodeKeepOneAudioStream(file, 'aac', 'en', 1).preset
//Function required responses
@ -10,356 +12,314 @@ module.exports = function transcodeKeepOneAudioStream(file, audioEncoder, langTa
// note
try {
var audioCodec = audioEncoder;
langTag = langTag.toLowerCase();
var audioCodec = audioEncoder
langTag = langTag.toLowerCase()
if (audioEncoder == 'dca') {
audioCodec = 'dts'
if (audioEncoder == "dca") {
audioCodec = "dts";
}
if (audioEncoder == 'libmp3lame') {
audioCodec = 'mp3'
if (audioEncoder == "libmp3lame") {
audioCodec = "mp3";
}
var reqLang = langTag
var numberOfAudioStreams = file.ffProbeData.streams.filter(stream => stream.codec_type == 'audio').length
var reqLang = langTag;
var numberOfAudioStreams = file.ffProbeData.streams.filter(
(stream) => stream.codec_type == "audio"
).length;
//Step 1: Check if the file already has the required stream codec/langtag/channel count
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) && stream.channels == channelCount) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) &&
stream.channels == channelCount
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
preset: "",
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels. It is the only track! \n`
}
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels. It is the only track! \n`,
};
} else if (hasStreamAlready.length >= 1) {
var audioStreamToKeep = hasStreamAlready[0].index
var ffmpegCommandInsert = ''
var audioStreamToKeep = hasStreamAlready[0].index;
var ffmpegCommandInsert = "";
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && i !== audioStreamToKeep) {
ffmpegCommandInsert += ` -map -0:${i}`
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
i !== audioStreamToKeep
) {
ffmpegCommandInsert += ` -map -0:${i}`;
}
} catch (err) {}
}
return {
preset: `, -map 0 ${ffmpegCommandInsert} -c copy`,
processFile: true,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels. It is not the only track, removing others. \n`
}
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels. It is not the only track, removing others. \n`,
};
}
//Step 2: Check if file has streams with specified lang tag
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
console.log("streamsWithLangTag:" + streamsWithLangTag)
console.log("streamsWithLangTag:" + streamsWithLangTag);
if (streamsWithLangTag.length != 0) {
return attemptMakeStreamLang(langTag)
return attemptMakeStreamLang(langTag);
} else {
return attemptMakeStreamUnd('und')
return attemptMakeStreamUnd("und");
}
function attemptMakeStreamLang(langTag) {
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
return first;
} else {
return second
return second;
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) && stream.channels == channelCount) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
stream.tags.language
.toLowerCase()
.includes(langTag.toLowerCase()) &&
stream.channels == channelCount
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
preset: "",
processFile: false,
note: `The required stream already exists. It is the only audio stream. \n`
}
note: `The required stream already exists. It is the only audio stream. \n`,
};
} else if (hasStreamAlready.length >= 1) {
return {
preset: `,-map 0:v -map 0:${hasStreamAlready[0].index} -map 0:s? -map 0:d? -c copy`,
processFile: true,
note: `The required stream already exists. Removing others. \n`
}
note: `The required stream already exists. Removing others. \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${channelCount}`,
processFile: true,
note: `The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}). Adding it and removing others! \n`
note: `The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}). Adding it and removing others! \n`,
};
}
}
} else {
console.log("here3");
console.log('here3')
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) && stream.channels == highestChannelCount.channels) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
stream.tags.language
.toLowerCase()
.includes(langTag.toLowerCase()) &&
stream.channels == highestChannelCount.channels
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
preset: "",
processFile: false,
note: `The best ${reqLang} stream already exists. It is the only audio stream. \n`
}
note: `The best ${reqLang} stream already exists. It is the only audio stream. \n`,
};
} else if (hasStreamAlready.length >= 1) {
return {
preset: `,-map 0:v -map 0:${hasStreamAlready[0].index} -map 0:s? -map 0:d? -c copy`,
processFile: true,
note: `The best ${reqLang} stream already exists. Removing others. \n`
}
note: `The best ${reqLang} stream already exists. Removing others. \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${highestChannelCount.channels}`,
processFile: true,
note: `The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track, removing others. \n`
}
note: `The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track, removing others. \n`,
};
}
}
}
function attemptMakeStreamUnd(langTag) {
console.log(
"No tracks with specified lang tag exist. Checking undefined tracks."
);
console.log('No tracks with specified lang tag exist. Checking undefined tracks.')
console.log(langTag)
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
console.log(langTag);
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && (stream.tags == undefined || stream.tags.language == undefined || stream.tags.language.toLowerCase().includes(langTag))) {
return true
if (
stream.codec_type == "audio" &&
(stream.tags == undefined ||
stream.tags.language == undefined ||
stream.tags.language.toLowerCase().includes(langTag))
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (streamsWithLangTag.length == 0) {
return {
preset: ``,
processFile: false,
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`
}
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`,
};
}
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
return first;
} else {
return second
return second;
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && (stream.tags == undefined || stream.tags.language == undefined || stream.tags.language.toLowerCase().includes(langTag)) && stream.channels == channelCount) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
(stream.tags == undefined ||
stream.tags.language == undefined ||
stream.tags.language.toLowerCase().includes(langTag)) &&
stream.channels == channelCount
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
preset: "",
processFile: false,
note: `No ${reqLang} streams. The required und stream already exists. It is the only audio stream. \n`
}
note: `No ${reqLang} streams. The required und stream already exists. It is the only audio stream. \n`,
};
} else if (hasStreamAlready.length >= 1) {
return {
preset: `,-map 0:v -map 0:${hasStreamAlready[0].index} -map 0:s? -map 0:d? -c copy`,
processFile: true,
note: `No ${reqLang} streams. The required und stream already exists. Removing others. \n`
}
note: `No ${reqLang} streams. The required und stream already exists. Removing others. \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${channelCount}`,
processFile: true,
note: `No ${reqLang} streams. The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}).Adding it and removing others! \n`
note: `No ${reqLang} streams. The required channel count ${channelCount} is lower than the highest available channel count (${highestChannelCount.channels}).Adding it and removing others! \n`,
};
}
}
} else {
var hasStreamAlready = file.ffProbeData.streams.filter(stream => {
var hasStreamAlready = file.ffProbeData.streams.filter((stream) => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && (stream.tags == undefined || stream.tags.language == undefined || stream.tags.language.toLowerCase().includes(langTag)) && stream.channels == highestChannelCount.channels) {
return true
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
(stream.tags == undefined ||
stream.tags.language == undefined ||
stream.tags.language.toLowerCase().includes(langTag)) &&
stream.channels == highestChannelCount.channels
) {
return true;
}
} catch (err) {}
return false
})
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
preset: "",
processFile: false,
note: `No ${reqLang} streams. The best und stream already exists. It is the only audio stream. \n`
}
note: `No ${reqLang} streams. The best und stream already exists. It is the only audio stream. \n`,
};
} else if (hasStreamAlready.length >= 1) {
return {
preset: `,-map 0:v -map 0:${hasStreamAlready[0].index} -map 0:s? -map 0:d? -c copy`,
processFile: true,
note: `No ${reqLang} streams. The best stream already exists. Removing others. \n`
}
note: `No ${reqLang} streams. The best stream already exists. Removing others. \n`,
};
} else {
return {
preset: `,-map 0:v -map 0:${highestChannelCount.index} -map 0:s? -map 0:d? -c copy -c:a:0 ${audioEncoder} -ac ${highestChannelCount.channels}`,
processFile: true,
note: `No ${reqLang} streams. The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track, removing others. \n`
note: `No ${reqLang} streams. The required channel count (${channelCount}) is higher than the highest channel available in specified lang tag (${highestChannelCount.channels}). Adding lower channel track, removing others. \n`,
};
}
}
}
}
} catch (err) {
return {
preset: '',
preset: "",
processFile: false,
note: `library.actions.transcodeKeepOneAudioStream error: ${err} \n`
}
}
note: `library.actions.transcodeKeepOneAudioStream error: ${err} \n`,
};
}
};

@ -1,77 +1,59 @@
module.exports = function transcodeStandardiseAudioCodecs(file, audioEncoder) {
//Function required responses
// preset
// processFile
// note
try {
var audioIdx = -1;
var hasNonSpecifiedAudioCodecStream = false;
var ffmpegCommandInsert = "";
var audioCodec = audioEncoder;
var audioIdx = -1
var hasNonSpecifiedAudioCodecStream = false
var ffmpegCommandInsert = ''
var audioCodec = audioEncoder
if (audioEncoder == 'dca') {
audioCodec = 'dts'
if (audioEncoder == "dca") {
audioCodec = "dts";
}
if (audioEncoder == 'libmp3lame') {
audioCodec = 'mp3'
if (audioEncoder == "libmp3lame") {
audioCodec = "mp3";
}
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) {}
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].codec_name != audioCodec) {
ffmpegCommandInsert += ` -c:a:${audioIdx} ${audioEncoder}`
hasNonSpecifiedAudioCodecStream = true
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
file.ffProbeData.streams[i].codec_name != audioCodec
) {
ffmpegCommandInsert += ` -c:a:${audioIdx} ${audioEncoder}`;
hasNonSpecifiedAudioCodecStream = true;
}
} catch (err) {}
}
if (hasNonSpecifiedAudioCodecStream === true) {
return {
preset: `,-map 0:v -map 0:a -map 0:s? -map 0:d? -c copy ${ffmpegCommandInsert}`,
processFile: true,
note: `File has audio streams which aren't in ${audioCodec} \n`
}
note: `File has audio streams which aren't in ${audioCodec} \n`,
};
}
return {
preset: '',
preset: "",
processFile: false,
note: `File does not have any audio streams which aren't in ${audioCodec} \n`
}
note: `File does not have any audio streams which aren't in ${audioCodec} \n`,
};
} catch (err) {
return {
preset: '',
preset: "",
processFile: false,
note: `library.actions.transcodeStandardiseAudioCodecs error: ${err} \n`
}
}
note: `library.actions.transcodeStandardiseAudioCodecs error: ${err} \n`,
};
}
};

@ -1,40 +1,29 @@
function filterByAge(file, ageCutOff_Seconds) {
try {
var timeNow = new Date()
var dateCreated = new Date(file.statSync.birthtime)
var fileAge = Math.round((timeNow - dateCreated) / 1000)
var timeNow = new Date();
var dateCreated = new Date(file.statSync.birthtime);
var fileAge = Math.round((timeNow - dateCreated) / 1000);
if (fileAge > ageCutOff_Seconds) {
var response = {
outcome: false,
note: `☒File creation date is older than specified requirement. \n`
}
return response
note: `☒File creation date is older than specified requirement. \n`,
};
return response;
} else {
var response = {
outcome: true,
note: `☑File creation date is within specified requirement. \n`
}
return response
note: `☑File creation date is within specified requirement. \n`,
};
return response;
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterByAge error: ${err} \n`
}
return response
note: `library.filters.filterByAge error: ${err} \n`,
};
return response;
}
}
module.exports = filterByAge
module.exports = filterByAge;

@ -1,82 +1,60 @@
function filterByCodec(file, mode, codecs) {
try {
// console.log(file,mode,codecs)
var allCodecs = file.ffProbeData.streams.map(row => row.codec_name)
var allCodecs = file.ffProbeData.streams.map((row) => row.codec_name);
var included = false
var included = false;
for (var i = 0; i < allCodecs.length; i++) {
if (codecs.toLowerCase().includes(allCodecs[i])) {
included = true
included = true;
}
}
if (mode === 'include') {
if (mode === "include") {
if (included) {
var response = {
outcome: true,
note: `☑Codec included \n`
}
return response
note: `☑Codec included \n`,
};
return response;
} else {
var response = {
outcome: false,
note: `☒Codec excluded \n`
note: `☒Codec excluded \n`,
};
return response;
}
return response
}
} else if (mode === 'exclude') {
} else if (mode === "exclude") {
if (included) {
var response = {
outcome: false,
note: `☒Codec excluded \n`
}
return response
note: `☒Codec excluded \n`,
};
return response;
} else {
var response = {
outcome: true,
note: `☑Codec not excluded \n`
}
return response
note: `☑Codec not excluded \n`,
};
return response;
}
}
var response = {
outcome: false,
note: `library.filters.filterByCodec error: ${err} \n`
}
return response
note: `library.filters.filterByCodec error: ${err} \n`,
};
return response;
} catch (err) {
console.log(err)
console.log(err);
var response = {
outcome: false,
note: `Filter error hello! ${err}\n`
note: `Filter error hello! ${err}\n`,
};
return response;
}
return response
}
}
module.exports = filterByCodec
module.exports = filterByCodec;

@ -1,34 +1,25 @@
function filterByMedium(file, medium) {
try {
if (file.fileMedium !== medium) {
var response = {
outcome: false,
note: `☒File is not ${medium} \n`
}
return response
note: `☒File is not ${medium} \n`,
};
return response;
} else {
var response = {
outcome: true,
note: `☑File is ${medium} \n`
}
return response
note: `☑File is ${medium} \n`,
};
return response;
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterByMedium error: ${err} \n`
}
return response
note: `library.filters.filterByMedium error: ${err} \n`,
};
return response;
}
}
module.exports = filterByMedium
module.exports = filterByMedium;

@ -1,58 +1,45 @@
function filterByResolution(file, mode, resolution) {
try {
if (mode === 'exclude') {
if (resolution.toLowerCase().includes(file.video_resolution.toLowerCase())) {
if (mode === "exclude") {
if (
resolution.toLowerCase().includes(file.video_resolution.toLowerCase())
) {
var response = {
outcome: false,
note: `☒File is in excluded resolution. \n`
}
return response
note: `☒File is in excluded resolution. \n`,
};
return response;
} else {
var response = {
outcome: true,
note: `☑File is not in excluded resolution. \n`
}
return response
}
} else if (mode === 'include') {
if (resolution.toLowerCase().includes(file.video_resolution.toLowerCase())) {
note: `☑File is not in excluded resolution. \n`,
};
return response;
}
} else if (mode === "include") {
if (
resolution.toLowerCase().includes(file.video_resolution.toLowerCase())
) {
var response = {
outcome: true,
note: `☑File is in included resolution. \n`
}
return response
note: `☑File is in included resolution. \n`,
};
return response;
} else {
var response = {
outcome: false,
note: `☒File is not in included resolution. \n`
}
return response
note: `☒File is not in included resolution. \n`,
};
return response;
}
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterByResolution error: ${err} \n`
note: `library.filters.filterByResolution error: ${err} \n`,
};
return response;
}
return response
}
}
module.exports = filterByResolution
module.exports = filterByResolution;

@ -1,34 +1,28 @@
function filterBySize(file, lowerBound, upperBound) {
try {
if (file.file_size / 1000 >= lowerBound && file.file_size / 1000 <= upperBound) {
if (
file.file_size / 1000 >= lowerBound &&
file.file_size / 1000 <= upperBound
) {
var response = {
outcome: true,
note: `☑File size is within filter limits. \n`
}
return response
note: `☑File size is within filter limits. \n`,
};
return response;
} else {
var response = {
outcome: false,
note: `☒File size is not within filter limits. \n`
}
return response
note: `☒File size is not within filter limits. \n`,
};
return response;
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterBySize error: ${err} \n`
}
return response
note: `library.filters.filterBySize error: ${err} \n`,
};
return response;
}
}
module.exports = filterBySize
module.exports = filterBySize;

Loading…
Cancel
Save