Migz Plugins

1. Made changes to all plugins following lint testing. There are still various warnings/errors but my very limited knowledge of javascript means I just don't understand what the errors mean. Or in some cases I don't understand how to split the variable across several lines to confirm to the line limits.
I did manage to get it from
952 problems (943 errors, 9 warnings)
down to
37 problems (28 errors, 9 warnings)

2. Fix Flawed logic in FFMPEG plugins which would cause remux conditions to never trigger. Was checking if file was HEVC & VP9 which is impossible as they're both codecs.

3. Fixed a bug with CleanTitle where plugin would fail if a stream in the file didn't have a title.

4. Modify CleanSubtitle plugin to not remove sdh subtitles.

5. Include new plugin to just perform remuxes. Mainly aimed at remuxing to mkv or mp4.
make-only-subtitle-default
Migz93 5 years ago
parent e9370ffe7c
commit 864cf41f1d

@ -1,253 +1,286 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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 This plugin will skip any files that are in the VP9 codec as these are already at a comparable compression level to H265. \n\n`,
Version: "2.8",
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.
\\nExample:\\n
6000
\\nExample:\\n
4000`,
},
{
name: "enable_10bit",
tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: "enable_bframes",
tooltip: `Specify if b frames should be used. Using B frames should decrease file sizes but are only supported on newer GPUs. Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: "force_conform",
tooltip: `Make the file conform to output containers requirements.
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.
\\n Settings are dependant on file bitrate
\\n Working by the logic that H265 can support the same ammount of data at half the bitrate of H264.
\\n NVDEC & NVENC compatable GPU required.
\\n This plugin will skip any files that are in the VP9 codec. \n\n`,
Version: '3.0',
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
\\n Ensure that all stream types you may have are supported by your chosen container.
\\n 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.
\\n Rate is in kbps.
\\n Leave empty to disable.
\\nExample:\\n
6000
\\nExample:\\n
4000`,
},
{
name: 'enable_10bit',
tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: 'enable_bframes',
tooltip: `Specify if b frames should be used.
\\n Using B frames should decrease file sizes but are only supported on newer GPUs.
\\n Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: 'force_conform',
tooltip: `Make the file conform to output containers requirements.
\\n Drop hdmv_pgs_subtitle/eia_608/subrip/timed_id3 for MP4.
\\n Drop data streams/mov_text/eia_608/timed_id3 for MKV.
\\n Default is false.
\\nExample:\\n
true
\\nExample:\\n
true
\\nExample:\\n
false`,
},
\\nExample:\\n
false`,
},
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
const response = {
processFile: false,
preset: "",
preset: '',
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "",
infoLog: '',
};
let duration = '';
// 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";
if (inputs.container === '') {
response.infoLog += 'Plugin has not been configured, please configure required options. Skipping this plugin. \n';
response.processFile = false;
return response;
} else {
response.container = "." + inputs.container;
}
response.container = `.${inputs.container}`;
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
if (file.fileMedium !== 'video') {
response.processFile = false;
response.infoLog += "☒File is not a video. \n";
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;
// 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') {
duration = file.meta.Duration * 0.0166667;
} else {
var duration = file.ffProbeData.streams[0].duration * 0.0166667;
duration = file.ffProbeData.streams[0].duration * 0.0166667;
}
// Set up required variables.
var videoIdx = 0;
var CPU10 = false;
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);
let videoIdx = 0;
let CPU10 = false;
let extraArguments = '';
let 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/
const 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.
const 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);
const minimumBitrate = ~~(targetBitrate * 0.7);
const 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") {
// If targetBitrate comes out as 0 then something has gone wrong and bitrates could not be calculated.
// Cancel plugin completely.
if (targetBitrate === '0') {
response.processFile = false;
response.infoLog +=
"☒Target bitrate could not be calculated. Skipping this plugin. \n";
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.
// 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`;
response.infoLog += `Current bitrate is below set cutoff of ${inputs.bitrate_cutoff}. Cancelling plugin. \n`;
return response;
}
}
// Check if force_conform option is checked. If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.force_conform == "true") {
if (inputs.container.toLowerCase() == "mkv") {
extraArguments += `-map -0:d `;
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_name
.toLowerCase() == "eia_608" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "timed_id3"
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {}
// Check if force_conform option is checked.
// If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.force_conform === 'true') {
if (inputs.container.toLowerCase() === 'mkv') {
extraArguments += '-map -0:d ';
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'mov_text'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'eia_608'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
}
}
}
if (inputs.container.toLowerCase() == "mp4") {
for (var i = 0; i < file.ffProbeData.streams.length; i++)
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "hdmv_pgs_subtitle" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "eia_608" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "subrip" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "timed_id3"
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {}
if (inputs.container.toLowerCase() === 'mp4') {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'hdmv_pgs_subtitle'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'eia_608'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'subrip'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
}
}
}
}
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
if (inputs.enable_10bit === 'true') {
// If set to true then add 10bit argument
extraArguments += `-pix_fmt p010le `;
extraArguments += '-pix_fmt p010le ';
}
// Check if b frame variable is true.
if (inputs.enable_bframes == "true") {
if (inputs.enable_bframes === 'true') {
// If set to true then add b frames argument
extraArguments += `-bf 5 `;
extraArguments += '-bf 5 ';
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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/png, if so then remove this "video" stream. mjpeg/png are usually embedded pictures that can cause havoc with plugins.
if (file.ffProbeData.streams[i].codec_name == "mjpeg" || file.ffProbeData.streams[i].codec_name == "png") {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'video') {
// Check if codec of stream is mjpeg/png, if so then remove this "video" stream.
// mjpeg/png are usually embedded pictures that can cause havoc with plugins.
if (file.ffProbeData.streams[i].codec_name === 'mjpeg' || file.ffProbeData.streams[i].codec_name === 'png') {
extraArguments += `-map -v:${videoIdx} `;
}
// Check if codec of stream is hevc or vp9 AND check if file.container matches inputs.container. If so nothing for plugin to do.
// Check if codec of stream is hevc or vp9 AND check if file.container matches inputs.container.
// If so nothing for plugin to do.
if (
file.ffProbeData.streams[i].codec_name == "hevc" || file.ffProbeData.streams[i].codec_name == "vp9" &&
file.container == inputs.container
(
file.ffProbeData.streams[i].codec_name === 'hevc'
|| file.ffProbeData.streams[i].codec_name === 'vp9'
)
&& file.container === inputs.container
) {
response.processFile = false;
response.infoLog += `☑File is already hevc or vp9 & in ${inputs.container}. \n`;
response.infoLog += `File is already hevc or vp9 & in ${inputs.container}. \n`;
return response;
}
// Check if codec of stream is hevc or vp9 AND check if file.container does NOT match inputs.container. If so remux file.
// Check if codec of stream is hevc or vp9
// AND check if file.container does NOT match inputs.container.
// If so remux file.
if (
file.ffProbeData.streams[i].codec_name == "hevc" || file.ffProbeData.streams[i].codec_name == "vp9" &&
file.container != "${inputs.container}"
(
file.ffProbeData.streams[i].codec_name === 'hevc'
|| file.ffProbeData.streams[i].codec_name === 'vp9'
)
&& file.container !== inputs.container
) {
response.infoLog += `☒File is hevc or vp9 but is not in ${inputs.container} container. Remuxing. \n`;
response.infoLog += `File is hevc or vp9 but is not in ${inputs.container} container. Remuxing. \n`;
response.preset = `, -map 0 -c copy ${extraArguments}`;
response.processFile = true;
return response;
}
// Check if video stream is HDR or 10bit
if (file.ffProbeData.streams[i].profile == "High 10" || file.ffProbeData.streams[i].bits_per_raw_sample == "10" ) {
CPU10 = true
// Check if video stream is HDR or 10bit
if (
file.ffProbeData.streams[i].profile === 'High 10'
|| file.ffProbeData.streams[i].bits_per_raw_sample === '10'
) {
CPU10 = true;
}
// Increment videoIdx.
videoIdx++;
videoIdx += 1;
}
}
// 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.infoLog += `Container for output selected as ${inputs.container}. \n`;
response.infoLog += `Current bitrate = ${currentBitrate} \n`;
response.infoLog += 'Bitrate settings: \n';
response.infoLog += `Target = ${targetBitrate} \n`;
response.infoLog += `Minimum = ${minimumBitrate} \n`;
response.infoLog += `Maximum = ${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 (CPU10 == false) {
response.preset = `-c:v h264_cuvid`;
if (file.video_codec_name === 'h263') {
response.preset = '-c:v h263_cuvid';
} else if (file.video_codec_name === 'h264') {
if (CPU10 === false) {
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 === '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';
}
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 9999 ${extraArguments}`;
response.processFile = true;
response.infoLog += `☒File is not hevc or vp9. Transcoding. \n`;
response.infoLog += 'File is not hevc or vp9. Transcoding. \n';
return response;
}
module.exports.details = details;

@ -1,212 +1,235 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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 This plugin will skip any files that are in the VP9 codec as these are already at a comparable compression level to H265.\n\n`,
Version: "1.7",
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.
\\nExample:\\n
6000
\\nExample:\\n
4000`,
},
{
name: "enable_10bit",
tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: "force_conform",
tooltip: `Make the file conform to output containers requirements.
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 Nvidia GPU with ffmpeg.
\\n Settings are dependant on file bitrate
\\n Working by the logic that H265 can support the same ammount of data at half the bitrate of H264.
\\n This plugin will skip any files that are in the VP9 codec. \n\n`,
Version: '1.9',
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.
\\n Ensure that all stream types you may have are supported by your chosen container.
\\n 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.
\\n Rate is in kbps.
\\n Leave empty to disable.
\\nExample:\\n
6000
\\nExample:\\n
4000`,
},
{
name: 'enable_10bit',
tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: 'force_conform',
tooltip: `Make the file conform to output containers requirements.
\\n Drop hdmv_pgs_subtitle/eia_608/subrip/timed_id3 for MP4.
\\n Drop data streams/mov_text/eia_608/timed_id3 for MKV.
\\n Default is false.
\\nExample:\\n
true
\\nExample:\\n
true
\\nExample:\\n
false`,
},
\\nExample:\\n
false`,
},
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
const response = {
processFile: false,
preset: "",
preset: '',
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "",
infoLog: '',
};
let duration = '';
// Check if inputs.container has been configured. If it hasn't then exit plugin.
if (!inputs || inputs.container == "") {
response.infoLog +=
"☒Container has not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
if (inputs.container === '') {
response.infoLog += 'Plugin has not been configured, please configure required options. Skipping this plugin. \n';
response.processFile = false;
return response;
} else {
response.container = "." + inputs.container;
}
response.container = `.${inputs.container}`;
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
if (file.fileMedium !== 'video') {
response.processFile = false;
response.infoLog += "☒File is not a video. \n";
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;
// 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') {
duration = file.meta.Duration * 0.0166667;
} else {
var duration = file.ffProbeData.streams[0].duration * 0.0166667;
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);
let videoIdx = -1;
let extraArguments = '';
let 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/
const 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.
const 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);
const minimumBitrate = ~~(targetBitrate * 0.7);
const 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") {
// 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";
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.
// 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`;
response.infoLog += `Current bitrate is below set bitrate cutoff of ${inputs.bitrate_cutoff}. Nothing to do, cancelling plugin. \n`;
return response;
}
}
// Check if force_conform option is checked. If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.force_conform == "true") {
if (inputs.container.toLowerCase() == "mkv") {
extraArguments += `-map -0:d `;
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_name
.toLowerCase() == "eia_608" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "timed_id3"
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {}
// Check if force_conform option is checked.
// If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.force_conform === 'true') {
if (inputs.container.toLowerCase() === 'mkv') {
extraArguments += '-map -0:d ';
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'mov_text'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'eia_608'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
}
}
}
if (inputs.container.toLowerCase() == "mp4") {
for (var i = 0; i < file.ffProbeData.streams.length; i++)
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "hdmv_pgs_subtitle" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "eia_608" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "subrip" ||
file.ffProbeData.streams[i].codec_name
.toLowerCase() == "timed_id3"
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {}
if (inputs.container.toLowerCase() === 'mp4') {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'hdmv_pgs_subtitle'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'eia_608'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'subrip'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
}
}
}
}
}
// Check if 10bit variable is true.
if (inputs.enable_10bit == "true") {
if (inputs.enable_10bit === 'true') {
// If set to true then add 10bit argument
extraArguments += `-pix_fmt p010le `;
extraArguments += '-pix_fmt p010le ';
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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/png, if so then remove this "video" stream. mjpeg/png are usually embedded pictures that can cause havoc with plugins.
if (file.ffProbeData.streams[i].codec_name == "mjpeg" || file.ffProbeData.streams[i].codec_name == "png") {
extraArguments += `-map -v:${videoIdx} `;
}
// Check if codec of stream is hevc or vp9 AND check if file.container matches inputs.container. If so nothing for plugin to do.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'video') {
// Check if codec of stream is mjpeg/png.
// If so then remove this "video" stream.
// mjpeg/png are usually embedded pictures that can cause havoc with plugins.
if (file.ffProbeData.streams[i].codec_name === 'mjpeg' || file.ffProbeData.streams[i].codec_name === 'png') {
extraArguments += `-map -v:${videoIdx} `;
}
// Check if codec of stream is hevc or vp9
// AND check if file.container matches inputs.container.
// If so nothing for plugin to do.
if (
file.ffProbeData.streams[i].codec_name == "hevc" || file.ffProbeData.streams[i].codec_name == "vp9" &&
file.container == inputs.container
(file.ffProbeData.streams[i].codec_name === 'hevc' || file.ffProbeData.streams[i].codec_name === 'vp9')
&& file.container === `${inputs.container}`
) {
response.processFile = false;
response.infoLog += `File is already hevc or vp9 & in ${inputs.container}. \n`;
response.infoLog += `File is already hevc or vp9 & in ${inputs.container}. \n`;
return response;
}
// Check if codec of stream is hevc or vp9 AND check if file.container does NOT match inputs.container. If so remux file.
// Check if codec of stream is hevc or vp9
// AND check if file.container does NOT match inputs.container.
// If so remux file.
if (
file.ffProbeData.streams[i].codec_name == "hevc" || file.ffProbeData.streams[i].codec_name == "vp9" &&
file.container != "${inputs.container}"
(file.ffProbeData.streams[i].codec_name === 'hevc' || file.ffProbeData.streams[i].codec_name === 'vp9')
&& file.container !== `${inputs.container}`
) {
response.infoLog += `File is hevc or vp9 but is not in ${inputs.container} container. Remuxing. \n`;
response.infoLog += `File is hevc or vp9 but is not in ${inputs.container} container. Remuxing. \n`;
response.preset = `, -map 0 -c copy ${extraArguments}`;
response.processFile = true;
return response;
}
// Increment videoIdx.
videoIdx++;
videoIdx += 1;
}
}
// 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.infoLog += `Container for output selected as ${inputs.container}. \n`;
response.infoLog += `Current bitrate = ${currentBitrate} \n`;
response.infoLog += 'Bitrate settings: \n';
response.infoLog += `Target = ${targetBitrate} \n`;
response.infoLog += `Minimum = ${minimumBitrate} \n`;
response.infoLog += `Maximum = ${maximumBitrate} \n`;
response.preset += `,-map 0 -c:v libx265 ${bitrateSettings} -c:a copy -c:s copy -max_muxing_queue_size 9999 ${extraArguments}`;
response.processFile = true;
response.infoLog += `☒File is not hevc or vp9. Transcoding. \n`;
response.infoLog += 'File is not hevc or vp9. Transcoding. \n';
return response;
}
module.exports.details = details;

@ -0,0 +1,130 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() {
return {
id: 'Tdarr_Plugin_MC93_Migz1Remux',
Stage: 'Pre-processing',
Name: 'Migz-Remux container',
Type: 'Video',
Operation: 'Remux',
Description: 'Files will be remuxed into either mkv or mp4. \n\n',
Version: '1.1',
Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1Remux.js',
Tags: 'pre-processing,ffmpeg,video only,configurable',
Inputs: [{
name: 'container',
tooltip: `Specify output container of file
\\nEnsure that all stream types you may have are supported by your chosen container.
\\nmkv is recommended.
\\nExample:\\n
mkv
\\nExample:\\n
mp4`,
},
{
name: 'force_conform',
tooltip: `Make the file conform to output containers requirements.
\\n Drop hdmv_pgs_subtitle/eia_608/subrip/timed_id3 for MP4.
\\n Drop data streams/mov_text/eia_608/timed_id3 for MKV.
\\n Default is false.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
],
};
}
function plugin(file, librarySettings, inputs) {
const 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, please configure required options. Skipping this plugin. \n';
response.processFile = false;
return response;
}
response.container = `.${inputs.container}`;
// 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.
let extraArguments = '';
let convert = false;
// Check if force_conform option is checked.
// If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.force_conform === 'true') {
if (inputs.container.toLowerCase() === 'mkv') {
extraArguments += '-map -0:d ';
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'mov_text'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'eia_608'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
}
}
}
if (inputs.container.toLowerCase() === 'mp4') {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'hdmv_pgs_subtitle'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'eia_608'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'subrip'
|| file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
}
}
}
}
// Check if file.container does NOT match inputs.container. If so remux file.
if (file.container !== inputs.container) {
response.infoLog += `☒File is ${file.container} but requested to be ${inputs.container} container. Remuxing. \n`;
convert = true;
} else if (file.container === inputs.container) {
response.infoLog += `☑File is already in ${inputs.container} container. \n`;
return response;
}
if (convert === true) {
response.preset += `, -map 0 -c copy -max_muxing_queue_size 9999 ${extraArguments}`;
response.processFile = true;
return response;
}
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -1,164 +1,193 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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.7",
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
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.\n\n',
Version: '1.9',
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.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: 'clean_subtitles',
tooltip: `Specify if subtitle titles should be checked & cleaned. Optional.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: "custom_title_matching",
tooltip: `By default if you enable audio or subtitle cleaning the plugin only looks for titles with more then 3 full stops, this is what i think is the safest way to identify junk metadata without removing real metadata that you might want to keep. Here you can specify your own text for it to also search for to match and remove. Comma separated. Optional.
\\nExample:\\n
MiNX - Small HD episodes
\\nExample:\\n
false`,
},
{
name: 'custom_title_matching',
tooltip: `If you enable audio or subtitle cleaning the plugin only looks for titles with more then 3 full stops.
//nThis is one way to identify junk metadata without removing real metadata that you might want.
//nHere you can specify your own text for it to also search for to match and remove.
//nComma separated. Optional.
\\nExample:\\n
MiNX - Small HD episodes
\\nExample:\\n
MiNX - Small HD episodes,GalaxyTV - small excellence!`,
},
\\nExample:\\n
MiNX - Small HD episodes,GalaxyTV - small excellence!`,
},
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
const response = {
processFile: false,
preset: "",
container: "." + file.container,
preset: '',
container: `.${file.container}`,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: "",
infoLog: '',
};
// Set up required variables.
var ffmpegCommandInsert = "";
var videoIdx = 0;
var audioIdx = 0;
var subtitleIdx = 0;
var convert = false;
let ffmpegCommandInsert = '';
let videoIdx = 0;
let audioIdx = 0;
let subtitleIdx = 0;
let convert = false;
let custom_title_matching = '';
// Check if inputs.custom_title_matching has been configured. If it has then set variable
if (typeof inputs.custom_title_matching != "undefined")
{
var custom_title_matching = inputs.custom_title_matching.toLowerCase().split(",");
// Check if inputs.custom_title_matching has been configured. If it has then set variable
if (typeof inputs.custom_title_matching !== 'undefined') {
custom_title_matching = inputs.custom_title_matching.toLowerCase().split(',');
}
// 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";
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")
if (typeof file.meta.Title !== 'undefined') {
try {
ffmpegCommandInsert += ` -metadata title="" `;
ffmpegCommandInsert += ' -metadata title="" ';
convert = true;
} catch (err) {}
} catch (err) {
// Error
}
}
// 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") {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is a video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'video') {
try {
// Check if stream title is not empty, if it's not empty set to "".
if (typeof file.ffProbeData.streams[i].tags.title != "undefined")
try {
response.infoLog += `☒Video stream title is not empty, most likely junk metadata. Removing title from stream ${i} \n`;
if (typeof file.ffProbeData.streams[i].tags.title !== 'undefined') {
response.infoLog += `☒Video stream title is not empty. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:v:${videoIdx} title="" `;
convert = true;
} catch (err) {}
}
// Increment videoIdx.
videoIdx++;
videoIdx += 1;
} catch (err) {
// Error
}
}
// 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. Then check if any audio streams match with user input custom_title_matching variable, if so then remove.
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" &&
inputs.clean_audio.toLowerCase() == "true"
) {
if (typeof file.ffProbeData.streams[i].tags.title != "undefined") {
if (file.ffProbeData.streams[i].tags.title.split(".").length - 1 > 3)
try {
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;
} catch (err) {}
if (typeof inputs.custom_title_matching != "undefined")
try {
if (custom_title_matching.indexOf(file.ffProbeData.streams[i].tags.title.toLowerCase()) !== -1)
{
response.infoLog += `☒Audio matched custom input. Removing title from stream ${i} \n`;
// 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.
// Then check if any audio streams match with user input custom_title_matching variable, if so then remove.
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
&& inputs.clean_audio.toLowerCase() === 'true'
) {
try {
if (typeof file.ffProbeData.streams[i].tags.title !== 'undefined') {
if (file.ffProbeData.streams[i].tags.title.split('.').length - 1 > 3) {
try {
response.infoLog += `☒More then 3 full stops in audio title. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:a:${audioIdx} title="" `;
convert = true;
}
} catch (err) {}
}
// Increment audioIdx.
audioIdx++;
} catch (err) {
// Error
}
}
if (typeof inputs.custom_title_matching !== 'undefined') {
try {
if (custom_title_matching.indexOf(file.ffProbeData.streams[i].tags.title.toLowerCase()) !== -1) {
response.infoLog += `☒Audio matched custom input. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:a:${audioIdx} title="" `;
convert = true;
}
} catch (err) {
// Error
}
}
}
// Increment audioIdx.
audioIdx += 1;
} catch (err) {
// Error
}
}
// 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. Then check if any audio streams match with user input custom_title_matching variable, if so then remove.
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" &&
inputs.clean_subtitles.toLowerCase() == "true"
) {
if (typeof file.ffProbeData.streams[i].tags.title != "undefined") {
if (file.ffProbeData.streams[i].tags.title.split(".").length - 1 > 3)
try {
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;
} catch (err) {}
if (typeof inputs.custom_title_matching != "undefined")
try {
if (custom_title_matching.indexOf(file.ffProbeData.streams[i].tags.title.toLowerCase()) !== -1) {
response.infoLog += `☒Subtitle matched custom input. Removing title from stream ${i} \n`;
// 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.
// Then check if any streams match with user input custom_title_matching variable, if so then remove.
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle'
&& inputs.clean_subtitles.toLowerCase() === 'true'
) {
try {
if (typeof file.ffProbeData.streams[i].tags.title !== 'undefined') {
if (file.ffProbeData.streams[i].tags.title.split('.').length - 1 > 3) {
try {
response.infoLog += `☒More then 3 full stops in subtitle title. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:s:${subtitleIdx} title="" `;
convert = true;
}
} catch (err) {}
}
} catch (err) {
// Error
}
}
if (typeof inputs.custom_title_matching !== 'undefined') {
try {
if (custom_title_matching.indexOf(file.ffProbeData.streams[i].tags.title.toLowerCase()) !== -1) {
response.infoLog += `☒Subtitle matched custom input. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:s:${subtitleIdx} title="" `;
convert = true;
}
} catch (err) {
// Error
}
}
}
// Increment subtitleIdx.
subtitleIdx++;
subtitleIdx += 1;
} catch (err) {
// Error
}
}
}
// Convert file if convert variable is set to true.
if (convert == true) {
response.infoLog += "☒File has title metadata. Removing \n";
if (convert === true) {
response.infoLog += '☒File has title metadata. Removing \n';
response.preset = `,${ffmpegCommandInsert} -c copy -map 0 -max_muxing_queue_size 9999`;
response.reQueueAfter = true;
response.processFile = true;
} else {
response.infoLog += "☑File has no title metadata \n";
response.infoLog += '☑File has no title metadata \n';
}
return response;
}

@ -1,141 +1,153 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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.3",
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
\\nExample:\\n
eng,und
\\nExample:\\n
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
\\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.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
id: 'Tdarr_Plugin_MC93_Migz3CleanAudio',
Stage: 'Pre-processing',
Name: 'Migz-Clean audio streams',
Type: 'Audio',
Operation: 'Clean',
Description: 'This plugin keeps only specified language tracks & can tags tracks with an unknown language. \n\n',
Version: '2.4',
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
\\nRecommended to keep "und" as this stands for undertermined
\\nSome files may not have the language specified.
\\nMust follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nExample:\\n
eng
\\nExample:\\n
eng,und
\\nExample:\\n
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.
\\nYou must have "und" in your list of languages to keep for this to function.
\\nMust follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nLeave empty to disable.
\\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.
\\nDo NOT use this with mp4, as mp4 does not support title tags.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
const response = {
processFile: false,
preset: "",
container: "." + file.container,
preset: '',
container: `.${file.container}`,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: "",
infoLog: '',
};
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
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";
if (inputs.language === '') {
response.infoLog += '☒Language/s options not set, 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"
const language = inputs.language.split(',');
let ffmpegCommandInsert = '';
let convert = false;
let audioIdx = 0;
let audioStreamsRemoved = 0;
const audioStreamCount = file.ffProbeData.streams.filter(
(row) => row.codec_type.toLowerCase() === 'audio',
).length;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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.
// 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()
file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
&& language.indexOf(
file.ffProbeData.streams[i].tags.language.toLowerCase(),
) === -1
) {
audioStreamsRemoved++;
audioStreamsRemoved += 1;
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`;
response.infoLog += `☒Audio stream detected as being unwanted, removing. Audio stream 0:a:${audioIdx} \n`;
convert = true;
}
} catch (err) {}
} catch (err) {
// Error
}
// 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.
// 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
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
.includes('commentary')
|| file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("description") ||
file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh"))
.includes('description')
|| file.ffProbeData.streams[i].tags.title.toLowerCase().includes('sdh'))
) {
audioStreamsRemoved++;
audioStreamsRemoved += 1;
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`;
response.infoLog += `☒Audio stream detected as being descriptive, removing. Stream 0:a:${audioIdx} \n`;
convert = true;
}
} catch (err) {}
} catch (err) {
// Error
}
// 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.
// 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"
inputs.tag_language !== ''
&& file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
) {
// Catch error here incase the metadata is completely missing.
try {
@ -143,64 +155,69 @@ function plugin(file, librarySettings, inputs) {
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes("und")
.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`;
response.infoLog += `☒Audio stream detected as having no language, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
} catch (err) {}
} catch (err) {
// Error
}
// 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") {
// 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`;
response.infoLog += `☒Audio stream detected as having no language, tagging as ${inputs.tag_language}. \n`;
convert = true;
} else if (typeof file.ffProbeData.streams[i].tags.language === 'undefined') {
// 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.
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Audio stream detected as having no language, 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.
// 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"
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") {
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`;
response.infoLog += `☒Audio stream detected as 8 channel with no title, tagging. Stream 0:a:${audioIdx} \n`;
convert = true;
}
if (file.ffProbeData.streams[i].channels == "6") {
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`;
response.infoLog += `☒Audio stream detected as 6 channel with no title, tagging. Stream 0:a:${audioIdx} \n`;
convert = true;
}
if (file.ffProbeData.streams[i].channels == "2") {
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`;
response.infoLog += `☒Audio stream detected as 2 channel with no title, tagging. Stream 0:a:${audioIdx} \n`;
convert = true;
}
}
} catch (err) {}
} catch (err) {
// Error
}
// 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].codec_type.toLowerCase() === 'audio') {
audioIdx += 1;
}
}
// 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";
if (audioStreamsRemoved === audioStreamCount) {
response.infoLog += '☒Cancelling plugin otherwise all audio tracks would be removed. \n';
response.processFile = false;
return response;
}
@ -209,12 +226,11 @@ function plugin(file, librarySettings, inputs) {
if (convert === true) {
response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 9999`;
response.container = "." + file.container;
response.container = `.${file.container}`;
response.reQueueAfter = true;
} else {
response.processFile = false;
response.infoLog +=
"☑File doesn't contain audio tracks which are unwanted or that require tagging.\n";
response.infoLog += "☑File doesn't contain audio tracks which are unwanted or that require tagging.\n";
}
return response;
}

@ -1,124 +1,131 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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.3",
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
id: 'Tdarr_Plugin_MC93_Migz4CleanSubs',
Stage: 'Pre-processing',
Name: 'Migz-Clean subtitle streams',
Type: 'subtitles',
Operation: 'Clean',
Description: 'This plugin keeps only specified language tracks & can tag tracks with an unknown language. \n\n',
Version: '2.4',
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.
\\nMust 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.
\\nExample:\\n
true
\\nExample:\\n
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
\\nExample:\\n
eng
\\nExample:\\n
false`,
},
{
name: 'tag_language',
tooltip: `Specify a single language for subtitle tracks with no language or unknown language to be tagged with.
\\nMust follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nLeave empty to disable.
\\nExample:\\n
eng
\\nExample:\\n
por`,
},
\\nExample:\\n
por`,
},
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
const response = {
processFile: false,
preset: "",
container: "." + file.container,
preset: '',
container: `.${file.container}`,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: "",
infoLog: '',
};
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
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";
if (inputs.language === '') {
response.infoLog += '☒Language/s to keep have not been configured, 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;
const language = inputs.language.split(',');
let ffmpegCommandInsert = '';
let subtitleIdx = 0;
let convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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.
// 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()
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`;
response.infoLog += `☒Subtitle stream detected as being unwanted, removing. Stream 0:s:${subtitleIdx} \n`;
convert = true;
}
} catch (err) {}
} catch (err) {
// Error
}
// 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.
// Check if inputs.commentary is set to true
// AND if stream is subtitle
// AND then checks for stream titles with the following "commentary or description".
// 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
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
.includes('commentary')
|| file.ffProbeData.streams[i].tags.title
.toLowerCase()
.includes("description") ||
file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh"))
.includes('description'))
) {
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`;
response.infoLog += `☒Subtitle stream detected as being descriptive, removing. Stream 0:s:${subtitleIdx} \n`;
convert = true;
}
} catch (err) {}
} catch (err) {
// Error
}
// 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.
// 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"
inputs.tag_language !== ''
&& file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle'
) {
// Catch error here incase the metadata is completely missing.
try {
@ -126,33 +133,36 @@ function plugin(file, librarySettings, inputs) {
if (
file.ffProbeData.streams[i].tags.language
.toLowerCase()
.includes("und")
.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`;
response.infoLog += `☒Subtitle stream detected as having no language, tagging as ${inputs.tag_language}. \n`;
convert = true;
}
} catch (err) {}
} catch (err) {
// Error
}
// 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") {
// 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`;
response.infoLog += `☒Subtitle stream detected as having no language, tagging as ${inputs.tag_language}. \n`;
convert = true;
} else if (typeof file.ffProbeData.streams[i].tags.language === 'undefined') {
// 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
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Subtitle stream detected as having no language, 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 stream type is subtitle and increment subtitleIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
subtitleIdx++;
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle') {
subtitleIdx += 1;
}
}
@ -160,12 +170,11 @@ function plugin(file, librarySettings, inputs) {
if (convert === true) {
response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 9999`;
response.container = "." + file.container;
response.container = `.${file.container}`;
response.reQueueAfter = true;
} else {
response.processFile = false;
response.infoLog +=
"☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n";
response.infoLog += "☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n";
}
return response;
}

@ -1,149 +1,153 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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.2",
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
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.3',
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.
\\nOptional.
\\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.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
{
name: 'downmix',
tooltip: `Specify if downmixing should be used to create extra audio tracks.
\\nI.e if you have an 8ch but no 2ch or 6ch, create the missing audio tracks from the 8 ch.
\\nLikewise if you only have 6ch, create the missing 2ch from it. Optional.
\\nExample:\\n
true
\\nExample:\\n
false`,
},
\\nExample:\\n
false`,
},
],
};
}
function plugin(file, librarySettings, inputs) {
var response = {
const response = {
processFile: false,
container: "." + file.container,
container: `.${file.container}`,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "",
infoLog: '',
};
// Check if both inputs.aac_stereo AND inputs.downmix have been left empty. If they have then exit plugin.
if (inputs && inputs.aac_stereo == "" && inputs.downmix == "") {
response.infoLog +=
"☒Neither aac_stereo or downmix options have been configured within plugin settings, please configure required options. Skipping this plugin. \n";
if (inputs && inputs.aac_stereo === '' && inputs.downmix === '') {
response.infoLog += '☒Plugin has not been configured, 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";
if (file.fileMedium !== 'video') {
console.log('File is not video');
response.infoLog += '☒File is not video. \n';
response.processFile = false;
return response;
}
// Set up required variables.
var ffmpegCommandInsert = "";
var audioIdx = 0;
var has2Channel = false;
var has6Channel = false;
var has8Channel = false;
var convert = false;
let ffmpegCommandInsert = '';
let audioIdx = 0;
let has2Channel = false;
let has6Channel = false;
let has8Channel = false;
let convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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") {
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") {
if (file.ffProbeData.streams[i].channels === '6') {
has6Channel = true;
}
if (file.ffProbeData.streams[i].channels == "8") {
if (file.ffProbeData.streams[i].channels === '8') {
has8Channel = true;
}
}
} catch (err) {}
} catch (err) {
// Error
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is audio.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "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") {
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"
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";
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"
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";
response.infoLog += '☒Audio track is 6 channel, no 2 channel exists. Creating 2 channel from 6 channel. \n';
convert = true;
}
}
} catch (err) {}
} catch (err) {
// Error
}
// 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") {
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"
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";
response.infoLog += '☒Audio track is 2 channel but is not AAC. Converting. \n';
convert = true;
}
}
} catch (err) {}
audioIdx++;
} catch (err) {
// Error
}
audioIdx += 1;
}
}
// Convert file if convert variable is set to true.
if (convert == 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 9999 `;
} else {
response.infoLog += "☑File contains all required audio formats. \n";
response.infoLog += '☑File contains all required audio formats. \n';
response.processFile = false;
}
return response;

@ -1,185 +1,201 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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.2",
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.3',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js",
Tags: "pre-processing,ffmpeg,",
'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz6OrderStreams.js',
Tags: 'pre-processing,ffmpeg,',
};
}
function plugin(file) {
var response = {
const response = {
processFile: false,
preset: "",
container: "." + file.container,
preset: '',
container: `.${file.container}`,
handBrakeMode: false,
FFmpegMode: true,
infoLog: "",
infoLog: '',
};
// Set up required variables.
var ffmpegCommandInsert = "";
var videoIdx = 0;
var audioIdx = 0;
var audio2Idx = 0;
var audio6Idx = 0;
var audio8Idx = 0;
var subtitleIdx = 0;
var convert = false;
let ffmpegCommandInsert = '';
let audioIdx = 0;
let audio6Idx = 0;
let audio8Idx = 0;
let subtitleIdx = 0;
let convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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") {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'video') {
// Check if audioIdx or subtitleIdx do NOT equal 0
// If so 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";
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") {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
// Check if subtitleIdx does NOT equal 0.
// If so 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";
response.infoLog += '☒ Audio not second. \n';
}
// Increment audioIdx.
audioIdx++;
audioIdx += 1;
// 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") {
if (file.ffProbeData.streams[i].channels === '2') {
// Check if audio6Idx or audio8Idx do NOT equal 0.
// If so then it means a 6 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";
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") {
if (file.ffProbeData.streams[i].channels === '6') {
// Check if audio8Idx does NOT equal 0.
// If so 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";
response.infoLog += '☒ Audio 6ch not second. \n';
}
// Increment audio6Idx.
audio6Idx++;
audio6Idx += 1;
}
// Check if audio track is 8 channel.
if (file.ffProbeData.streams[i].channels == "8") {
if (file.ffProbeData.streams[i].channels === '8') {
// Increment audio8Idx.
audio8Idx++;
audio8Idx += 1;
}
}
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle') {
// Increment subtitleIdx
subtitleIdx++;
subtitleIdx += 1;
}
} catch (err) {}
} catch (err) {
// Error
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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"
file.ffProbeData.streams[i].codec_type.toLowerCase() === 'video'
&& file.ffProbeData.streams[i].codec_name.toLowerCase() !== 'mjpeg'
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
} catch (err) {
// Error
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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"
file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
&& file.ffProbeData.streams[i].channels === '2'
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
} catch (err) {
// Error
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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"
file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
&& file.ffProbeData.streams[i].channels === '6'
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
} catch (err) {
// Error
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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"
file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
&& file.ffProbeData.streams[i].channels === '8'
) {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
} catch (err) {
// Error
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let 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"
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) {}
} catch (err) {
// Error
}
}
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Check if stream is subtitle.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle') {
ffmpegCommandInsert += `-map 0:${i} `;
}
} catch (err) {}
} catch (err) {
// Error
}
}
// Convert file if convert variable is set to true.
if (convert == true) {
if (convert === true) {
response.processFile = true;
response.preset = `,${ffmpegCommandInsert} -c copy -max_muxing_queue_size 9999`;
response.reQueueAfter = true;
response.infoLog +=
"☒ Streams are out of order, reorganizing streams. Video, Audio, Subtitles. \n";
response.infoLog
+= '☒ Streams are out of order, reorganizing streams. Video, Audio, Subtitles. \n';
} else {
response.infoLog += "☑ Streams are in expected order. \n ";
response.infoLog += '☑ Streams are in expected order. \n ';
response.processFile = false;
}
return response;

@ -1,68 +1,68 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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.2",
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.3',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js",
Tags: "pre-processing,ffmpeg,video only",
'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 = {
function plugin(file, librarySettings) {
const response = {
processFile: false,
preset: "",
preset: '',
handBrakeMode: false,
container: "." + file.container,
container: `.${file.container}`,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "",
infoLog: '',
};
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") {
if (file.fileMedium !== 'video') {
response.processFile = false;
response.infoLog += "☒File is not a video. \n";
response.infoLog += '☒File is not a video. \n';
return response;
}
// Set up required variables.
var videoIdx = 0;
var extraArguments = "";
var convert = false;
let videoIdx = 0;
let extraArguments = '';
let convert = false;
// Go through each stream in the file.
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
// Check if stream is video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "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"
file.ffProbeData.streams[i].codec_name === 'mjpeg'
|| file.ffProbeData.streams[i].codec_name === 'png'
) {
convert = true;
extraArguments += `-map -v:${videoIdx} `;
}
// Increment videoIdx.
videoIdx++;
videoIdx += 1;
}
}
// Convert file if convert variable is set to true.
if (convert === true) {
response.preset += `,-map 0 -c copy -max_muxing_queue_size 9999 ${extraArguments}`;
response.infoLog += `☒File has image format stream, removing. \n`;
response.infoLog += '☒File has image format stream, removing. \n';
response.processFile = true;
} else {
response.processFile = false;
response.infoLog +=
"☑File doesn't contain any unwanted image format streams.\n";
response.infoLog
+= "☑File doesn't contain any unwanted image format streams.\n";
}
return response;
}

@ -1,95 +1,89 @@
/* eslint-disable */
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
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",
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.2',
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: `
Enter the IP address/URL for autoscan. Must include http(s)://
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
http://192.168.0.10
\\nExample:\\n
https://subdomain.domain.tld`,
},
{
name: "autoscan_port",
tooltip: `
Enter the port Autoscan is using, default is 3468
\\nExample:\\n
https://subdomain.domain.tld`,
},
{
name: 'autoscan_port',
tooltip: `
Enter the port Autoscan is using, default is 3468
\\nExample:\\n
3468`,
},
{
name: "autoscan_passkey",
tooltip: `
\\nExample:\\n
3468`,
},
{
name: 'autoscan_passkey',
tooltip: `
Enter the autoscan passkey.
Enter the autoscan passkey.
\\nExample:\\n
9c4b81fe234e4d6eb9011cefe514d915`,
},
\\nExample:\\n
9c4b81fe234e4d6eb9011cefe514d915`,
},
],
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
// Set up required variables.
const request = require('request');
const ADDRESS = inputs.autoscan_address;
const PORT = inputs.autoscan_port;
const PASSKEY = inputs.autoscan_passkey;
let filepath = '';
const response = '';
filepath = `${file.file}`;
// 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 == ""
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.infoLog += '☒Plugin options have not been configured, please configure 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;
// 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}`,
},
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);
},
(error, res, body) => {
if (error) {
console.error(error);
}
);
console.log(`statusCode: ${res.statusCode}`);
console.log(body);
});
console.log("request next");
console.log('request next');
console.log(request.post);
};

Loading…
Cancel
Save