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

@ -1,178 +1,190 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_Migz1FFMPEG",
Stage: "Pre-processing",
Name: "Migz-Transcode Using Nvidia GPU & FFMPEG",
Type: "Video",
Operation: "Transcode",
Description: `Files not in H265 will be transcoded into H265 using Nvidia GPU with ffmpeg, 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',
tooltip: `Specify output container of file, ensure that all stream types you may have are supported by your chosen container. mkv is recommended.
return {
id: "Tdarr_Plugin_MC93_Migz1FFMPEG",
Stage: "Pre-processing",
Name: "Migz-Transcode Using Nvidia GPU & FFMPEG",
Type: "Video",
Operation: "Transcode",
Description: `Files not in H265 will be transcoded into H265 using Nvidia GPU with ffmpeg, 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",
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`
},
{
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.
mp4`,
},
{
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`
},
{
name: 'enable_10bit',
tooltip: `Specify if output file should be 10bit. Default is false.
4000`,
},
{
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: '',
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
var response = {
processFile: false,
preset: "",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
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;
} else {
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 ";
}
// 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;
}
// 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;
} else {
var duration = file.ffProbeData.streams[0].duration * 0.0166667;
}
// Set up required variables.
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));
// 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);
// Allow some leeway under and over the targetBitrate.
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;
}
// 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;
}
// 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
} else {
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 "
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
// If set to true then add 10bit argument
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} `;
}
// 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;
}
// 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}`;
response.processFile = true;
return response;
}
// Increment videoIdx.
videoIdx++;
}
// 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
}
// 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)
} else {
var duration = (file.ffProbeData.streams[0].duration * 0.0166667)
}
// Set up required variables.
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))
// 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)
// Allow some leeway under and over the targetBitrate.
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
}
// Set bitrateSettings variable using bitrate information calulcated earlier.
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`;
// 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`;
}
// 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
}
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
// If set to true then add 10bit argument
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} `
}
// 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
}
// 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}`
response.processFile = true;
return response
}
// Increment videoIdx.
videoIdx++
}
}
// Set bitrateSettings variable using bitrate information calulcated earlier.
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`
// 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
} 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;
module.exports.plugin = plugin;

@ -1,157 +1,168 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_Migz1FFMPEG_CPU",
Stage: "Pre-processing",
Name: "Migz-Transcode Using CPU & FFMPEG",
Type: "Video",
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',
tooltip: `Specify output container of file, ensure that all stream types you may have are supported by your chosen container. mkv is recommended.
return {
id: "Tdarr_Plugin_MC93_Migz1FFMPEG_CPU",
Stage: "Pre-processing",
Name: "Migz-Transcode Using CPU & FFMPEG",
Type: "Video",
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",
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`
},
{
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.
mp4`,
},
{
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`
},
{
name: 'enable_10bit',
tooltip: `Specify if output file should be 10bit. Default is false.
4000`,
},
{
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: '',
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
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
} else {
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 "
}
// 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
var response = {
processFile: false,
preset: "",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
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;
} else {
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 ";
}
// 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;
}
// 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;
} else {
var duration = file.ffProbeData.streams[0].duration * 0.0166667;
}
// Set up required variables.
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));
// 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);
// Allow some leeway under and over the targetBitrate.
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;
}
// 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;
}
// 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)
} else {
var duration = (file.ffProbeData.streams[0].duration * 0.0166667)
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
// If set to true then add 10bit argument
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} `;
}
// 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;
}
// 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}`;
response.processFile = true;
return response;
}
// Increment videoIdx.
videoIdx++;
}
// Set up required variables.
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))
// 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)
// Allow some leeway under and over the targetBitrate.
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
}
// 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
}
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
// If set to true then add 10bit argument
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} `
}
// 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
}
// 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}`
response.processFile = true;
return response
}
// Increment videoIdx.
videoIdx++
}
}
// Set bitrateSettings variable using bitrate information calulcated earlier.
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
}
// Set bitrateSettings variable using bitrate information calulcated earlier.
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;
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,116 +1,125 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_Migz2CleanTitle",
Stage: "Pre-processing",
Name: "Migz-Clean title metadata",
Type: "Video",
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',
tooltip: `Specify if audio titles should be checked & cleaned. Optional.
return {
id: "Tdarr_Plugin_MC93_Migz2CleanTitle",
Stage: "Pre-processing",
Name: "Migz-Clean title metadata",
Type: "Video",
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",
tooltip: `Specify if audio titles should be checked & cleaned. Optional.
\\nExample:\\n
true
\\nExample:\\n
false`
},
{
name: 'clean_subtitles',
tooltip: `Specify if subtitle titles should be checked & cleaned. Optional.
false`,
},
{
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,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
var response = {
processFile: false,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: "",
};
}
// Set up required variables.
var ffmpegCommandInsert = "";
var videoIdx = 0;
var audioIdx = 0;
var subtitleIdx = 0;
var convert = false;
// Set up required variables.
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";
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"
response.processFile = false;
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
// 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;
} catch (err) {}
// Go through each stream in the file.
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
}
// Increment videoIdx.
videoIdx++
// Go through each stream in the file.
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;
}
// Increment 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
}
// Increment audioIdx.
audioIdx++
// 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;
}
// Increment 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
}
// Increment subtitleIdx.
subtitleIdx++
// 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;
}
// Increment 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.reQueueAfter = true;
response.processFile = true;
} else {
response.infoLog += "☑File has no title metadata \n"
}
return response
// 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.reQueueAfter = true;
response.processFile = true;
} else {
response.infoLog += "☑File has no title metadata \n";
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,17 +1,19 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_Migz3CleanAudio",
Stage: "Pre-processing",
Name: "Migz-Clean audio streams",
Type: "Audio",
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',
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
return {
id: "Tdarr_Plugin_MC93_Migz3CleanAudio",
Stage: "Pre-processing",
Name: "Migz-Clean audio streams",
Type: "Audio",
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",
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`
},
{
name: 'commentary',
tooltip: `Specify if audio tracks that contain commentary/description should be removed.
eng,und,jap`,
},
{
name: "commentary",
tooltip: `Specify if audio tracks that contain commentary/description should be removed.
\\nExample:\\n
true
\\nExample:\\n
false`
},
{
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
false`,
},
{
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`
},
{
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.
por`,
},
{
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,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
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"
response.processFile = false;
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.processFile = false;
return response
var response = {
processFile: false,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
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";
response.processFile = false;
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.processFile = false;
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;
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;
}
} 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;
}
} 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"
) {
// 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;
}
} 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;
}
// 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;
}
}
}
// 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;
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
}
} 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
}
} 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") {
// 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
}
} 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
}
// 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
}
}
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 (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;
}
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 (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
}
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
}
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
}
}
} catch (err) {}
// Check if stream type is audio and increment audioIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
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;
}
}
// 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
}
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;
}
}
} catch (err) {}
// 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
} else {
response.processFile = false
response.infoLog += "☑File doesn't contain audio tracks which are unwanted or that require tagging.\n"
// Check if stream type is audio and increment audioIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++;
}
return response
}
// 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;
}
// 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;
} else {
response.processFile = false;
response.infoLog +=
"☑File doesn't contain audio tracks which are unwanted or that require tagging.\n";
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,145 +1,172 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_Migz4CleanSubs",
Stage: "Pre-processing",
Name: "Migz-Clean subtitle streams",
Type: "subtitles",
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',
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
return {
id: "Tdarr_Plugin_MC93_Migz4CleanSubs",
Stage: "Pre-processing",
Name: "Migz-Clean subtitle streams",
Type: "subtitles",
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",
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`
},
{
name: 'commentary',
tooltip: `Specify if subtitle tracks that contain commentary/description should be removed.
eng,jap`,
},
{
name: "commentary",
tooltip: `Specify if subtitle tracks that contain commentary/description should be removed.
\\nExample:\\n
true
\\nExample:\\n
false`
},
{
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
false`,
},
{
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,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
}
var response = {
processFile: false,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
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"
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";
response.processFile = false;
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.processFile = false;
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.processFile = false;
return response;
}
// Set up required variables.
var language = inputs.language.split(",")
var ffmpegCommandInsert = ''
var subtitleIdx = 0
var convert = false
// Set up required variables.
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++) {
// 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;
}
} catch (err) {}
// 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
}
} 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;
}
} 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
}
} 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") {
// 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
}
} 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
}
// 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
}
}
// 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"
) {
// 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;
}
} catch (err) {}
// Check if stream type is subtitle and increment subtitleIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
subtitleIdx++
// 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;
}
// 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;
}
}
}
// 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;
} else {
response.processFile = false;
response.infoLog += "☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n"
// Check if stream type is subtitle and increment subtitleIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
subtitleIdx++;
}
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;
} else {
response.processFile = false;
response.infoLog +=
"☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n";
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,137 +1,151 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_Migz5ConvertAudio",
Stage: "Pre-processing",
Name: "Migz-Convert audio streams",
Type: "Audio",
Operation: "Transcode",
Description: `This plugin can convert any 2.0 audio track/s to AAC and can create downmixed audio tracks. \n\n`,
Version: "2.1",
Link: "",
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.
return {
id: "Tdarr_Plugin_MC93_Migz5ConvertAudio",
Stage: "Pre-processing",
Name: "Migz-Convert audio streams",
Type: "Audio",
Operation: "Transcode",
Description: `This plugin can convert any 2.0 audio track/s to AAC and can create downmixed audio tracks. \n\n`,
Version: "2.1",
Link: "",
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`
},
{
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.
false`,
},
{
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,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
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
}
// 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"
response.processFile = false;
return response
}
var response = {
processFile: false,
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "",
};
// Set up required variables.
var ffmpegCommandInsert = ''
var audioIdx = 0
var has2Channel = false
var has6Channel = false
var has8Channel = false
var convert = false
// 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;
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// 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
}
if (file.ffProbeData.streams[i].channels == "6") {
has6Channel = true
}
if (file.ffProbeData.streams[i].channels == "8") {
has8Channel = true
}
}
} catch (err) {}
}
// 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";
response.processFile = false;
return response;
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is audio.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
// Catch error here incase user left inputs.downmix empty.
try {
// 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
}
// 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
}
}
} catch (err) {}
// Set up required variables.
var ffmpegCommandInsert = "";
var audioIdx = 0;
var has2Channel = false;
var has6Channel = false;
var has8Channel = false;
var convert = false;
// Catch error here incase user left inputs.downmix empty.
try {
// 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
}
}
} catch (err) {}
audioIdx++
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// 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;
}
if (file.ffProbeData.streams[i].channels == "6") {
has6Channel = true;
}
if (file.ffProbeData.streams[i].channels == "8") {
has8Channel = true;
}
}
} catch (err) {}
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is audio.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
// Catch error here incase user left inputs.downmix empty.
try {
// 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;
}
// 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;
}
}
} catch (err) {}
// 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 `
} else {
response.infoLog += "☑File contains all required audio formats. \n"
response.processFile = false;
// Catch error here incase user left inputs.downmix empty.
try {
// 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;
}
}
} catch (err) {}
audioIdx++;
}
return response
}
// 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 `;
} else {
response.infoLog += "☑File contains all required audio formats. \n";
response.processFile = false;
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,169 +1,187 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_Migz6OrderStreams",
Stage: "Pre-processing",
Name: "Migz-Order Streams",
Type: "Streams",
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,'
}
return {
id: "Tdarr_Plugin_MC93_Migz6OrderStreams",
Stage: "Pre-processing",
Name: "Migz-Order Streams",
Type: "Streams",
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,",
};
}
function plugin(file) {
var response = {
processFile: false,
preset: '',
container: '.' + file.container,
handBrakeMode: false,
FFmpegMode: true,
infoLog: '',
}
var response = {
processFile: false,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
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
// 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;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is video.
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"
}
// Increment videoIdx.
videoIdx++
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is video.
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";
}
// Increment 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"
}
// Increment 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"
}
// Increment 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"
}
// Increment audio6Idx.
audio6Idx++
}
// Check if audio track is 8 channel.
if (file.ffProbeData.streams[i].channels == "8") {
// Increment audio8Idx.
audio8Idx++
}
}
// 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";
}
// Increment audioIdx.
audioIdx++;
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
// Increment subtitleIdx
subtitleIdx++
}
} catch (err) {}
}
// 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";
}
// Increment 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";
}
// Increment audio6Idx.
audio6Idx++;
}
// Go through each stream in the 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} `
}
} catch (err) {}
}
// Check if audio track is 8 channel.
if (file.ffProbeData.streams[i].channels == "8") {
// Increment audio8Idx.
audio8Idx++;
}
}
// Go through each stream in the 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} `
}
} catch (err) {}
}
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
// Increment subtitleIdx
subtitleIdx++;
}
} catch (err) {}
}
// Go through each stream in the 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} `
}
} catch (err) {}
}
// Go through each stream in the 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} `;
}
} catch (err) {}
}
// Go through each stream in the 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} `
}
} catch (err) {}
}
// Go through each stream in the 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} `;
}
} catch (err) {}
}
// Go through each stream in the 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} `
}
} catch (err) {}
}
// Go through each stream in the 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} `;
}
} catch (err) {}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
ffmpegCommandInsert += `-map 0:${i} `
}
} catch (err) {}
}
// Go through each stream in the 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} `;
}
} catch (err) {}
}
// 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.reQueueAfter = true;
response.infoLog += "☒ Streams are out of order, reorganizing streams. Video, Audio, Subtitles. \n"
} else {
response.infoLog += "☑ Streams are in expected order. \n "
response.processFile = false;
}
return response
// Go through each stream in the 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} `;
}
} catch (err) {}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
}
// 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.reQueueAfter = true;
response.infoLog +=
"☒ Streams are out of order, reorganizing streams. Video, Audio, Subtitles. \n";
} else {
response.infoLog += "☑ Streams are in expected order. \n ";
response.processFile = false;
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,64 +1,69 @@
function details() {
return {
id: "Tdarr_Plugin_MC93_MigzImageRemoval",
Stage: "Pre-processing",
Name: "Migz-Remove image formats from file",
Type: "Video",
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'
}
return {
id: "Tdarr_Plugin_MC93_MigzImageRemoval",
Stage: "Pre-processing",
Name: "Migz-Remove image formats from file",
Type: "Video",
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",
};
}
function plugin(file, librarySettings, inputs) {
var response = {
processFile: false,
preset: '',
handBrakeMode: false,
container: '.' + file.container,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
var response = {
processFile: false,
preset: "",
handBrakeMode: false,
container: "." + file.container,
FFmpegMode: true,
reQueueAfter: true,
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
}
// 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;
}
// Set up required variables.
var videoIdx = 0
var extraArguments = ""
var convert = false
// Set up required variables.
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} `
}
// Increment videoIdx.
videoIdx++
}
// 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} `;
}
// Increment 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.processFile = true;
} else {
response.processFile = false;
response.infoLog += "☑File doesn't contain any unwanted image format streams.\n"
}
return response
// 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.processFile = true;
} else {
response.processFile = false;
response.infoLog +=
"☑File doesn't contain any unwanted image format streams.\n";
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,84 +1,94 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_MC93_MigzPlex_Autoscan",
Stage: "Post-processing",
Name: "Send request for file to be scanned by plex_autoscan.",
Type: "Video",
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",
Tags: "3rd party,post-processing,configurable",
return {
id: "Tdarr_Plugin_MC93_MigzPlex_Autoscan",
Stage: "Post-processing",
Name: "Send request for file to be scanned by plex_autoscan.",
Type: "Video",
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",
Tags: "3rd party,post-processing,configurable",
Inputs: [{
name: 'autoscan_address',
tooltip: `
Inputs: [
{
name: "autoscan_address",
tooltip: `
Enter the IP address/URL for autoscan. Must include http(s)://
\\nExample:\\n
http://192.168.0.10
\\nExample:\\n
https://subdomain.domain.tld`
},
{
name: 'autoscan_port',
tooltip: `
https://subdomain.domain.tld`,
},
{
name: "autoscan_port",
tooltip: `
Enter the port Autoscan is using, default is 3468
\\nExample:\\n
3468`
},
{
name: 'autoscan_passkey',
tooltip: `
3468`,
},
{
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"
response.processFile = false;
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
// 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";
response.processFile = false;
return response;
}
// Set up required variables.
var response = ""
filepath = `${file.file}`
// 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;
// Set content of request/post.
request.post({
headers: {
'content-type': 'application/json'
},
url: `${ADDRESS}:${PORT}/${PASSKEY}`,
form: {
"eventType": "Manual",
"filepath": `${filepath}`
}
}, (error, res, body) => {
if (error) {
console.error(error)
}
console.log(`statusCode: ${res.statusCode}`)
console.log(body)
})
// Set up required variables.
var response = "";
filepath = `${file.file}`;
// Set content of request/post.
request.post(
{
headers: {
"content-type": "application/json",
},
url: `${ADDRESS}:${PORT}/${PASSKEY}`,
form: {
eventType: "Manual",
filepath: `${filepath}`,
},
},
(error, res, body) => {
if (error) {
console.error(error);
}
console.log(`statusCode: ${res.statusCode}`);
console.log(body);
}
);
console.log("request next")
console.log(request.post)
}
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,75 +7,55 @@ 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",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
processFile : false,
preset : '',
container : '.mp4',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
response.FFmpegMode = true
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
} else {
var jsonString = JSON.stringify(file)
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'
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
}else{
response.infoLog += "☑File has no title metadata \n"
}
response.infoLog += "☑File meets conditions! \n"
return response
return response;
} else {
response.infoLog += "☑File has no title metadata \n";
}
response.infoLog += "☑File meets conditions! \n";
return response;
}
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -1,138 +1,138 @@
function details() {
return {
id: "Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30",
Stage: "Pre-processing",
Name:
"HaveAGitGat HandBrake VeryFast1080p30, No title meta, no subs, 192Kb AAC stereo,MP4 ",
Type: "Video",
Description: `[Contains built-in filter] This plugin transcodes into H264 using HandBrake's 'Very Fast 1080p30' preset if the file is not in H264 already. It removes subs, metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (any) doesn't exist. The output container is MP4. \n\n
`,
Version: "1.00",
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js",
Tags: "pre-processing,handbrake,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response;
} else {
var jsonString = JSON.stringify(file);
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
if (file.ffProbeData.streams[0].codec_name != "h264") {
response.infoLog += "☒File is not in h264! \n";
response.preset = '-Z "Very Fast 1080p30"';
response.reQueueAfter = true;
response.processFile = true;
response.handBrakeMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (hasSubs) {
response.infoLog += "☒File has subs \n";
response.preset = ",-sn -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no subs \n";
}
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 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
",-sn -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;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != "undefined" && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset = ",-sn -map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata";
}
if (!jsonString.includes("aac")) {
response.infoLog += "☒File has no aac track \n";
response.preset =
",-map 0:v -map 0: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;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n";
}
response.infoLog += "☑File meets conditions! \n";
return response;
}
}
module.exports.details = details;
module.exports.plugin = plugin;
function details() {
return {
id: "Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30",
Stage: "Pre-processing",
Name:
"HaveAGitGat HandBrake VeryFast1080p30, No title meta, no subs, 192Kb AAC stereo,MP4 ",
Type: "Video",
Description: `[Contains built-in filter] This plugin transcodes into H264 using HandBrake's 'Very Fast 1080p30' preset if the file is not in H264 already. It removes subs, metadata (if a title exists) and adds a stereo 192kbit AAC track if an AAC track (any) doesn't exist. The output container is MP4. \n\n
`,
Version: "1.00",
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30.js",
Tags: "pre-processing,handbrake,ffmpeg,h264",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response;
} else {
var jsonString = JSON.stringify(file);
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
if (file.ffProbeData.streams[0].codec_name != "h264") {
response.infoLog += "☒File is not in h264! \n";
response.preset = '-Z "Very Fast 1080p30"';
response.reQueueAfter = true;
response.processFile = true;
response.handBrakeMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (hasSubs) {
response.infoLog += "☒File has subs \n";
response.preset = ",-sn -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no subs \n";
}
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 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
",-sn -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;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != "undefined" && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset = ",-sn -map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset = ",-map_metadata -1 -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata";
}
if (!jsonString.includes("aac")) {
response.infoLog += "☒File has no aac track \n";
response.preset =
",-map 0:v -map 0: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;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n";
}
response.infoLog += "☑File meets conditions! \n";
return response;
}
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -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) {
response.processFile = false;
response.infoLog += "☒ Inputs not entered! \n";
return response;
}
var encoder = inputs.codec;
var encoder = inputs.codec
if (encoder == 'mp3') {
encoder = `libmp3lame`
} else if (encoder == 'dts') {
encoder = `dca`
if (encoder == "mp3") {
encoder = `libmp3lame`;
} else if (encoder == "dts") {
encoder = `dca`;
}
var codecs_to_transcode = inputs.codecs_to_transcode.split(",");
var hasStreamsToTranscode = false;
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
}else{
response.infoLog += "☑File is already in hevc! \n"
}
response.infoLog += "☒File is not in hevc! \n";
return response;
} else {
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) { }
} 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) { }
} 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) { }
} 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) { }
} 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,20 +1,20 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_c0r1_SetDefaultAudioStream",
Stage: "Pre-processing",
Name: "Set Default Audio Stream (Based On Channel Count)",
Type: "Audio",
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",
Tags:"audio only,ffmpeg,configurable",
Inputs: [
{
name: 'channels',
tooltip: `Desired audio channel number.
return {
id: "Tdarr_Plugin_c0r1_SetDefaultAudioStream",
Stage: "Pre-processing",
Name: "Set Default Audio Stream (Based On Channel Count)",
Type: "Audio",
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",
Tags: "audio only,ffmpeg,configurable",
Inputs: [
{
name: "channels",
tooltip: `Desired audio channel number.
\\nExample:\\n
@ -26,84 +26,86 @@ 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,
handBrakeMode: false,
FFmpegMode: true,
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].disposition.default === 1){
defaultAudioStreams++;
}
}
var response = {
processFile: false,
preset: "",
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
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].disposition.default === 1) {
defaultAudioStreams++;
}
}
// 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(!defaultSet){
ffmpegCommandInsert += `-disposition:${i} default `
defaultSet = true
} else {
ffmpegCommandInsert += `-disposition:${i} 0 `
}
} else {
ffmpegCommandInsert += `-disposition:${i} 0 `
}
}
// 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 (!defaultSet) {
ffmpegCommandInsert += `-disposition:${i} default `;
defaultSet = true;
} else {
ffmpegCommandInsert += `-disposition:${i} 0 `;
}
} else {
ffmpegCommandInsert += `-disposition:${i} 0 `;
}
}
// Only process when there is a matching stream and
// 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"
}
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"
}
// Only process when there is a matching stream and
// 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";
}
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";
} else {
if (matchingAudioStreams < 1) {
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 ";
} else {
if(matchingAudioStreams < 1){
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 "
} else {
response.infoLog += "☑ Unexpected: Did not process \n "
}
response.processFile = false;
response.infoLog += "☑ Unexpected: Did not process \n ";
}
return response
}
response.processFile = false;
}
return response;
};

@ -4,189 +4,193 @@ function details() {
Stage: "Pre-processing",
Name: "Tiered FFMPEG NVENC settings depending on resolution",
Type: "Video",
Operation:"Transcode",
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) {
var transcode = 0; //if this var changes to 1 the file will be transcoded
var bitrateprobe = 0; //bitrate from ffprobe
var bitrateprobe = 0; //bitrate from ffprobe
var bitratetarget = 0;
var bitratemax = 0;
var bitratecheck = 0;
var subcli = `-c:s copy`;
var maxmux = '';
var map = '-map 0'
//default values that will be returned
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: '',
maxmux: false,
}
//check if the file is a video, if not the function will be stopped immediately
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
}
//codec will be checked so it can be transcoded correctly
if (file.video_codec_name == 'h263') {
response.preset = `-c:v h263_cuvid`
//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;
}
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`
//codec will be checked so it can be transcoded correctly
if (file.video_codec_name == "h263") {
response.preset = `-c:v h263_cuvid`;
} else if (file.video_codec_name == "h264") {
if (file.ffProbeData.streams[0].profile != "High 10") {
//Remove HW Decoding for High 10 Profile
response.preset = `-c:v h264_cuvid`;
}
} else if (file.video_codec_name == "mjpeg") {
response.preset = `c:v mjpeg_cuvid`;
} else if (file.video_codec_name == "mpeg1") {
response.preset = `-c:v mpeg1_cuvid`;
} else if (file.video_codec_name == "mpeg2") {
response.preset = `-c:v mpeg2_cuvid`;
}
// skipping this one because it's empty
// else if (file.video_codec_name == 'mpeg4') {
// response.preset = ``
// }
else if (file.video_codec_name == "vc1") {
response.preset = `-c:v vc1_cuvid`;
} else if (file.video_codec_name == "vp8") {
response.preset = `-c:v vp8_cuvid`;
} else if (file.video_codec_name == "vp9") {
response.preset = `-c:v vp9_cuvid`;
}
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`
}
//Set Subtitle Var before adding encode cli
//Set Subtitle Var before adding encode cli
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" && file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" ) {
subcli = `-c:s srt`
}
}
catch (err) { }
//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) { }
//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?`
}
}
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
bitratemax = bitratetarget + 500; // Set max bitrate to 6MB Higher
}
else {
bitratetarget = 1000;
bitratemax = 1500;
try {
if (
file.ffProbeData.streams[i].codec_name.toLowerCase() == "mov_text" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
subcli = `-c:s srt`;
}
} catch (err) {}
//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) {}
//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?`;
}
} 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 * 0.8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 500; // Set max bitrate to 6MB Higher
} else {
bitratetarget = 1000;
bitratemax = 1500;
}
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 29 -b:v ${bitratetarget}k -maxrate:v 1500k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}`;
transcode = 1;
}
//file will be encoded if the resolution is 720p
//codec will be checked so it can be transcoded correctly
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
bitratemax = bitratetarget + 2000; // Set max bitrate to 6MB Higher
}
else {
bitratetarget = 2000;
bitratemax = 4000;
//file will be encoded if the resolution is 720p
//codec will be checked so it can be transcoded correctly
if (file.video_resolution === "720p") {
bitratecheck = 2000000;
if (bitrateprobe != null && bitrateprobe < bitratecheck) {
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 {
bitratetarget = 2000;
bitratemax = 4000;
}
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 30 -b:v ${bitratetarget}k -maxrate:v ${bitratemax}k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}`;
transcode = 1;
}
//file will be encoded if the resolution is 1080p
//codec will be checked so it can be transcoded correctly
if(file.video_resolution === "1080p") {
bitratecheck = 2500000;
if(bitrateprobe != null && bitrateprobe < bitratecheck) {
bitratetarget = parseInt((bitrateprobe * .8) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 2500; // Set max bitrate to 6MB Higher
}
else {
bitratetarget = 2500;
bitratemax = 5000;
//file will be encoded if the resolution is 1080p
//codec will be checked so it can be transcoded correctly
if (file.video_resolution === "1080p") {
bitratecheck = 2500000;
if (bitrateprobe != null && bitrateprobe < bitratecheck) {
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 {
bitratetarget = 2500;
bitratemax = 5000;
}
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:V 31 -b:v ${bitratetarget}k -maxrate:v ${bitratemax}k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}`;
transcode = 1;
}
//file will be encoded if the resolution is 4K
//codec will be checked so it can be transcoded correctly
if(file.video_resolution === "4KUHD") {
bitratecheck = 14000000;
if(bitrateprobe != null && bitrateprobe < bitratecheck) {
bitratetarget = parseInt((bitrateprobe * .7) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 6000; // Set max bitrate to 6MB Higher
//file will be encoded if the resolution is 4K
//codec will be checked so it can be transcoded correctly
if (file.video_resolution === "4KUHD") {
bitratecheck = 14000000;
if (bitrateprobe != null && bitrateprobe < bitratecheck) {
bitratetarget = parseInt((bitrateprobe * 0.7) / 1000); // Lower Bitrate to 60% of original and convert to KB
bitratemax = bitratetarget + 6000; // Set max bitrate to 6MB Higher
} else {
bitratetarget = 14000;
bitratemax = 20000;
}
else {
bitratetarget = 14000;
bitratemax = 20000;
}
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -b:v ${bitratetarget}k -maxrate:v ${bitratemax}k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}`;
transcode = 1;
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v 31 -b:v ${bitratetarget}k -maxrate:v ${bitratemax}k -preset slow -rc-lookahead 32 -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}`;
transcode = 1;
}
//check if the file is eligible for transcoding
//if true the neccessary response values will be changed
//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 += `☒File is ${file.video_resolution}!\n`
response.infoLog += `☒File is not hevc!\n`
response.infoLog += `☒File bitrate is ${parseInt(bitrateprobe / 1000)}kb!\n`
if(bitrateprobe < bitratecheck) {
response.infoLog += `File bitrate is LOWER than the Default Target Bitrate!\n`
}
else {
response.infoLog += `File bitrate is HIGHER than the Default Target Bitrate!\n`
}
response.infoLog += `☒Target Bitrate set to ${bitratetarget}kb!\n`
response.infoLog += `File is being transcoded!\n`
}
return response
response.infoLog += `☒File is ${file.video_resolution}!\n`;
response.infoLog += `☒File is not hevc!\n`;
response.infoLog += `☒File bitrate is ${parseInt(
bitrateprobe / 1000
)}kb!\n`;
if (bitrateprobe < bitratecheck) {
response.infoLog += `File bitrate is LOWER than the Default Target Bitrate!\n`;
} else {
response.infoLog += `File bitrate is HIGHER than the Default Target Bitrate!\n`;
}
response.infoLog += `☒Target Bitrate set to ${bitratetarget}kb!\n`;
response.infoLog += `File is being transcoded!\n`;
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -4,75 +4,75 @@ function details() {
Stage: "Pre-processing",
Name: "Mjpeg Stream False Not A Video Fixer",
Type: "Video",
Operation:"",
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) {
var transcode = 0; //if this var changes to 1 the file will be transcoded
//default values that will be returned
//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
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
//check for mjpeg streams and set the preset if mjpeg streams are found
try {
if ((file.ffProbeData.streams[i].codec_name.toLowerCase() == "mjpeg") && file.ffProbeData.streams[i].codec_type.toLowerCase() == "video" ) {
response.preset = `,-map 0 -map -0:v:1 -c:v copy -c:a copy -c:s copy`
response.infoLog = "☒File is not a video but has Mjpeg Stream! \n"
}
}
catch (err) { }
infoLog: "",
};
response.container = "." + file.container;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
//check for mjpeg streams and set the preset if mjpeg streams are found
try {
if (
file.ffProbeData.streams[i].codec_name.toLowerCase() == "mjpeg" &&
file.ffProbeData.streams[i].codec_type.toLowerCase() == "video"
) {
response.preset = `,-map 0 -map -0:v:1 -c:v copy -c:a copy -c:s copy`;
response.infoLog = "☒File is not a video but has Mjpeg Stream! \n";
}
} catch (err) {}
}
//If preset is not set check if file is video and stop (reque if it is a video)
if (response.preset != `,-map 0 -map -0:v:1 -c:v copy -c:a copy -c:s copy`) {
if (file.fileMedium !== "video") {
console.log("File is not video!")
response.infoLog += " File is not video\n"
response.processFile = false;
if (response.preset != `,-map 0 -map -0:v:1 -c:v copy -c:a copy -c:s copy`) {
if (file.fileMedium !== "video") {
console.log("File is not video!");
response.infoLog += " File is not video\n";
response.processFile = false;
return response
}
else {
response.infoLog += "☑File is a video Without Mjpeg! \n"
response.processFile = false
response.reQueueAfter = true
return response
}
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
if (file.fileMedium !== "video") {
transcode = 1;
} else {
response.infoLog += "☑File is a video With Mjpeg! \n";
response.processFile = false;
response.reQueueAfter = true;
return response;
}
}
}
//check if the file is eligible for transcoding
//if true the neccessary response values will be changed
//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",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
processFile : false,
preset : '',
container : '.mp4',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
response.FFmpegMode = true
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
} else {
var jsonString = JSON.stringify(file)
var hasSubs = false
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){
hasSubs = true
}
} catch (err) { }
}
//
if(file.ffProbeData.streams[0].codec_name != 'h264' || file.ffProbeData.streams[0].width > 720 || file.ffProbeData.streams[0].height > 480 ){
return response;
} else {
var jsonString = JSON.stringify(file);
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
//
if (
file.ffProbeData.streams[0].codec_name != "h264" ||
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
}else{
response.infoLog += "☑File is h264 480p! \n"
}
//
if(file.meta.Title != "undefined" && hasSubs){
response.infoLog += "☒File is not h264 480p! \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no title and has no subs \n"
}
if(file.meta.Title != undefined ){
response.infoLog += "☒File has title and has subs \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no title metadata \n"
}
if(hasSubs){
response.infoLog += "☒File has title metadata \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no subs \n"
}
if( file.container != 'mkv'){
response.infoLog += "☒File has subs \n";
return response;
} else {
response.infoLog += "☑File has no subs \n";
}
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
}else{
response.infoLog += "☑File is in mkv container! \n"
}
response.processFile = false;
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
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",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
processFile : false,
preset : '',
container : '.mp4',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
response.FFmpegMode = true
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
} else {
var jsonString = JSON.stringify(file)
var hasSubs = false
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){
hasSubs = true
}
} catch (err) { }
}
//
if(file.ffProbeData.streams[0].codec_name != 'h264' || file.ffProbeData.streams[0].width > 1280 || file.ffProbeData.streams[0].height > 720 ){
return response;
} else {
var jsonString = JSON.stringify(file);
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
//
if (
file.ffProbeData.streams[0].codec_name != "h264" ||
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
}else{
response.infoLog += "☑File is h264 720p! \n"
}
//
if(file.meta.Title != "undefined" && hasSubs){
response.infoLog += "☒File is not h264 720p! \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no title and has no subs \n"
}
if(file.meta.Title != undefined ){
response.infoLog += "☒File has title and has subs \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no title metadata \n"
}
if(hasSubs){
response.infoLog += "☒File has title metadata \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no subs \n"
}
if( file.container != 'mkv'){
response.infoLog += "☒File has subs \n";
return response;
} else {
response.infoLog += "☑File has no subs \n";
}
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
}else{
response.infoLog += "☑File is in mkv container! \n"
}
response.processFile = false;
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
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",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
processFile : false,
preset : '',
container : '.mp4',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
response.FFmpegMode = true
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
} else {
var jsonString = JSON.stringify(file)
var hasSubs = false
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){
hasSubs = true
}
} catch (err) { }
}
//
if(file.ffProbeData.streams[0].codec_name != 'h264' || file.ffProbeData.streams[0].width > 1920 || file.ffProbeData.streams[0].height > 1080 ){
return response;
} else {
var jsonString = JSON.stringify(file);
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
//
if (
file.ffProbeData.streams[0].codec_name != "h264" ||
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
}else{
response.infoLog += "☑File is h264 1080p!"
}
//
if(file.meta.Title != "undefined" && hasSubs){
response.infoLog += "☒File is not h264 1080p! \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no title and has no subs \n"
}
if(file.meta.Title != undefined ){
response.infoLog += "☒File has title and has subs \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no title metadata \n"
}
if(hasSubs){
response.infoLog += "☒File has title metadata \n";
return response;
} else {
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
}else{
response.infoLog += "☑File has no subs \n"
}
if( file.container != 'mkv'){
response.infoLog += "☒File has subs \n";
return response;
} else {
response.infoLog += "☑File has no subs \n";
}
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
}else{
response.infoLog += "☑File is in mkv container! \n"
}
response.processFile = false;
response.infoLog += "☑File meets conditions! \n"
return response
response.infoLog += "☒File is not in mkv container! \n";
return response;
} else {
response.infoLog += "☑File is in mkv container! \n";
}
response.processFile = false;
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,143 +1,154 @@
const fs = require('fs');
const execSync = require('child_process').execSync;
const fs = require("fs");
const execSync = require("child_process").execSync;
function details() {
return {
id: "Tdarr_Plugin_e5c3_CnT_Add_Subtitles",
Stage: "Pre-processing",
Name: "Add subtitles to MKV files",
Type: "Video",
Operation:"Remux",
Description: `This plugin will check for subtitles, they should be named according to the ISO 639-2 language code.\nA subtitle could look like this: eng.srt\n If there are subtitles found they will be added with FFMPEG, if there are no subs of that language found.\n On first run node module iso-639-2 will be installed in the documents folder.\n Created by @control#0405`,
Version: "1.3",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Add_Subtitles.js",
Tags:'pre-processing,ffmpeg,subtitle only,configurable',
Inputs: [
{
name: 'install_packages',
tooltip: `Please change this to "yes", it allows the plugin to install the required nodemodule. (iso-639-2) \\nExample:\\n yes`
},
{
name: 'container',
tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv`
},
]
}
return {
id: "Tdarr_Plugin_e5c3_CnT_Add_Subtitles",
Stage: "Pre-processing",
Name: "Add subtitles to MKV files",
Type: "Video",
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",
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: "container",
tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv`,
},
],
};
}
function plugin(file, librarySettings, inputs, otherArguments) {
//default response
var response = {
processFile: false,
preset: `,`,
container: '.mkv',
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: `Searching new subtitles...\n`,
}
if (inputs.container !== undefined) {
response.container = inputs.container;
console.log(`Changed container to: ` + inputs.container);
}
//default response
var response = {
processFile: false,
preset: `,`,
container: ".mkv",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: `Searching new subtitles...\n`,
};
if (inputs.install_packages == "yes") {
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.`
return response;
if (inputs.container !== undefined) {
response.container = inputs.container;
console.log(`Changed container to: ` + inputs.container);
}
if (inputs.install_packages == "yes") {
if (
!fs.existsSync(`${otherArguments.homePath}/Tdarr/node_modules/iso-639-2`)
) {
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.`;
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');
if (fs.existsSync(`/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`;
return response;
}
var i = 0; //int for counting lang[position]
var found_subtitle_stream = 0;
var sub = 0; //becomes first subtitle stream
var lang = iso6392; //languages to check against
var path = file.meta.Directory; //path of media folder
var exist = 0; //if the language exists should be added this becomes 1
var new_subs = 0; //count the new subs
var added_subs = 0; //counts the amount of subs that have been mapped
var preset_import = "";
var preset_meta = "";
//find first subtitle stream
while (found_subtitle_stream == 0 && sub < file.ffProbeData.streams.length) {
if (file.ffProbeData.streams[sub].codec_type.toLowerCase() == "subtitle") {
found_subtitle_stream = 1;
} else {
response.infoLog += `Nodemodule iso-639-2 isn't installed!\nTry Again`
return response;
sub++;
}
}
var i = 0; //int for counting lang[position]
var found_subtitle_stream = 0;
var sub = 0; //becomes first subtitle stream
var lang = iso6392; //languages to check against
var path = file.meta.Directory; //path of media folder
var exist = 0; //if the language exists should be added this becomes 1
var new_subs = 0 //count the new subs
var added_subs = 0; //counts the amount of subs that have been mapped
var preset_import = '';
var preset_meta = '';
//find first subtitle stream
while (found_subtitle_stream == 0 && sub < file.ffProbeData.streams.length) {
if (file.ffProbeData.streams[sub].codec_type.toLowerCase() == "subtitle") {
found_subtitle_stream = 1;
} else {
sub++;
}
}
response.infoLog += `Path: ${path}\n`;
for (i = 0; i < lang.length; i++) {
//check if srt file exists in folder
if (fs.existsSync(`${path}/${lang[i].iso6392B}.srt`)) {
response.infoLog += `Found subtitle ${lang[i].name}.srt\n`;
if (found_subtitle_stream == 1) {
//check if language already exists
for (sub_stream = sub; sub_stream < file.ffProbeData.streams.length; sub_stream++) {
//response.infoLog += `does ${lang[i].name} exist in stream ${sub_stream}?\n`
if (file.ffProbeData.streams[sub_stream].tags.language) {
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`;
}
}
}
} else {
exist = 0;
}
//add if it hasn't found the language
if (exist != 1) {
preset_import += ` -sub_charenc "UTF-8" -f srt -i "${path}/${lang[i].iso6392B}.srt"`;
preset_meta += ` -metadata:s:s:${new_subs} language=${lang[i].iso6392B}`;
new_subs++;
response.infoLog += `Path: ${path}\n`;
for (i = 0; i < lang.length; i++) {
//check if srt file exists in folder
if (fs.existsSync(`${path}/${lang[i].iso6392B}.srt`)) {
response.infoLog += `Found subtitle ${lang[i].name}.srt\n`;
if (found_subtitle_stream == 1) {
//check if language already exists
for (
sub_stream = sub;
sub_stream < file.ffProbeData.streams.length;
sub_stream++
) {
//response.infoLog += `does ${lang[i].name} exist in stream ${sub_stream}?\n`
if (file.ffProbeData.streams[sub_stream].tags.language) {
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`;
}
}
//else {
// response.infoLog += `did not find sub ${lang[i].iso6392B}.srt\n`
//}
}
}
} else {
exist = 0;
}
}
response.preset += ` ${preset_import}${preset_meta} -map 0:v -map 0:a`
//map new subs
while (added_subs < new_subs) {
added_subs++;
response.preset += ` -map ${added_subs}:s`;
//add if it hasn't found the language
if (exist != 1) {
preset_import += ` -sub_charenc "UTF-8" -f srt -i "${path}/${lang[i].iso6392B}.srt"`;
preset_meta += ` -metadata:s:s:${new_subs} language=${lang[i].iso6392B}`;
new_subs++;
}
}
//else {
// response.infoLog += `did not find sub ${lang[i].iso6392B}.srt\n`
//}
exist = 0;
}
//if new subs have been found they will be added
if (new_subs > 0) {
response.FFmpegMode = true;
response.processFile = true;
response.reQueueAfter = true;
if (found_subtitle_stream == 1) {
response.preset += ` -map 0:s `;
}
response.preset += ` -c copy`;
response.infoLog += `${new_subs} new subs will be added\n`;
} else {
response.infoLog += `No new subtitle languages were found\n`;
response.preset += ` ${preset_import}${preset_meta} -map 0:v -map 0:a`;
//map new subs
while (added_subs < new_subs) {
added_subs++;
response.preset += ` -map ${added_subs}:s`;
}
//if new subs have been found they will be added
if (new_subs > 0) {
response.FFmpegMode = true;
response.processFile = true;
response.reQueueAfter = true;
if (found_subtitle_stream == 1) {
response.preset += ` -map 0:s `;
}
response.preset += ` -c copy`;
response.infoLog += `${new_subs} new subs will be added\n`;
} else {
response.infoLog += `No new subtitle languages were found\n`;
}
//response.infoLog += `The ffmpeg string is: ${response.preset}\n`
//response.infoLog += `The ffmpeg string is: ${response.preset}\n`
return response
return response;
}
module.exports.details = details;

@ -1,137 +1,168 @@
const exec = require('child_process').exec;
const fs = require('fs');
const exec = require("child_process").exec;
const fs = require("fs");
function details() {
return {
id: "Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio",
Stage: "Pre-processing",
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",
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',
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: '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`
},
]
}
return {
id: "Tdarr_Plugin_e5c3_CnT_Keep_Preferred_Audio",
Stage: "Pre-processing",
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",
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",
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: "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`,
},
],
};
}
function plugin(file, librarySettings, inputs, otherArguments) {
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
}
if (inputs.special == "" || typeof inputs.special == 'undefined') {
var special = ``;
} else {
var special = inputs.special.toLowerCase().split(',');
}
if (languages.length >= special.length) {
var length = languages.length;
} else {
var length = special.length;
}
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 specialcheck = ``; //contains the txt string if special language was found
var wanted = 0;
var audio = 0;
//default response
var response = {
processFile: false,
preset: `, -map 0:v`,
container: '.mkv',
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: 'Removing unwanted audio...\n',
};
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
}
if (inputs.special == "" || typeof inputs.special == "undefined") {
var special = ``;
} else {
var special = inputs.special.toLowerCase().split(",");
}
if (languages.length >= special.length) {
var length = languages.length;
} else {
var length = special.length;
}
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 specialcheck = ``; //contains the txt string if special language was found
var wanted = 0;
var audio = 0;
if (inputs.container !== undefined) {
response.container = inputs.container;
console.log(`Container was set to: ` + inputs.container);
}
//default response
var response = {
processFile: false,
preset: `, -map 0:v`,
container: ".mkv",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "Removing unwanted audio...\n",
};
for (i = 0; i < file.ffProbeData.streams.length; i++) {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
//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) {
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
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`);
console.log(`added to txt: ` + sourcename);
}
}
if (inputs.container !== undefined) {
response.container = inputs.container;
console.log(`Container was set to: ` + inputs.container);
}
response.preset += ` -map 0:${i}`;
response.infoLog += `Found special ${special[l]}: ${i}\n`;
wanted++;
break;
} else if (file.ffProbeData.streams[i].tags.language == languages[l]) {
response.preset += ` -map 0:${i}`;
response.infoLog += `Found wanted ${languages[l]}: ${i}\n`;
wanted++;
break;
} else if (i == length-1) {
response.infoLog += `Found unwanted: ${file.ffProbeData.streams[i].tags.language}: ${i}\n`;
}
}
} else {
response.preset += ` -map 0:${i}`;
response.infoLog += `Added undefined: ${i}\n`;
wanted++;
for (i = 0; i < file.ffProbeData.streams.length; i++) {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
//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
) {
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
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`
);
console.log(`added to txt: ` + sourcename);
}
} else {
response.preset += ` -map 0:${i}`;
response.infoLog += `Added undefined: ${i}\n`;
wanted++;
}
}
audio++;
response.preset += ` -map 0:${i}`;
response.infoLog += `Found special ${special[l]}: ${i}\n`;
wanted++;
break;
} else if (
file.ffProbeData.streams[i].tags.language == languages[l]
) {
response.preset += ` -map 0:${i}`;
response.infoLog += `Found wanted ${languages[l]}: ${i}\n`;
wanted++;
break;
} else if (i == length - 1) {
response.infoLog += `Found unwanted: ${file.ffProbeData.streams[i].tags.language}: ${i}\n`;
}
}
} else {
response.preset += ` -map 0:${i}`;
response.infoLog += `Added undefined: ${i}\n`;
wanted++;
}
}
} else {
response.preset += ` -map 0:${i}`;
response.infoLog += `Added undefined: ${i}\n`;
wanted++;
}
if (audio > wanted && wanted > 0) {
transcode = 1;
audio++;
}
}
if (transcode == 1) {
response.infoLog += `Found unwanted audio\nIt will be removed\n`;
response.processFile = true;
response.FFmpegMode = true;
response.preset += ` -map 0:s? -c copy`;
response.reQueueAfter = true;
} else {
response.infoLog += `No unwanted audio found!\n`;
}
if (audio > wanted && wanted > 0) {
transcode = 1;
}
if (transcode == 1) {
response.infoLog += `Found unwanted audio\nIt will be removed\n`;
response.processFile = true;
response.FFmpegMode = true;
response.preset += ` -map 0:s? -c copy`;
response.reQueueAfter = true;
} else {
response.infoLog += `No unwanted audio found!\n`;
}
return response
return response;
}
module.exports.details = details;

@ -1,395 +1,451 @@
const fs = require('fs');
const execSync = require('child_process').execSync;
const fs = require("fs");
const execSync = require("child_process").execSync;
function details() {
return {
id: "Tdarr_Plugin_e5c3_CnT_Remove_Letterbox",
Stage: "Pre-processing",
Name: "Remove letterbox",
Type: "Video",
Operation:"Transcode",
Description: `Uses iiDrakeii's filter, and crops video files when letterboxing is detected.\nThis uses the FFMPEG NVENC transcoding(hw).\nIf a file is 4K it will be scaled down to 1080p.\nNow with user definable bitrates!(since 1.104 beta)\nCreated by @control#0405`,
Version: "1.3",
Link: "https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js",
Tags: '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: 'container',
tooltip: `Enter the output container of the new file.\\n Default: .mkv\\nExample:\\n.mkv`
},
]
}
return {
id: "Tdarr_Plugin_e5c3_CnT_Remove_Letterbox",
Stage: "Pre-processing",
Name: "Remove letterbox",
Type: "Video",
Operation: "Transcode",
Description: `Uses iiDrakeii's filter, and crops video files when letterboxing is detected.\nThis uses the FFMPEG NVENC transcoding(hw).\nIf a file is 4K it will be scaled down to 1080p.\nNow with user definable bitrates!(since 1.104 beta)\nCreated by @control#0405`,
Version: "1.3",
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_e5c3_CnT_Remove_Letterbox.js",
Tags: "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: "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') {
var min_bitrate = 6600;
var avg_rate = 3000;
var max_rate = 6000;
if (inputs.bitrate == "" || inputs.bitrate == "undefined") {
var min_bitrate = 6600;
var avg_rate = 3000;
var max_rate = 6000;
} else {
var min_bitrate = inputs.bitrate * 2.2;
var avg_rate = inputs.bitrate;
var max_rate = inputs.bitrate * 2;
}
//default values that will be returned
var response = {
processFile: false,
preset: "",
container: ".mkv",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "",
};
if (inputs.container !== undefined) {
response.container = inputs.container;
console.log(`Container was set to: ` + inputs.container);
}
var source = file.meta.SourceFile; //source file
var stats = fs.statSync(source);
var size = stats["size"] / 1000000000;
size = size.toFixed(2);
var decoder = decoder_string(file); //decoder, before the input
var encoder = encoder_string_full(
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),
};
var log = {
size: returns.size.log,
hevc: ``,
resolution: ``,
crop: returns.crop.log,
createcrop: returns.create_crop.log,
};
//filters
if (size_check(file, min_bitrate).size == 1) {
if (hevc(file) == 1) {
log.hevc = `☑ - Video is not HEVC \n`;
process = 1;
} else {
var min_bitrate = inputs.bitrate*2.2;
var avg_rate = inputs.bitrate;
var max_rate = inputs.bitrate*2;
}
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mkv',
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
if (inputs.container !== undefined) {
response.container = inputs.container;
console.log(`Container was set to: ` + inputs.container);
log.hevc += "☒ - File is already in HEVC \n";
}
var source = file.meta.SourceFile; //source file
var stats = fs.statSync(source);
var size = stats["size"]/1000000000;
size = size.toFixed(2);
var decoder = decoder_string(file); //decoder, before the input
var encoder = encoder_string_full(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)
}
var log = {
size: returns.size.log,
hevc: ``,
resolution: ``,
crop: returns.crop.log,
createcrop: returns.create_crop.log
}
//filters
if (size_check(file, min_bitrate).size == 1) {
if (hevc(file) == 1) {
log.hevc = `☑ - Video is not HEVC \n`;
process = 1;
} else {
log.hevc += "☒ - File is already in HEVC \n"
}
if (highres(file) == 1) {
process = 1;
log.resolution += `☑ - Resolution > 1080p.\n File will be transcoded to 1080p \n`;
} else {
log.resolution += `☒ - Resolution <= 1080p \n`;
}
if (crop_decider(file, generate_crop_values(file, otherArguments).crop_height).crop != "0") {
process = 1;
}
if (highres(file) == 1) {
process = 1;
log.resolution += `☑ - Resolution > 1080p.\n File will be transcoded to 1080p \n`;
} else {
log.resolution += `☒ - Resolution <= 1080p \n`;
}
response.infoLog += log.createcrop +
log.crop +
log.resolution +
log.size +
log.hevc;
response.preset = `${decoder}, -map 0:v:0 -map 0:a -map 0:s? ${encoder}`
//change response
if (process == 1) {
response.processFile = true;
response.infoLog += `File will be processed\n`;
} else if (file.forceProcessing === true) {
response.processFile = true;
response.infoLog += `Force processing!\n`;
} else {
response.infoLog += `Processing not necessary\n`;
if (
crop_decider(file, generate_crop_values(file, otherArguments).crop_height)
.crop != "0"
) {
process = 1;
}
return response;
}
response.infoLog +=
log.createcrop + log.crop + log.resolution + log.size + log.hevc;
response.preset = `${decoder}, -map 0:v:0 -map 0:a -map 0:s? ${encoder}`;
//change response
if (process == 1) {
response.processFile = true;
response.infoLog += `File will be processed\n`;
} else if (file.forceProcessing === true) {
response.processFile = true;
response.infoLog += `Force processing!\n`;
} else {
response.infoLog += `Processing not necessary\n`;
}
return response;
}
function highres(file) {
//if file is larger than 1080p it should be transcoded
if (file.meta.ImageWidth > 1920) {
return 1;
} else {
return 0;
}
//if file is larger than 1080p it should be transcoded
if (file.meta.ImageWidth > 1920) {
return 1;
} else {
return 0;
}
}
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 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: ``
}
//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}\"`);
} else {
returns.log += `Crop values already exist\n`;
}
//get data from copvalue.txt
var data = fs.readFileSync(`${cropfile}`).toString().split("\n"); //full data from cropvalue.txt
//get height of the supposed cropped video
//var crop_height = parseInt(data[0].substring(10, 14));
for (var c = 0; c < data.length; c++) {
crop = data[c].split(":");
crop_height = Math.abs(parseInt(crop[1]));
if (crop_height > returns.crop_height) {
returns.crop_height = crop_height;
returns.log += `New cropheight: ${crop_height}\n`;
}
var source = file.meta.SourceFile; //source file
var dir = file.meta.Directory; //source directory
var sourcename = file.meta.FileName.substring(
0,
file.meta.FileName.lastIndexOf(".")
); //filename without extension
var cropfile = `${dir}/${sourcename}.txt`; //location and name of the crop file
var returns = {
crop_height: 0, //return value for this function, required for crop_decider
log: ``,
};
//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}\"`
);
} else {
returns.log += `Crop values already exist\n`;
}
//get data from copvalue.txt
var data = fs.readFileSync(`${cropfile}`).toString().split("\n"); //full data from cropvalue.txt
//get height of the supposed cropped video
//var crop_height = parseInt(data[0].substring(10, 14));
for (var c = 0; c < data.length; c++) {
crop = data[c].split(":");
crop_height = Math.abs(parseInt(crop[1]));
if (crop_height > returns.crop_height) {
returns.crop_height = crop_height;
returns.log += `New cropheight: ${crop_height}\n`;
}
return returns;
}
return returns;
}
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())) {
return 0;
} else {
return 1;
}
//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())
) {
return 0;
} else {
return 1;
}
}
}
function decoder_string(file) {
var decoder = ``; //decoder, before the input
//use the correct decoder
if (file.video_codec_name == 'h263') {
decoder = `-c:v h263_cuvid`
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 == '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;
} else if (file.video_codec_name == "mjpeg") {
decoder = `c:v mjpeg_cuvid`;
} else if (file.video_codec_name == "mpeg1") {
decoder = `-c:v mpeg1_cuvid`;
} else if (file.video_codec_name == "mpeg2") {
decoder = `-c:v mpeg2_cuvid`;
} else if (file.video_codec_name == "vc1") {
decoder = `-c:v vc1_cuvid`;
} else if (file.video_codec_name == "vp8") {
decoder = `-c:v vp8_cuvid`;
} else if (file.video_codec_name == "vp9") {
decoder = `-c:v vp9_cuvid`;
}
return decoder;
}
function crop_decider(file, crop_height) {
var returns = {
crop: `0`, //sets the crop filter
log: ``,
var returns = {
crop: `0`, //sets the crop filter
log: ``,
};
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
if (file.ffProbeData.streams[i].width !== undefined) {
var imageWidth = file.ffProbeData.streams[i].width;
var imageHeight = file.ffProbeData.streams[i].height;
break;
}
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
if (file.ffProbeData.streams[i].width !== undefined) {
var imageWidth = file.ffProbeData.streams[i].width;
var imageHeight = file.ffProbeData.streams[i].height;
break;
}
}
var min_crop = parseInt(imageHeight * 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)
//crop only if it is a larger crop than 1%;
if (crop_height < min_crop) {
var crop_hdis = parseInt((imageHeight - crop_height) / 2);
if (crop_height >= 790) {
returns.crop = `-filter:0 crop=${imageWidth}:${crop_height}:0:${crop_hdis}`;
returns.log += `☑ - crop is larger than 1%\n`;
}
} else {
returns.log += `☒ - Crop is not necessary\n`;
}
var min_crop = parseInt(imageHeight*.98); //if the crop value is larger than this the file won't be cropped
//tree for resolution : quality
if (imageWidth >= 1300) { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled)
//crop only if it is a larger crop than 1%;
if (crop_height < min_crop) {
var crop_hdis = parseInt((imageHeight-crop_height)/2);
if (crop_height >= 790) {
returns.crop = `-filter:0 crop=${imageWidth}:${crop_height}:0:${crop_hdis}`;
returns.log += `☑ - crop is larger than 1%\n`;
}
} else {
returns.log += `☒ - Crop is not necessary\n`;
}
} else if(imageWidth < 1300 && file.meta.ImageWidth >= 770) {
//crop only if it is a larger crop than 1%;
if (crop_height < min_crop) {
var crop_hdis = parseInt((imageHeight-crop_height)/2);
if (crop_height >= 530) {
returns.crop = `-filter:0 crop=${imageWidth}:${crop_height}:0:${crop_hdis}`;
returns.log += `☑ - crop is larger than 1%\n`;
}
} else {
returns.log += `☒ - Crop is not necessary\n`;
}
} else if(imageWidth < 770) { //file won't be cropped at this resolution
returns.log += `No crop: Resolution < 720p\n`;
} else if (imageWidth < 1300 && file.meta.ImageWidth >= 770) {
//crop only if it is a larger crop than 1%;
if (crop_height < min_crop) {
var crop_hdis = parseInt((imageHeight - crop_height) / 2);
if (crop_height >= 530) {
returns.crop = `-filter:0 crop=${imageWidth}:${crop_height}:0:${crop_hdis}`;
returns.log += `☑ - crop is larger than 1%\n`;
}
} else {
returns.log += `☒ - Crop is not necessary\n`;
}
} else if (imageWidth < 770) {
//file won't be cropped at this resolution
returns.log += `No crop: Resolution < 720p\n`;
}
return returns;
return returns;
}
function size_check(file, min_bitrate) {
var duration = file.meta.Duration; //duration of video in seconds
var source = file.meta.SourceFile; //source file
var stats = fs.statSync(source);
var size = stats["size"]/1000000000;
size = size.toFixed(2);
var returns = {
size: 0,
log: ``
}
//tree for resolution : quality
if (file.video_resolution === "1080p" || file.video_resolution === "4KUHD") { //file will be encoded if the resolution is 1080p, or greater (it will be downscaled)
var min_transcode_size = (min_bitrate * duration * 0.125)/1000000; //minimum size in GB for transcode
min_transcode_size = min_transcode_size.toFixed(2);
//check if file is large enough for transcode
if (size >= (min_bitrate * duration * 0.125)/1000000) {
returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`;
returns.size = 1;
} else {
returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`;
}
} else if(file.video_resolution === "720p") { //file will be encoded if the resolution is 720p
var min_transcode_size = ((min_bitrate/2) * duration * 0.125)/1000000; //minimum size in GB for transcode
min_transcode_size = min_transcode_size.toFixed(2);
//check if file is large enough for transcode
if (size >= ((min_bitrate/2) * duration * 0.125)/1000000) {
returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`;
returns.size = 1;
} else {
returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`;
}
} else if(file.video_resolution === "480p" || file.video_resolution === "576p") { //file will be encoded if the resolution is 480p or 576p
var min_transcode_size = ((min_bitrate/4) * duration * 0.125)/1000000; //minimum size in GB for transcode
min_transcode_size = min_transcode_size.toFixed(2);
//check if file is large enough for transcode
if (size >= ((min_bitrate/4) * duration * 0.125)/1000000) {
returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`;
returns.size = 1;
} else {
returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`;
}
var duration = file.meta.Duration; //duration of video in seconds
var source = file.meta.SourceFile; //source file
var stats = fs.statSync(source);
var size = stats["size"] / 1000000000;
size = size.toFixed(2);
var returns = {
size: 0,
log: ``,
};
//tree for resolution : quality
if (file.video_resolution === "1080p" || file.video_resolution === "4KUHD") {
//file will be encoded if the resolution is 1080p, or greater (it will be downscaled)
var min_transcode_size = (min_bitrate * duration * 0.125) / 1000000; //minimum size in GB for transcode
min_transcode_size = min_transcode_size.toFixed(2);
//check if file is large enough for transcode
if (size >= (min_bitrate * duration * 0.125) / 1000000) {
returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`;
returns.size = 1;
} else {
returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`;
}
} else if (file.video_resolution === "720p") {
//file will be encoded if the resolution is 720p
var min_transcode_size = ((min_bitrate / 2) * duration * 0.125) / 1000000; //minimum size in GB for transcode
min_transcode_size = min_transcode_size.toFixed(2);
//check if file is large enough for transcode
if (size >= ((min_bitrate / 2) * duration * 0.125) / 1000000) {
returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`;
returns.size = 1;
} else {
returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`;
}
} else if (
file.video_resolution === "480p" ||
file.video_resolution === "576p"
) {
//file will be encoded if the resolution is 480p or 576p
var min_transcode_size = ((min_bitrate / 4) * duration * 0.125) / 1000000; //minimum size in GB for transcode
min_transcode_size = min_transcode_size.toFixed(2);
//check if file is large enough for transcode
if (size >= ((min_bitrate / 4) * duration * 0.125) / 1000000) {
returns.log += `☑ - ${size}GB > ${min_transcode_size}GB\n`;
returns.size = 1;
} else {
returns.log += `☒ - ${size}GB < ${min_transcode_size}GB\n`;
}
}
return returns;
return returns;
}
function error_fix(file, container) {
var fix = {
sub_codec: 0, //changes to 1 if unwanted codec is found
muxing: 0
}
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
//these subtitle codecs don't fit in a mkv container
if (file.ffProbeData.streams[i].codec_name && 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" ) {
fix.muxing = 1;
}
}
var fix = {
sub_codec: 0, //changes to 1 if unwanted codec is found
muxing: 0,
};
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
//these subtitle codecs don't fit in a mkv container
if (
file.ffProbeData.streams[i].codec_name &&
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")
) {
fix.muxing = 1;
}
}
}
return fix;
return fix;
}
function encoder_string(file, avg_rate, max_rate, container) {
var encoder = ``; //encoder
var fix = error_fix(file, 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)
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
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`;
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")) {
sub += ` -c:${i} ass`;
} else {
if (file.ffProbeData.streams[i].codec_type) {
if (file.ffProbeData.streams[i].codec_type.toLowerCase().includes("sub")) {
sub += ` -c:${i} copy`;
}
}
}
var encoder = ``; //encoder
var fix = error_fix(file, 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)
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
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`;
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"))
) {
sub += ` -c:${i} ass`;
} else {
if (file.ffProbeData.streams[i].codec_type) {
if (
file.ffProbeData.streams[i].codec_type
.toLowerCase()
.includes("sub")
) {
sub += ` -c:${i} copy`;
}
}
}
} else {
sub = ` -c:s copy`
}
}
if (fix.muxing == 1) {
encoder += ` -max_muxing_queue_size 2048`;
}
return encoder + ` -c:a copy` + sub;
} else {
sub = ` -c:s copy`;
}
if (fix.muxing == 1) {
encoder += ` -max_muxing_queue_size 2048`;
}
return encoder + ` -c:a copy` + sub;
}
function encoder_string_full(highres, crop, encoder) {
console.log(`crop filter: ` + crop);
if (highres == 1 && crop != "0") {
return crop + `,scale=-1:1920 ` + encoder;
} else if (highres == 1) {
return `-filter:0 scale=-1:1920 ` + encoder;
} else if (crop != "0") {
return crop + encoder;
} else {
return encoder;
}
console.log(`crop filter: ` + crop);
if (highres == 1 && crop != "0") {
return crop + `,scale=-1:1920 ` + encoder;
} else if (highres == 1) {
return `-filter:0 scale=-1:1920 ` + encoder;
} else if (crop != "0") {
return crop + encoder;
} else {
return encoder;
}
}
function execCommand(cmd) {
const exec = require('child_process').exec;
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {
console.warn(error);
}
resolve(stdout? stdout : stderr);
});
const exec = require("child_process").exec;
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {
console.warn(error);
}
resolve(stdout ? stdout : stderr);
});
});
}
module.exports.details = details;

@ -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) { }
} 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) { }
} catch (err) {}
//check if commentary AC3 track
//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) { }
} catch (err) {}
//check if AC3 track
try {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() == "ac3") {
ac3TrackCount++
ac3TrackCount++;
}
} catch (err) { }
} catch (err) {}
//check if subs track
//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) { }
} 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",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
processFile : false,
preset : '',
container : '.mp4',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
response.FFmpegMode = true
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
} else {
return response;
} else {
var hasPreferredLangTrack = false;
var hasPreferredLangInRequiredCodecs = false;
var hasAnyInRequiredCodecs = false;
var hasPreferredLangTrack = false
var hasPreferredLangInRequiredCodecs = false
var hasAnyInRequiredCodecs = false
var audioIdx = -1;
var engTrackIdx = -1;
var audioIdx = -1
var engTrackIdx = -1
var requiredAudioCodecs = "aac";
var preferredLangTrack = "eng";
var preferredCodec = "aac";
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
}
} catch (err) { }
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
try {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++
audioIdx++;
}
} catch (err) { }
} 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) { }
} 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) { }
} 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`
} catch (err) {}
}
if (hasPreferredLangInRequiredCodecs) {
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'
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.reQueueAfter = true;
response.processFile = true;
return response
}
///
if(file.meta.Title != undefined ){
return response;
}
response.infoLog += "☒File has title metadata \n"
response.preset = ',-map_metadata -1 -c:v copy -c:a copy'
///
if (file.meta.Title != undefined) {
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
}else{
response.infoLog += "☑File has no title metadata \n"
}
if(hasSubs){
return response;
} else {
response.infoLog += "☑File has no title metadata \n";
}
response.infoLog += "☒File has subs \n"
response.preset = ',-sn -c:v copy -c:a copy'
if (hasSubs) {
response.infoLog += "☒File has subs \n";
response.preset = ",-sn -c:v copy -c:a copy";
response.reQueueAfter = true;
response.processFile = true;
return response
}else{
response.infoLog += "☑File has no subs \n"
}
return response;
} else {
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
}else{
response.infoLog += "☑File is in mp4 container! \n"
}
response.infoLog += "☑File meets conditions! \n"
return response
return response;
} else {
response.infoLog += "☑File is in mp4 container! \n";
}
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',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
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,66 +7,53 @@ 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)
// 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;
}
}
module.exports.details = details;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -4,63 +4,64 @@ function details() {
Stage: "Pre-processing",
Name: "FFMPEG HQ 10-bit HEVC MKV for Animation",
Type: "Video",
Operation:"Transcode",
Operation: "Transcode",
Description: `[Contains built-in filter] High Quality FFMPEG transcoding settings for Animation. Converts all audio to AAC 512K. Preserves track names, metadata and attachments/fonts. Proper use of x265-params. CRF 18. Preset medium. 10-Bit Video encoding. Skips h.265 encoded videos. The output container is mkv. \n\n`,
Version: "1.1",
Link: "",
Tags:"pre-processing,ffmpeg,h265,aac,10bit,anime,"
}
Tags: "pre-processing,ffmpeg,h265,aac,10bit,anime,",
};
}
function plugin(file) {
var transcode = 0; //if this var changes to 1 the file will be transcoded
//default values that will be returned
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mkv',
preset: "",
container: ".mkv",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
//check if the file is a video, if not the function will be stopped immediately
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
//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;
}
//Transcoding options
//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;
}
//check if the file is eligible for transcoding
//if true the neccessary response values will be changed
//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 += `☒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;
module.exports.plugin = plugin;

@ -4,168 +4,171 @@ function details() {
Stage: "Pre-processing",
Name: "FFmpeg Tiered HEVC MKV",
Type: "Video",
Operation:"Transcode",
Operation: "Transcode",
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) {
var transcode = 0; //if this var changes to 1 the file will be transcoded
//default values that will be returned
//default values that will be returned
var response = {
processFile: false,
preset: '',
container: '.mkv',
preset: "",
container: ".mkv",
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: ''
}
//check if the file is a video, if not the function will be stopped immediately
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
//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;
}
//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'
}
//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";
}
transcode = 1;
}
//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'
}
//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";
}
transcode = 1;
}
//file will be encoded if the resolution is 1080p
//codec will be checked so it can be transcoded correctly
if(file.video_resolution === "1080p") {
if (file.video_codec_name == 'h263') {
response.preset = ',-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'
}
//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";
}
transcode = 1;
}
//check if the file is eligible for transcoding
//if true the neccessary response values will be changed
//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 += `☒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;
module.exports.plugin = plugin;
module.exports.plugin = plugin;

@ -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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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) { }
} 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
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) {
}
} 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) { }
} 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) { }
} 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',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
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
} else {
response.FFmpegMode = true
response.container = '.' + file.container
var hasSubs = false
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if(file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"){
hasSubs = true
}
} catch (err) { }
}
if(hasSubs){
response.infoLog += "☒File has subs \n"
response.preset = ',-sn -map 0 -c copy'
return response;
} else {
response.FFmpegMode = true;
response.container = "." + file.container;
var hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle"
) {
hasSubs = true;
}
} catch (err) {}
}
if (hasSubs) {
response.infoLog += "☒File has subs \n";
response.preset = ",-sn -map 0 -c copy";
response.reQueueAfter = true;
response.processFile = true;
return response
}else{
response.infoLog += "☑File has no subs \n"
}
response.infoLog += "☑File meets conditions! \n"
return response
return response;
} else {
response.infoLog += "☑File has no subs \n";
}
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",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: true,
infoLog: "",
};
processFile : false,
preset : '',
container : '.mp4',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : true,
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
} else {
if(file.hasClosedCaptions === true){
response = {
processFile : true,
preset : ',-map 0 -codec copy -bsf:v "filter_units=remove_types=6"',
container : '.' + file.container ,
handBrakeMode : false,
FFmpegMode : true,
reQueueAfter : true,
infoLog : '☒This file has closed captions \n',
}
return response
}else{
response.infoLog += "☑Closed captions have not been detected on this file \n"
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,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "☒This file has closed captions \n",
};
return response;
} else {
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',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
if (file.fileMedium !== "video"){
console.log("File is not video")
response.infoLog += "☒File is not video \n"
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
return response;
} else {
var jsonString = JSON.stringify(file)
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
}
} 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'
var jsonString = JSON.stringify(file);
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;
}
} catch (err) {}
}
if (file.ffProbeData.streams[0].codec_name != "h264") {
response.infoLog += "☒File is not in h264! \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset medium -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File is already in h264! \n"
}
///
if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has title metadata and no aac and subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(!jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has no aac track and has subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(file.meta.Title != undefined && hasSubs){
response.infoLog += "☒File has title and has subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
///
if(file.meta.Title != undefined ){
response.infoLog += "☒File has title metadata \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no title metadata \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.FFmpegMode = true;
return response;
} else {
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.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
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.FFmpegMode = true;
return response;
} else {
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.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no/compatible subs \n"
}
response.infoLog += "☑File meets conditions! \n"
return response
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -1,72 +1,69 @@
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_z18s_rename_files_based_on_codec",
Stage: "Post-processing",
Stage: "Post-processing",
Name: "Rename based on codec",
Type: "Video",
Operation: "",
Description: `[TESTING][Contains built-in filter]This plugin renames 264 files to 265 or vice versa depending on codec. \n\n`,
Version: "1.00",
Link: "",
Tags:"post-processing",
}
}
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/')
} else{
var rootModules = ''
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 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',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
if (file.fileMedium !== "video"){
console.log("File is not video")
response.infoLog += "☒File is not video \n"
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
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 {
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) { }
}
} 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
}else{
response.infoLog += "☑File is already in h264! \n"
}
///
if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has title metadata and no aac and subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(!jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has no aac track and has subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(file.meta.Title != undefined && hasSubs){
response.infoLog += "☒File has title and has subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
///
if(file.meta.Title != undefined ){
response.infoLog += "☒File has title metadata \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no title metadata \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.FFmpegMode = true;
return response;
} else {
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.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
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.FFmpegMode = true;
return response;
} else {
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.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no/compatible subs \n"
}
response.infoLog += "☑File meets conditions! \n"
return response
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
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',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
if (file.fileMedium !== "video"){
console.log("File is not video")
response.infoLog += "☒File is not video \n"
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
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 {
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'){
} catch (err) {}
}
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
}else{
response.infoLog += "☑File is already in h264! \n"
}
///
if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has title metadata and no aac and subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(!jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has no aac track and has subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(file.meta.Title != undefined && hasSubs){
response.infoLog += "☒File has title and has subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
///
if(file.meta.Title != undefined ){
response.infoLog += "☒File has title metadata \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no title metadata \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.FFmpegMode = true;
return response;
} else {
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.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
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.FFmpegMode = true;
return response;
} else {
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.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no/compatible subs \n"
}
response.infoLog += "☑File meets conditions! \n"
return response
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
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',
handBrakeMode : false,
FFmpegMode : false,
reQueueAfter : false,
infoLog : '',
}
if (file.fileMedium !== "video"){
console.log("File is not video")
response.infoLog += "☒File is not video \n"
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response
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 {
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'){
} catch (err) {}
}
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
}else{
response.infoLog += "☑File is already in h264! \n"
}
///
if((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has title metadata and no aac and subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(!jsonString.includes("aac") && hasSubs){
response.infoLog += "☒File has no aac track and has subs \n"
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
if(file.meta.Title != undefined && hasSubs){
response.infoLog += "☒File has title and has subs \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}
///
if(file.meta.Title != undefined ){
response.infoLog += "☒File has title metadata \n"
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text'
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no title metadata \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.FFmpegMode = true;
return response;
} else {
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.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
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.FFmpegMode = true;
return response;
} else {
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.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true
return response
}else{
response.infoLog += "☑File has no/compatible subs \n"
}
response.infoLog += "☑File meets conditions! \n"
return response
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n";
return response;
}
}

@ -14,11 +14,11 @@ https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Tdarr_Plugin_aaaa_Pre_P
https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Tdarr_Plugin_zzzz_Post_Proc_Example.js
2.Determine an id for your plugin. Every id must start with 'Tdarr_Plugin_xxxx' where xxxx is a random mini id containing the following:
Numeric digits (0-9)
Uppercase letters (A-Z)
Lowercase letters (a-z)
Numeric digits (0-9)
Uppercase letters (A-Z)
Lowercase letters (a-z)
The rest of the plugin id can be whatever you like. See the plugins folder for examples:
https://github.com/HaveAGitGat/Tdarr_Plugins/tree/master/Community
@ -29,7 +29,7 @@ Your plugin id inside the file must be exactly the same as the plugin filename.
IMPORTANT: Think carefully about what you'd like your plugin to do. You cannot change the aim of a community plugin at a later date as others may be using the plugin. After the plugin has been submitted to community plugins, you can only fix bugs, clarify details and improve plugin performance.
4.(If local plugin then you can skip this)
For the plugin link, I'll add this once you create a PR to community plugins.
For the plugin link, I'll add this once you create a PR to community plugins.
5. Configure 'function plugin(file)' with logic on whether to transcode the file or not. 'file' is an object with hundreds of file properties extracted using FFprobe and ExifTool. The following response object MUST be returned by your plugin. The values shown are the default values:
@ -37,7 +37,7 @@ For the plugin link, I'll add this once you create a PR to community plugins.
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 aguments you'd like to use.
preset: '', //HandBrake/FFmpeg CLI aguments you'd like to use.
//For FFmpeg, the input arguments come first followed by a comma, followed by the output argument.
// Examples
//HandBrake
@ -50,28 +50,25 @@ For the plugin link, I'll add this once you create a PR to community plugins.
reQueueAfter: false, //If you can't do all tasks in one pass, set this to true. The file will be re-added to the transcode queue
//afterwards for additional processing. See Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle
//In that plugin, several passes are used to remove subs, metadata and add an aac track.
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!')
}
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:
Create a pull request to have your plugin added to:
https://github.com/HaveAGitGat/Tdarr_Plugins/tree/master/Community
For local 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:
Create a pull request to have your plugin added to:
https://github.com/HaveAGitGat/Tdarr_Plugins/tree/master/Community
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 = {
var file = {
_id: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
DB: 'ZRPDmnmpyuAEQi7nG',
HealthCheck: 'Not attempted',
@ -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.
@ -12,12 +8,13 @@ module.exports.details = function details() {
Description: `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_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
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
{
name: 'language',
tooltip: `Enter one language tag here for the language of the subtitles you'd like to keep.
Inputs: [
//(Optional) Inputs you'd like the user to enter to allow your plugin to be easily configurable from the UI
{
name: "language",
tooltip: `Enter one language tag here for the language of the subtitles you'd like to keep.
\\nExample:\\n
eng
@ -28,357 +25,345 @@ module.exports.details = function details() {
\\nExample:\\n
de` //Each line following `Example:` will be clearly formatted. \\n used for line breaks
},
{
name: 'channels',
tooltip: `Desired audio channel number.
de`, //Each line following `Example:` will be clearly formatted. \\n used for line breaks
},
{
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!')
//Optional (include together)
file,
removeFromDB: false, //Tell Tdarr to remove file from database if true
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
} else {
response.infoLog += " File has no title metadata"
}
response.infoLog += " File meets conditions!"
return response
}
module.exports.onTranscodeSuccess = function onTranscodeSuccess(file, librarySettings, inputs) {
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;
} else {
response.infoLog += " File has no title metadata";
}
console.log('Transcode success! Now do some stuff with the newly scanned file.')
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."
);
//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:
// {
// _id: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// DB: 'ZRPDmnmpyuAEQi7nG',
// HealthCheck: 'Not attempted',
// TranscodeDecisionMaker: 'Not attempted',
// bit_rate: 1690430.4,
// container: 'mp4',
// createdAt: 2019-09-26T06:46:31.929Z,
// ffProbeData:
// { streams:
// [ { index: 0,
// codec_name: 'h264',
// codec_long_name: 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10',
// profile: 'Main',
// codec_type: 'video',
// codec_time_base: '1/50',
// codec_tag_string: 'avc1',
// codec_tag: '0x31637661',
// width: 1280,
// height: 720,
// coded_width: 1280,
// coded_height: 720,
// has_b_frames: 0,
// sample_aspect_ratio: '1:1',
// display_aspect_ratio: '16:9',
// pix_fmt: 'yuv420p',
// level: 31,
// chroma_location: 'left',
// refs: 1,
// is_avc: 'true',
// nal_length_size: '4',
// r_frame_rate: '25/1',
// avg_frame_rate: '25/1',
// time_base: '1/12800',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 67584,
// duration: '5.280000',
// bit_rate: '1205959',
// bits_per_raw_sample: '8',
// nb_frames: '132',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'VideoHandler' } },
// { index: 1,
// codec_name: 'aac',
// codec_long_name: 'AAC (Advanced Audio Coding)',
// profile: 'LC',
// codec_type: 'audio',
// codec_time_base: '1/48000',
// codec_tag_string: 'mp4a',
// codec_tag: '0x6134706d',
// sample_fmt: 'fltp',
// sample_rate: '48000',
// channels: 6,
// channel_layout: '5.1',
// bits_per_sample: 0,
// r_frame_rate: '0/0',
// avg_frame_rate: '0/0',
// time_base: '1/48000',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 254976,
// duration: '5.312000',
// bit_rate: '384828',
// max_bit_rate: '400392',
// nb_frames: '249',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'SoundHandler' } } ] },
// ffProbeRead: 'success',
// file: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// fileMedium: 'video',
// file_size: 1.056519,
// meta:
// { SourceFile: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// errors: [],
// Duration: 5.312,
// PreviewDuration: 0,
// SelectionDuration: 0,
// TrackDuration: 5.28,
// MediaDuration: 5.312,
// ExifToolVersion: 11.65,
// FileName: 'Sample.mp4',
// Directory: 'C:/Users/H/Desktop/Test Input1',
// FileSize: '1032 kB',
// FileModifyDate:
// { year: 2019,
// month: 9,
// day: 24,
// hour: 7,
// minute: 24,
// second: 22,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:24 07:24:22+01:00' },
// FileAccessDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FileCreateDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FilePermissions: 'rw-rw-rw-',
// FileType: 'MP4',
// FileTypeExtension: 'mp4',
// MIMEType: 'video/mp4',
// MajorBrand: 'MP4 Base Media v1 [IS0 14496-12:2003]',
// MinorVersion: '0.2.0',
// CompatibleBrands: [ 'isom', 'iso2', 'avc1', 'mp41' ],
// MovieDataSize: 0,
// MovieDataOffset: 1051515,
// MovieHeaderVersion: 0,
// CreateDate:
// { year: 1970,
// month: 1,
// day: 8,
// hour: 0,
// minute: 0,
// second: 0,
// millisecond: 0,
// rawValue: '1970:01:08 00:00:00' },
// ModifyDate:
// { year: 2014,
// month: 7,
// day: 19,
// hour: 17,
// minute: 15,
// second: 29,
// millisecond: 0,
// rawValue: '2014:07:19 17:15:29' },
// TimeScale: 1000,
// PreferredRate: 1,
// PreferredVolume: '100.00%',
// PreviewTime: '0 s',
// PosterTime: '0 s',
// SelectionTime: '0 s',
// CurrentTime: '0 s',
// NextTrackID: 3,
// TrackHeaderVersion: 0,
// TrackCreateDate: '0000:00:00 00:00:00',
// TrackModifyDate: '0000:00:00 00:00:00',
// TrackID: 1,
// TrackLayer: 0,
// TrackVolume: '0.00%',
// ImageWidth: 1280,
// ImageHeight: 720,
// GraphicsMode: 'srcCopy',
// OpColor: '0 0 0',
// CompressorID: 'avc1',
// SourceImageWidth: 1280,
// SourceImageHeight: 720,
// XResolution: 72,
// YResolution: 72,
// BitDepth: 24,
// VideoFrameRate: 25,
// MatrixStructure: '1 0 0 0 1 0 0 0 1',
// MediaHeaderVersion: 0,
// MediaCreateDate: '0000:00:00 00:00:00',
// MediaModifyDate: '0000:00:00 00:00:00',
// MediaTimeScale: 48000,
// MediaLanguageCode: 'und',
// HandlerDescription: 'SoundHandler',
// Balance: 0,
// AudioFormat: 'mp4a',
// AudioChannels: 2,
// AudioBitsPerSample: 16,
// AudioSampleRate: 48000,
// HandlerType: 'Metadata',
// HandlerVendorID: 'Apple',
// Encoder: 'Lavf53.24.2',
// Title: 'Sample title test',
// Composer: 'th',
// BeatsPerMinute: '',
// ContentCreateDate: 2018,
// Genre: 'this',
// Artist: 'hhj',
// Comment: 'hhk',
// Subtitle: 'jj',
// Mood: 'lik',
// ContentDistributor: 'cont',
// Conductor: 'jo',
// Writer: 'writ',
// InitialKey: 'ho',
// Producer: 'prod',
// ParentalRating: 'par',
// Director: 'dir',
// Period: 'pol',
// Publisher: 'pub',
// PromotionURL: 'prom',
// AuthorURL: 'auth',
// EncodedBy: 'enc',
// Category: 'h',
// ImageSize: '1280x720',
// Megapixels: 0.922,
// AvgBitrate: '1.58 Mbps',
// Rotation: 0 },
// processingStatus: false,
// video_codec_name: 'h264',
// video_resolution: '720p' }
// {
// _id: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// DB: 'ZRPDmnmpyuAEQi7nG',
// HealthCheck: 'Not attempted',
// TranscodeDecisionMaker: 'Not attempted',
// bit_rate: 1690430.4,
// container: 'mp4',
// createdAt: 2019-09-26T06:46:31.929Z,
// ffProbeData:
// { streams:
// [ { index: 0,
// codec_name: 'h264',
// codec_long_name: 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10',
// profile: 'Main',
// codec_type: 'video',
// codec_time_base: '1/50',
// codec_tag_string: 'avc1',
// codec_tag: '0x31637661',
// width: 1280,
// height: 720,
// coded_width: 1280,
// coded_height: 720,
// has_b_frames: 0,
// sample_aspect_ratio: '1:1',
// display_aspect_ratio: '16:9',
// pix_fmt: 'yuv420p',
// level: 31,
// chroma_location: 'left',
// refs: 1,
// is_avc: 'true',
// nal_length_size: '4',
// r_frame_rate: '25/1',
// avg_frame_rate: '25/1',
// time_base: '1/12800',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 67584,
// duration: '5.280000',
// bit_rate: '1205959',
// bits_per_raw_sample: '8',
// nb_frames: '132',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'VideoHandler' } },
// { index: 1,
// codec_name: 'aac',
// codec_long_name: 'AAC (Advanced Audio Coding)',
// profile: 'LC',
// codec_type: 'audio',
// codec_time_base: '1/48000',
// codec_tag_string: 'mp4a',
// codec_tag: '0x6134706d',
// sample_fmt: 'fltp',
// sample_rate: '48000',
// channels: 6,
// channel_layout: '5.1',
// bits_per_sample: 0,
// r_frame_rate: '0/0',
// avg_frame_rate: '0/0',
// time_base: '1/48000',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 254976,
// duration: '5.312000',
// bit_rate: '384828',
// max_bit_rate: '400392',
// nb_frames: '249',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'SoundHandler' } } ] },
// ffProbeRead: 'success',
// file: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// fileMedium: 'video',
// file_size: 1.056519,
// meta:
// { SourceFile: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// errors: [],
// Duration: 5.312,
// PreviewDuration: 0,
// SelectionDuration: 0,
// TrackDuration: 5.28,
// MediaDuration: 5.312,
// ExifToolVersion: 11.65,
// FileName: 'Sample.mp4',
// Directory: 'C:/Users/H/Desktop/Test Input1',
// FileSize: '1032 kB',
// FileModifyDate:
// { year: 2019,
// month: 9,
// day: 24,
// hour: 7,
// minute: 24,
// second: 22,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:24 07:24:22+01:00' },
// FileAccessDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FileCreateDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FilePermissions: 'rw-rw-rw-',
// FileType: 'MP4',
// FileTypeExtension: 'mp4',
// MIMEType: 'video/mp4',
// MajorBrand: 'MP4 Base Media v1 [IS0 14496-12:2003]',
// MinorVersion: '0.2.0',
// CompatibleBrands: [ 'isom', 'iso2', 'avc1', 'mp41' ],
// MovieDataSize: 0,
// MovieDataOffset: 1051515,
// MovieHeaderVersion: 0,
// CreateDate:
// { year: 1970,
// month: 1,
// day: 8,
// hour: 0,
// minute: 0,
// second: 0,
// millisecond: 0,
// rawValue: '1970:01:08 00:00:00' },
// ModifyDate:
// { year: 2014,
// month: 7,
// day: 19,
// hour: 17,
// minute: 15,
// second: 29,
// millisecond: 0,
// rawValue: '2014:07:19 17:15:29' },
// TimeScale: 1000,
// PreferredRate: 1,
// PreferredVolume: '100.00%',
// PreviewTime: '0 s',
// PosterTime: '0 s',
// SelectionTime: '0 s',
// CurrentTime: '0 s',
// NextTrackID: 3,
// TrackHeaderVersion: 0,
// TrackCreateDate: '0000:00:00 00:00:00',
// TrackModifyDate: '0000:00:00 00:00:00',
// TrackID: 1,
// TrackLayer: 0,
// TrackVolume: '0.00%',
// ImageWidth: 1280,
// ImageHeight: 720,
// GraphicsMode: 'srcCopy',
// OpColor: '0 0 0',
// CompressorID: 'avc1',
// SourceImageWidth: 1280,
// SourceImageHeight: 720,
// XResolution: 72,
// YResolution: 72,
// BitDepth: 24,
// VideoFrameRate: 25,
// MatrixStructure: '1 0 0 0 1 0 0 0 1',
// MediaHeaderVersion: 0,
// MediaCreateDate: '0000:00:00 00:00:00',
// MediaModifyDate: '0000:00:00 00:00:00',
// MediaTimeScale: 48000,
// MediaLanguageCode: 'und',
// HandlerDescription: 'SoundHandler',
// Balance: 0,
// AudioFormat: 'mp4a',
// AudioChannels: 2,
// AudioBitsPerSample: 16,
// AudioSampleRate: 48000,
// HandlerType: 'Metadata',
// HandlerVendorID: 'Apple',
// Encoder: 'Lavf53.24.2',
// Title: 'Sample title test',
// Composer: 'th',
// BeatsPerMinute: '',
// ContentCreateDate: 2018,
// Genre: 'this',
// Artist: 'hhj',
// Comment: 'hhk',
// Subtitle: 'jj',
// Mood: 'lik',
// ContentDistributor: 'cont',
// Conductor: 'jo',
// Writer: 'writ',
// InitialKey: 'ho',
// Producer: 'prod',
// ParentalRating: 'par',
// Director: 'dir',
// Period: 'pol',
// Publisher: 'pub',
// PromotionURL: 'prom',
// AuthorURL: 'auth',
// EncodedBy: 'enc',
// Category: 'h',
// ImageSize: '1280x720',
// Megapixels: 0.922,
// AvgBitrate: '1.58 Mbps',
// Rotation: 0 },
// processingStatus: false,
// video_codec_name: 'h264',
// video_resolution: '720p' }

@ -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
@ -12,12 +8,13 @@ module.exports.details = function details() {
Description: `This plugin does some stuff after all plugins have been executed. \n\n`,
Version: "1.00",
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
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
{
name: 'language',
tooltip: `Enter one language tag here for the language of the subtitles you'd like to keep.
Inputs: [
//(Optional) Inputs you'd like the user to enter to allow your plugin to be easily configurable from the UI
{
name: "language",
tooltip: `Enter one language tag here for the language of the subtitles you'd like to keep.
\\nExample:\\n
eng
@ -26,277 +23,273 @@ module.exports.details = function details() {
fr
\\nExample:\\n
de` //Each line following `Example:` will be clearly formatted. \\n used for line breaks
},
{
name: 'channels',
tooltip: `Desired audio channel number.
de`, //Each line following `Example:` will be clearly formatted. \\n used for line breaks
},
{
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:
// {
// _id: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// DB: 'ZRPDmnmpyuAEQi7nG',
// HealthCheck: 'Not attempted',
// TranscodeDecisionMaker: 'Not attempted',
// bit_rate: 1690430.4,
// container: 'mp4',
// createdAt: 2019-09-26T06:46:31.929Z,
// ffProbeData:
// { streams:
// [ { index: 0,
// codec_name: 'h264',
// codec_long_name: 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10',
// profile: 'Main',
// codec_type: 'video',
// codec_time_base: '1/50',
// codec_tag_string: 'avc1',
// codec_tag: '0x31637661',
// width: 1280,
// height: 720,
// coded_width: 1280,
// coded_height: 720,
// has_b_frames: 0,
// sample_aspect_ratio: '1:1',
// display_aspect_ratio: '16:9',
// pix_fmt: 'yuv420p',
// level: 31,
// chroma_location: 'left',
// refs: 1,
// is_avc: 'true',
// nal_length_size: '4',
// r_frame_rate: '25/1',
// avg_frame_rate: '25/1',
// time_base: '1/12800',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 67584,
// duration: '5.280000',
// bit_rate: '1205959',
// bits_per_raw_sample: '8',
// nb_frames: '132',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'VideoHandler' } },
// { index: 1,
// codec_name: 'aac',
// codec_long_name: 'AAC (Advanced Audio Coding)',
// profile: 'LC',
// codec_type: 'audio',
// codec_time_base: '1/48000',
// codec_tag_string: 'mp4a',
// codec_tag: '0x6134706d',
// sample_fmt: 'fltp',
// sample_rate: '48000',
// channels: 6,
// channel_layout: '5.1',
// bits_per_sample: 0,
// r_frame_rate: '0/0',
// avg_frame_rate: '0/0',
// time_base: '1/48000',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 254976,
// duration: '5.312000',
// bit_rate: '384828',
// max_bit_rate: '400392',
// nb_frames: '249',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'SoundHandler' } } ] },
// ffProbeRead: 'success',
// file: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// fileMedium: 'video',
// file_size: 1.056519,
// meta:
// { SourceFile: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// errors: [],
// Duration: 5.312,
// PreviewDuration: 0,
// SelectionDuration: 0,
// TrackDuration: 5.28,
// MediaDuration: 5.312,
// ExifToolVersion: 11.65,
// FileName: 'Sample.mp4',
// Directory: 'C:/Users/H/Desktop/Test Input1',
// FileSize: '1032 kB',
// FileModifyDate:
// { year: 2019,
// month: 9,
// day: 24,
// hour: 7,
// minute: 24,
// second: 22,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:24 07:24:22+01:00' },
// FileAccessDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FileCreateDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FilePermissions: 'rw-rw-rw-',
// FileType: 'MP4',
// FileTypeExtension: 'mp4',
// MIMEType: 'video/mp4',
// MajorBrand: 'MP4 Base Media v1 [IS0 14496-12:2003]',
// MinorVersion: '0.2.0',
// CompatibleBrands: [ 'isom', 'iso2', 'avc1', 'mp41' ],
// MovieDataSize: 0,
// MovieDataOffset: 1051515,
// MovieHeaderVersion: 0,
// CreateDate:
// { year: 1970,
// month: 1,
// day: 8,
// hour: 0,
// minute: 0,
// second: 0,
// millisecond: 0,
// rawValue: '1970:01:08 00:00:00' },
// ModifyDate:
// { year: 2014,
// month: 7,
// day: 19,
// hour: 17,
// minute: 15,
// second: 29,
// millisecond: 0,
// rawValue: '2014:07:19 17:15:29' },
// TimeScale: 1000,
// PreferredRate: 1,
// PreferredVolume: '100.00%',
// PreviewTime: '0 s',
// PosterTime: '0 s',
// SelectionTime: '0 s',
// CurrentTime: '0 s',
// NextTrackID: 3,
// TrackHeaderVersion: 0,
// TrackCreateDate: '0000:00:00 00:00:00',
// TrackModifyDate: '0000:00:00 00:00:00',
// TrackID: 1,
// TrackLayer: 0,
// TrackVolume: '0.00%',
// ImageWidth: 1280,
// ImageHeight: 720,
// GraphicsMode: 'srcCopy',
// OpColor: '0 0 0',
// CompressorID: 'avc1',
// SourceImageWidth: 1280,
// SourceImageHeight: 720,
// XResolution: 72,
// YResolution: 72,
// BitDepth: 24,
// VideoFrameRate: 25,
// MatrixStructure: '1 0 0 0 1 0 0 0 1',
// MediaHeaderVersion: 0,
// MediaCreateDate: '0000:00:00 00:00:00',
// MediaModifyDate: '0000:00:00 00:00:00',
// MediaTimeScale: 48000,
// MediaLanguageCode: 'und',
// HandlerDescription: 'SoundHandler',
// Balance: 0,
// AudioFormat: 'mp4a',
// AudioChannels: 2,
// AudioBitsPerSample: 16,
// AudioSampleRate: 48000,
// HandlerType: 'Metadata',
// HandlerVendorID: 'Apple',
// Encoder: 'Lavf53.24.2',
// Title: 'Sample title test',
// Composer: 'th',
// BeatsPerMinute: '',
// ContentCreateDate: 2018,
// Genre: 'this',
// Artist: 'hhj',
// Comment: 'hhk',
// Subtitle: 'jj',
// Mood: 'lik',
// ContentDistributor: 'cont',
// Conductor: 'jo',
// Writer: 'writ',
// InitialKey: 'ho',
// Producer: 'prod',
// ParentalRating: 'par',
// Director: 'dir',
// Period: 'pol',
// Publisher: 'pub',
// PromotionURL: 'prom',
// AuthorURL: 'auth',
// EncodedBy: 'enc',
// Category: 'h',
// ImageSize: '1280x720',
// Megapixels: 0.922,
// AvgBitrate: '1.58 Mbps',
// Rotation: 0 },
// processingStatus: false,
// video_codec_name: 'h264',
// video_resolution: '720p' }
// {
// _id: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// DB: 'ZRPDmnmpyuAEQi7nG',
// HealthCheck: 'Not attempted',
// TranscodeDecisionMaker: 'Not attempted',
// bit_rate: 1690430.4,
// container: 'mp4',
// createdAt: 2019-09-26T06:46:31.929Z,
// ffProbeData:
// { streams:
// [ { index: 0,
// codec_name: 'h264',
// codec_long_name: 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10',
// profile: 'Main',
// codec_type: 'video',
// codec_time_base: '1/50',
// codec_tag_string: 'avc1',
// codec_tag: '0x31637661',
// width: 1280,
// height: 720,
// coded_width: 1280,
// coded_height: 720,
// has_b_frames: 0,
// sample_aspect_ratio: '1:1',
// display_aspect_ratio: '16:9',
// pix_fmt: 'yuv420p',
// level: 31,
// chroma_location: 'left',
// refs: 1,
// is_avc: 'true',
// nal_length_size: '4',
// r_frame_rate: '25/1',
// avg_frame_rate: '25/1',
// time_base: '1/12800',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 67584,
// duration: '5.280000',
// bit_rate: '1205959',
// bits_per_raw_sample: '8',
// nb_frames: '132',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'VideoHandler' } },
// { index: 1,
// codec_name: 'aac',
// codec_long_name: 'AAC (Advanced Audio Coding)',
// profile: 'LC',
// codec_type: 'audio',
// codec_time_base: '1/48000',
// codec_tag_string: 'mp4a',
// codec_tag: '0x6134706d',
// sample_fmt: 'fltp',
// sample_rate: '48000',
// channels: 6,
// channel_layout: '5.1',
// bits_per_sample: 0,
// r_frame_rate: '0/0',
// avg_frame_rate: '0/0',
// time_base: '1/48000',
// start_pts: 0,
// start_time: '0.000000',
// duration_ts: 254976,
// duration: '5.312000',
// bit_rate: '384828',
// max_bit_rate: '400392',
// nb_frames: '249',
// disposition:
// { default: 1,
// dub: 0,
// original: 0,
// comment: 0,
// lyrics: 0,
// karaoke: 0,
// forced: 0,
// hearing_impaired: 0,
// visual_impaired: 0,
// clean_effects: 0,
// attached_pic: 0,
// timed_thumbnails: 0 },
// tags:
// { creation_time: '1970-01-01T00:00:00.000000Z',
// language: 'und',
// handler_name: 'SoundHandler' } } ] },
// ffProbeRead: 'success',
// file: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// fileMedium: 'video',
// file_size: 1.056519,
// meta:
// { SourceFile: 'C:/Users/H/Desktop/Test Input1/Sample.mp4',
// errors: [],
// Duration: 5.312,
// PreviewDuration: 0,
// SelectionDuration: 0,
// TrackDuration: 5.28,
// MediaDuration: 5.312,
// ExifToolVersion: 11.65,
// FileName: 'Sample.mp4',
// Directory: 'C:/Users/H/Desktop/Test Input1',
// FileSize: '1032 kB',
// FileModifyDate:
// { year: 2019,
// month: 9,
// day: 24,
// hour: 7,
// minute: 24,
// second: 22,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:24 07:24:22+01:00' },
// FileAccessDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FileCreateDate:
// { year: 2019,
// month: 9,
// day: 26,
// hour: 7,
// minute: 44,
// second: 30,
// millisecond: 0,
// tzoffsetMinutes: 60,
// rawValue: '2019:09:26 07:44:30+01:00' },
// FilePermissions: 'rw-rw-rw-',
// FileType: 'MP4',
// FileTypeExtension: 'mp4',
// MIMEType: 'video/mp4',
// MajorBrand: 'MP4 Base Media v1 [IS0 14496-12:2003]',
// MinorVersion: '0.2.0',
// CompatibleBrands: [ 'isom', 'iso2', 'avc1', 'mp41' ],
// MovieDataSize: 0,
// MovieDataOffset: 1051515,
// MovieHeaderVersion: 0,
// CreateDate:
// { year: 1970,
// month: 1,
// day: 8,
// hour: 0,
// minute: 0,
// second: 0,
// millisecond: 0,
// rawValue: '1970:01:08 00:00:00' },
// ModifyDate:
// { year: 2014,
// month: 7,
// day: 19,
// hour: 17,
// minute: 15,
// second: 29,
// millisecond: 0,
// rawValue: '2014:07:19 17:15:29' },
// TimeScale: 1000,
// PreferredRate: 1,
// PreferredVolume: '100.00%',
// PreviewTime: '0 s',
// PosterTime: '0 s',
// SelectionTime: '0 s',
// CurrentTime: '0 s',
// NextTrackID: 3,
// TrackHeaderVersion: 0,
// TrackCreateDate: '0000:00:00 00:00:00',
// TrackModifyDate: '0000:00:00 00:00:00',
// TrackID: 1,
// TrackLayer: 0,
// TrackVolume: '0.00%',
// ImageWidth: 1280,
// ImageHeight: 720,
// GraphicsMode: 'srcCopy',
// OpColor: '0 0 0',
// CompressorID: 'avc1',
// SourceImageWidth: 1280,
// SourceImageHeight: 720,
// XResolution: 72,
// YResolution: 72,
// BitDepth: 24,
// VideoFrameRate: 25,
// MatrixStructure: '1 0 0 0 1 0 0 0 1',
// MediaHeaderVersion: 0,
// MediaCreateDate: '0000:00:00 00:00:00',
// MediaModifyDate: '0000:00:00 00:00:00',
// MediaTimeScale: 48000,
// MediaLanguageCode: 'und',
// HandlerDescription: 'SoundHandler',
// Balance: 0,
// AudioFormat: 'mp4a',
// AudioChannels: 2,
// AudioBitsPerSample: 16,
// AudioSampleRate: 48000,
// HandlerType: 'Metadata',
// HandlerVendorID: 'Apple',
// Encoder: 'Lavf53.24.2',
// Title: 'Sample title test',
// Composer: 'th',
// BeatsPerMinute: '',
// ContentCreateDate: 2018,
// Genre: 'this',
// Artist: 'hhj',
// Comment: 'hhk',
// Subtitle: 'jj',
// Mood: 'lik',
// ContentDistributor: 'cont',
// Conductor: 'jo',
// Writer: 'writ',
// InitialKey: 'ho',
// Producer: 'prod',
// ParentalRating: 'par',
// Director: 'dir',
// Period: 'pol',
// Publisher: 'pub',
// PromotionURL: 'prom',
// AuthorURL: 'auth',
// EncodedBy: 'enc',
// Category: 'h',
// ImageSize: '1280x720',
// Megapixels: 0.922,
// AvgBitrate: '1.58 Mbps',
// Rotation: 0 },
// processingStatus: false,
// video_codec_name: 'h264',
// video_resolution: '720p' }

@ -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/')
} else{
var rootModules = ''
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
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/')
} else{
var rootModules = ''
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
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/')
} else{
var rootModules = ''
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
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
} else {
var response = {
processFile: false,
note:`File is already in ${container} \n`
}
return response
}
} catch (err) {
var response = {
processFile: false,
note:`library.actions.remuxContainer error: ${err} \n`
}
return response
try {
if (file.container != container) {
var response = {
processFile: true,
note: `File is not in ${container} \n`,
};
return response;
} else {
var response = {
processFile: false,
note: `File is already in ${container} \n`,
};
return response;
}
} catch (err) {
var response = {
processFile: false,
note: `library.actions.remuxContainer error: ${err} \n`,
};
return response;
}
}
module.exports = remuxContainer
module.exports = remuxContainer;

@ -1,313 +1,276 @@
module.exports = function transcodeAddAudioStream(
file,
audioEncoder,
langTag,
channelCount
) {
// response.preset = library.actions.transcodeAddAudioStream(file, 'aac', 'en', 1).preset
//Function required responses
// preset
// processFile
// note
try {
var audioCodec = audioEncoder;
langTag = langTag.toLowerCase();
if (audioEncoder == "dca") {
audioCodec = "dts";
}
if (audioEncoder == "libmp3lame") {
audioCodec = "mp3";
}
module.exports = function transcodeAddAudioStream(file, audioEncoder, langTag, channelCount) {
// response.preset = library.actions.transcodeAddAudioStream(file, 'aac', 'en', 1).preset
//Function required responses
// preset
// processFile
// note
try {
var audioCodec = audioEncoder
langTag = langTag.toLowerCase()
if (audioEncoder == 'dca') {
audioCodec = 'dts'
}
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) => {
try {
if (
stream.codec_type == "audio" &&
stream.codec_name === audioCodec &&
stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) &&
stream.channels == channelCount
) {
return true;
}
} catch (err) {}
//Step 1: Check if the file already has the required stream codec/langtag/channel count
return false;
});
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
}
} catch (err) { }
return false
})
if (hasStreamAlready.length > 0) {
return {
preset: "",
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels\n`,
};
}
if (hasStreamAlready.length > 0) {
//Step 2: Check if file has streams with specified lang tag
return {
preset: '',
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels\n`
}
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false;
});
//Step 2: Check if file has streams with specified lang tag
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
}
} catch (err) { }
console.log("streamsWithLangTag:" + streamsWithLangTag);
return false
})
console.log("streamsWithLangTag:" + streamsWithLangTag)
if (streamsWithLangTag.length != 0) {
return attemptMakeStreamLang(langTag)
if (streamsWithLangTag.length != 0) {
return attemptMakeStreamLang(langTag);
} else {
return attemptMakeStreamUnd("und");
}
function attemptMakeStreamLang(langTag) {
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false;
});
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first;
} else {
return attemptMakeStreamUnd('und')
return second;
}
function attemptMakeStreamLang(langTag) {
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
}
} catch (err) { }
return false
})
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
} else {
return second
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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;
}
} catch (err) {}
return false;
});
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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
}
} catch (err) { }
return false
})
if (hasStreamAlready.length > 0) {
return {
preset: '',
processFile: false,
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`
}
}
} else {
console.log('here3')
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
}
} catch (err) { }
return false
})
if (hasStreamAlready.length > 0) {
return {
preset: '',
processFile: false,
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`
}
}
}
if (hasStreamAlready.length > 0) {
return {
preset: "",
processFile: false,
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`,
};
}
function attemptMakeStreamUnd(langTag) {
console.log('No tracks with specified lang tag exist. Checking undefined tracks.')
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
}
} catch (err) { }
return false
})
if (streamsWithLangTag.length == 0) {
return {
preset: ``,
processFile: false,
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`
}
} else {
console.log("here3");
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;
}
} catch (err) {}
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
} else {
return second
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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
}
} catch (err) { }
return false
})
if (hasStreamAlready.length > 0) {
return {
preset: '',
processFile: false,
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`
}
}
return false;
});
} else {
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
}
} catch (err) { }
return false
})
if (hasStreamAlready.length > 0) {
return {
preset: '',
processFile: false,
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`
}
}
}
if (hasStreamAlready.length > 0) {
return {
preset: "",
processFile: false,
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`,
};
}
}
}
function attemptMakeStreamUnd(langTag) {
console.log(
"No tracks with specified lang tag exist. Checking undefined tracks."
);
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;
}
} catch (err) {}
return false;
});
if (streamsWithLangTag.length == 0) {
return {
preset: ``,
processFile: false,
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`,
};
}
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first;
} else {
return second;
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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;
}
} catch (err) {}
return false;
});
if (hasStreamAlready.length > 0) {
return {
preset: "",
processFile: false,
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`,
};
}
} else {
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;
}
} catch (err) {}
return false;
});
} catch (err) {
return {
preset: '',
if (hasStreamAlready.length > 0) {
return {
preset: "",
processFile: false,
note: `library.actions.transcodeAddAudioStream error: ${err} \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`,
};
}
}
}
}
} catch (err) {
return {
preset: "",
processFile: false,
note: `library.actions.transcodeAddAudioStream error: ${err} \n`,
};
}
};

@ -1,365 +1,325 @@
module.exports = function transcodeKeepOneAudioStream(
file,
audioEncoder,
langTag,
channelCount
) {
// response.preset = library.actions.transcodeKeepOneAudioStream(file, 'aac', 'en', 1).preset
//Function required responses
// preset
// processFile
// note
try {
var audioCodec = audioEncoder;
langTag = langTag.toLowerCase();
if (audioEncoder == "dca") {
audioCodec = "dts";
}
if (audioEncoder == "libmp3lame") {
audioCodec = "mp3";
}
module.exports = function transcodeKeepOneAudioStream(file, audioEncoder, langTag, channelCount) {
// response.preset = library.actions.transcodeKeepOneAudioStream(file, 'aac', 'en', 1).preset
//Function required responses
// preset
// processFile
// note
var reqLang = langTag;
try {
var numberOfAudioStreams = file.ffProbeData.streams.filter(
(stream) => stream.codec_type == "audio"
).length;
var audioCodec = audioEncoder
langTag = langTag.toLowerCase()
//Step 1: Check if the file already has the required stream codec/langtag/channel count
if (audioEncoder == 'dca') {
audioCodec = 'dts'
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;
}
} catch (err) {}
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: "",
processFile: false,
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 = "";
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}`;
}
} 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`,
};
}
if (audioEncoder == 'libmp3lame') {
audioCodec = 'mp3'
}
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 => {
try {
if (stream.codec_type == 'audio' && stream.codec_name === audioCodec && stream.tags.language.toLowerCase().includes(langTag.toLowerCase()) && stream.channels == channelCount) {
return true
}
//Step 2: Check if file has streams with specified lang tag
} catch (err) { }
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false
})
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return false;
});
console.log("streamsWithLangTag:" + streamsWithLangTag);
if (streamsWithLangTag.length != 0) {
return attemptMakeStreamLang(langTag);
} else {
return attemptMakeStreamUnd("und");
}
return {
preset: '',
processFile: false,
note: `File already has ${langTag} stream in ${audioEncoder}, ${channelCount} channels. It is the only track! \n`
function attemptMakeStreamLang(langTag) {
var streamsWithLangTag = file.ffProbeData.streams.filter((stream) => {
try {
if (
stream.codec_type == "audio" &&
stream.tags.language.toLowerCase().includes(langTag)
) {
return true;
}
} catch (err) {}
return false;
});
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first;
} else {
return second;
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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;
}
} catch (err) {}
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: "",
processFile: false,
note: `The required stream already exists. It is the only audio stream. \n`,
};
} else if (hasStreamAlready.length >= 1) {
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}`
}
} catch (err) { }
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`,
};
} 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`,
};
}
} else {
console.log("here3");
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;
}
} 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`
}
return false;
});
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: "",
processFile: false,
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`,
};
} 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`,
};
}
}
}
function attemptMakeStreamUnd(langTag) {
console.log(
"No tracks with specified lang tag exist. Checking undefined tracks."
);
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;
}
} catch (err) {}
return false;
});
if (streamsWithLangTag.length == 0) {
return {
preset: ``,
processFile: false,
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`,
};
}
//Step 2: Check if file has streams with specified lang tag
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
}
} catch (err) { }
return false
})
console.log("streamsWithLangTag:" + streamsWithLangTag)
if (streamsWithLangTag.length != 0) {
return attemptMakeStreamLang(langTag)
var highestChannelCount = streamsWithLangTag.reduce(getHighest);
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first;
} else {
return attemptMakeStreamUnd('und')
return second;
}
function attemptMakeStreamLang(langTag) {
var streamsWithLangTag = file.ffProbeData.streams.filter(stream => {
try {
if (stream.codec_type == 'audio' && stream.tags.language.toLowerCase().includes(langTag)) {
return true
}
} catch (err) { }
return false
})
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
} else {
return second
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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;
}
} catch (err) {}
return false;
});
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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
}
} catch (err) { }
return false
})
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
processFile: false,
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`
}
} 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`
}
}
} else {
console.log('here3')
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
}
} catch (err) { }
return false
})
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
processFile: false,
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`
}
} 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`
}
}
}
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: "",
processFile: false,
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`,
};
} 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`,
};
}
function attemptMakeStreamUnd(langTag) {
console.log('No tracks with specified lang tag exist. Checking undefined tracks.')
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
}
} catch (err) { }
return false
})
if (streamsWithLangTag.length == 0) {
return {
preset: ``,
processFile: false,
note: `Unable to add audio stream in ${langTag}/und with ${channelCount} channels \n`
}
}
var highestChannelCount = streamsWithLangTag.reduce(getHighest)
function getHighest(first, second) {
if (first.channels > second.channels && first) {
return first
} else {
return second
}
}
if (parseInt(highestChannelCount.channels) >= parseInt(channelCount)) {
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
}
} catch (err) { }
return false
})
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
processFile: false,
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`
}
} 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`
}
}
} else {
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
}
} catch (err) { }
return false
})
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: '',
processFile: false,
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`
}
} 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`
}
}
} else {
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;
}
}
} catch (err) {}
return false;
});
} catch (err) {
return {
preset: '',
if (numberOfAudioStreams == 1 && hasStreamAlready.length == 1) {
return {
preset: "",
processFile: false,
note: `library.actions.transcodeKeepOneAudioStream error: ${err} \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`,
};
} 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`,
};
}
}
}
}
} catch (err) {
return {
preset: "",
processFile: false,
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;
if (audioEncoder == "dca") {
audioCodec = "dts";
}
if (audioEncoder == "libmp3lame") {
audioCodec = "mp3";
}
//Function required responses
// preset
// processFile
// note
try {
var audioIdx = -1
var hasNonSpecifiedAudioCodecStream = false
var ffmpegCommandInsert = ''
var audioCodec = audioEncoder
if (audioEncoder == 'dca') {
audioCodec = 'dts'
}
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++
}
} 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
}
} 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`
}
}
return {
preset: '',
processFile: false,
note: `File does not have any audio streams which aren't in ${audioCodec} \n`
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
audioIdx++;
}
} catch (err) {
return {
preset: '',
processFile: false,
note: `library.actions.transcodeStandardiseAudioCodecs error: ${err} \n`
} 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;
}
} 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`,
};
}
}
return {
preset: "",
processFile: false,
note: `File does not have any audio streams which aren't in ${audioCodec} \n`,
};
} catch (err) {
return {
preset: "",
processFile: false,
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)
if (fileAge > ageCutOff_Seconds) {
var response = {
outcome: false,
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
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterByAge error: ${err} \n`
}
return response
try {
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;
} else {
var response = {
outcome: true,
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;
}
}
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);
try {
// console.log(file,mode,codecs)
var allCodecs = file.ffProbeData.streams.map(row => row.codec_name)
var included = false
for (var i = 0; i < allCodecs.length; i++) {
if (codecs.toLowerCase().includes(allCodecs[i])) {
included = true
}
}
if (mode === 'include') {
if (included) {
var response = {
outcome: true,
note: `☑Codec included \n`
}
return response
} else {
var response = {
outcome: false,
note: `☒Codec excluded \n`
}
return response
}
var included = false;
} else if (mode === 'exclude') {
if (included) {
var response = {
outcome: false,
note: `☒Codec excluded \n`
}
return response
} else {
var response = {
outcome: true,
note: `☑Codec not excluded \n`
}
return response
}
}
for (var i = 0; i < allCodecs.length; i++) {
if (codecs.toLowerCase().includes(allCodecs[i])) {
included = true;
}
}
if (mode === "include") {
if (included) {
var response = {
outcome: false,
note: `library.filters.filterByCodec error: ${err} \n`
}
return response
} catch (err) {
console.log(err)
outcome: true,
note: `☑Codec included \n`,
};
return response;
} else {
var response = {
outcome: false,
note: `Filter error hello! ${err}\n`
}
return response
outcome: false,
note: `☒Codec excluded \n`,
};
return response;
}
} else if (mode === "exclude") {
if (included) {
var response = {
outcome: false,
note: `☒Codec excluded \n`,
};
return response;
} else {
var response = {
outcome: true,
note: `☑Codec not excluded \n`,
};
return response;
}
}
var response = {
outcome: false,
note: `library.filters.filterByCodec error: ${err} \n`,
};
return response;
} catch (err) {
console.log(err);
var response = {
outcome: false,
note: `Filter error hello! ${err}\n`,
};
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
} else {
var response = {
outcome: true,
note: `☑File is ${medium} \n`
}
return response
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterByMedium error: ${err} \n`
}
return response
try {
if (file.fileMedium !== medium) {
var response = {
outcome: false,
note: `☒File is not ${medium} \n`,
};
return response;
} else {
var response = {
outcome: true,
note: `☑File is ${medium} \n`,
};
return response;
}
} catch (err) {
var response = {
outcome: false,
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())) {
var response = {
outcome: false,
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())) {
var response = {
outcome: true,
note: `☑File is in included resolution. \n`
}
return response
} else {
var response = {
outcome: false,
note: `☒File is not in included resolution. \n`
}
return response
}
}
} catch (err) {
try {
if (mode === "exclude") {
if (
resolution.toLowerCase().includes(file.video_resolution.toLowerCase())
) {
var response = {
outcome: false,
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())
) {
var response = {
outcome: false,
note: `library.filters.filterByResolution error: ${err} \n`
}
return response
outcome: true,
note: `☑File is in included resolution. \n`,
};
return response;
} else {
var response = {
outcome: false,
note: `☒File is not in included resolution. \n`,
};
return response;
}
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterByResolution error: ${err} \n`,
};
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) {
var response = {
outcome: true,
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
}
} catch (err) {
var response = {
outcome: false,
note: `library.filters.filterBySize error: ${err} \n`
}
return response
try {
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;
} else {
var response = {
outcome: false,
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;
}
}
module.exports = filterBySize
module.exports = filterBySize;

Loading…
Cancel
Save