Merge pull request #1 from HaveAGitGat/master

catch up
This commit is contained in:
3n8 2020-12-29 18:25:43 +01:00 committed by GitHub
commit 613febe0a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
110 changed files with 4117 additions and 156167 deletions

30
.eslintrc.json Normal file
View File

@ -0,0 +1,30 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": [
"airbnb-base"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"class-methods-use-this": 0,
"no-case-declarations": 0,
"camelcase": 0,
"jsx-a11y/click-events-have-key-events": 0,
"no-underscore-dangle": ["error", { "allow": ["_id"] }],
"max-len": [
"error",
{
"code": 120
}
]
}
}

25
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Node.js CI
on:
push:
branches: ['**']
pull_request:
branches: ['**']
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x, 14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm i
- run: npm run lint

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

View File

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

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_075a_FFMPEG_HEVC_Generic", id: "Tdarr_Plugin_075a_FFMPEG_HEVC_Generic",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_075a_Transcode_Customisable", id: "Tdarr_Plugin_075a_Transcode_Customisable",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_075b_FFMPEG_HEVC_Generic_Video_Audio_Only", id: "Tdarr_Plugin_075b_FFMPEG_HEVC_Generic_Video_Audio_Only",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_075c_FFMPEG_HEVC_Generic_Video_Audio_Only_CRF20", id: "Tdarr_Plugin_075c_FFMPEG_HEVC_Generic_Video_Audio_Only_CRF20",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_075d_FFMPEG_HEVC_GPU_Generic_Video_Audio_Only_CRF20", id: "Tdarr_Plugin_075d_FFMPEG_HEVC_GPU_Generic_Video_Audio_Only_CRF20",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_076a_re_order_audio_streams", id: "Tdarr_Plugin_076a_re_order_audio_streams",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_076b_re_order_subtitle_streams", id: "Tdarr_Plugin_076b_re_order_subtitle_streams",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_077b_HandBrake_NVENC_264_Configurable", id: "Tdarr_Plugin_077b_HandBrake_NVENC_264_Configurable",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_078d_Output_embedded_subs_to_SRT_and_remove", id: "Tdarr_Plugin_078d_Output_embedded_subs_to_SRT_and_remove",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_43az_add_to_radarr", id: "Tdarr_Plugin_43az_add_to_radarr",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_A47j_FFMPEG_NVENC_HEVC_Video_Only", id: "Tdarr_Plugin_A47j_FFMPEG_NVENC_HEVC_Video_Only",
@ -175,7 +176,7 @@ function plugin(file,librarySettings,inputs,otherArguments) {
// -------------------------------- METADATA UPDATES -------------------------------- // -------------------------------- METADATA UPDATES --------------------------------
// If there is no _STATISTICS_WRITING_DATE_UTC-eng field, then we need to run mkvpropedit and // If there is no _STATISTICS_WRITING_DATE_UTC-eng field, then we need to run mkvpropedit and
// rerun mediainfo to load the stats. // rerun mediainfo to load the stats.
if (file.ffProbeData.streams[0].tags["_STATISTICS_WRITING_DATE_UTC-eng"] === undefined ) { if (file.ffProbeData.streams[0].tags === undefined || file.ffProbeData.streams[0].tags["_STATISTICS_WRITING_DATE_UTC-eng"] === undefined ) {
response.infoLog += "☑Track statistics are missing.\n"; response.infoLog += "☑Track statistics are missing.\n";
updateTrackStats(file); updateTrackStats(file);
getMediaInfo(file); getMediaInfo(file);

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_DOOM_NVENC_Tiered_MKV_CleanAll", id: "Tdarr_Plugin_DOOM_NVENC_Tiered_MKV_CleanAll",
@ -194,7 +195,7 @@ function loopOverStreamsOfType(file, type, method) {
} }
/** /**
* Converts all multi channel audio streams to AC3. * Removes audio tracks that aren't in the allowed languages or labeled as Commentary tracks.
*/ */
function buildAudioConfiguration(inputs, file, logger) { function buildAudioConfiguration(inputs, file, logger) {
var configuration = new Configurator(["-c:a copy"]); var configuration = new Configurator(["-c:a copy"]);
@ -202,7 +203,7 @@ function buildAudioConfiguration(inputs, file, logger) {
var streams_removing = 0; var streams_removing = 0;
var languages = inputs.audio_language.split(","); var languages = inputs.audio_language.split(",");
loopOverStreamsOfType(file, "audio", function (stream, id) { loopOverStreamsOfType(file, "audio", function (stream, id) {
stream_count++; stream_count++;
if ("tags" in stream && "title" in stream.tags && inputs.audio_commentary.toLowerCase() == "true") { if ("tags" in stream && "title" in stream.tags && inputs.audio_commentary.toLowerCase() == "true") {
if ( if (
stream.tags.title.toLowerCase().includes("commentary") || stream.tags.title.toLowerCase().includes("commentary") ||
@ -216,12 +217,12 @@ function buildAudioConfiguration(inputs, file, logger) {
); );
} }
} }
if ("tags" in stream) { if ("tags" in stream) {
// Remove unwated languages // Remove unwanted languages
if ("language" in stream.tags) { if ("language" in stream.tags) {
if (languages.indexOf(stream.tags.language.toLowerCase()) === -1) { if (languages.indexOf(stream.tags.language.toLowerCase()) === -1) {
configuration.AddOutputSetting(`-map -0:a:${id}`); configuration.AddOutputSetting(`-map -0:a:${id}`);
streams_removing++; streams_removing++;
logger.AddError( logger.AddError(
`Removing audio track in language ${stream.tags.language}` `Removing audio track in language ${stream.tags.language}`
); );

View File

@ -1,3 +1,4 @@
/* eslint-disable */
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Author: JarBinks, Zachg99, Jeff47 // Author: JarBinks, Zachg99, Jeff47

View File

@ -1,3 +1,4 @@
/* eslint-disable */
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Author: JarBinks, Zachg99, Jeff47 // Author: JarBinks, Zachg99, Jeff47

View File

@ -1,233 +1,292 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MC93_Migz1FFMPEG", id: 'Tdarr_Plugin_MC93_Migz1FFMPEG',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "Migz-Transcode Using Nvidia GPU & FFMPEG", Name: 'Migz-Transcode Using Nvidia GPU & FFMPEG',
Type: "Video", Type: 'Video',
Operation: "Transcode", Operation: 'Transcode',
Description: `Files not in H265 will be transcoded into H265 using Nvidia GPU with ffmpeg, settings are dependant on file bitrate, working by the logic that H265 can support the same ammount of data at half the bitrate of H264. NVDEC & NVENC compatable GPU required. \n\n`, Description: `Files not in H265 will be transcoded into H265 using Nvidia GPU with ffmpeg.
Version: "2.5", \\n Settings are dependant on file bitrate
Link: \\n Working by the logic that H265 can support the same ammount of data at half the bitrate of H264.
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js", \\n NVDEC & NVENC compatable GPU required.
Tags: "pre-processing,ffmpeg,video only,nvenc h265,configurable", \\n This plugin will skip any files that are in the VP9 codec. \n\n`,
Inputs: [ Version: '3.0',
{ Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js',
name: "container", Tags: 'pre-processing,ffmpeg,video only,nvenc h265,configurable',
tooltip: `Specify output container of file, ensure that all stream types you may have are supported by your chosen container. mkv is recommended. Inputs: [{
\\nExample:\\n name: 'container',
mkv 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 \\nExample:\\n
mp4`, mp4`,
}, },
{ {
name: "bitrate_cutoff", name: 'bitrate_cutoff',
tooltip: `Specify bitrate cutoff, files with a current bitrate lower then this will not be transcoded. Rate is in kbps. Leave empty to disable. tooltip: `Specify bitrate cutoff, files with a current bitrate lower then this will not be transcoded.
\\nExample:\\n \\n Rate is in kbps.
6000 \\n Leave empty to disable.
\\nExample:\\n
6000
\\nExample:\\n \\nExample:\\n
4000`, 4000`,
}, },
{ {
name: "enable_10bit", name: 'enable_10bit',
tooltip: `Specify if output file should be 10bit. Default is false. tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
{ {
name: "force_conform", name: 'enable_bframes',
tooltip: `Make the file conform to output containers requirements. tooltip: `Specify if b frames should be used.
\\n Drop hdmv_pgs_subtitle/eia_608/subrip subtitles for MP4. \\n Using B frames should decrease file sizes but are only supported on newer GPUs.
\\n Drop data streams and mov_text/eia_608 subtitles for MKV. \\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. \\n Default is false.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
], ],
}; };
} }
function plugin(file, librarySettings, inputs) { function plugin(file, librarySettings, inputs) {
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: true, FFmpegMode: true,
reQueueAfter: true, reQueueAfter: true,
infoLog: "", infoLog: '',
}; };
let duration = '';
// Check if inputs.container has been configured. If it hasn't then exit plugin. // Check if inputs.container has been configured. If it hasn't then exit plugin.
if (inputs.container == "") { if (inputs.container === '') {
response.infoLog += response.infoLog += 'Plugin has not been configured, please configure required options. Skipping this plugin. \n';
"☒Container has not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false; response.processFile = false;
return response; return response;
} else {
response.container = "." + inputs.container;
} }
response.container = `.${inputs.container}`;
// Check if file is a video. If it isn't then exit plugin. // 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.processFile = false;
response.infoLog += "☒File is not a video. \n"; response.infoLog += 'File is not a video. \n';
return response; 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. // Check if duration info is filled, if so times it by 0.0166667 to get time in minutes.
if (typeof file.meta.Duration != "undefined") { // If not filled then get duration of stream 0 and do the same.
var duration = file.meta.Duration * 0.0166667; if (typeof file.meta.Duration !== 'undefined') {
duration = file.meta.Duration * 0.0166667;
} else { } else {
var duration = file.ffProbeData.streams[0].duration * 0.0166667; duration = file.ffProbeData.streams[0].duration * 0.0166667;
} }
// Set up required variables. // Set up required variables.
var videoIdx = 0; let videoIdx = 0;
var CPU10 = false; let CPU10 = false;
var extraArguments = ""; let extraArguments = '';
var bitrateSettings = ""; 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/ // Work out currentBitrate using "Bitrate = file size / (number of minutes * .0075)"
var currentBitrate = ~~(file.file_size / (duration * 0.0075)); // Used from here https://blog.frame.io/2017/03/06/calculate-video-bitrates/
// 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. // eslint-disable-next-line no-bitwise
var targetBitrate = ~~(file.file_size / (duration * 0.0075) / 2); 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.
// eslint-disable-next-line no-bitwise
const targetBitrate = ~~(file.file_size / (duration * 0.0075) / 2);
// Allow some leeway under and over the targetBitrate. // Allow some leeway under and over the targetBitrate.
var minimumBitrate = ~~(targetBitrate * 0.7); // eslint-disable-next-line no-bitwise
var maximumBitrate = ~~(targetBitrate * 1.3); const minimumBitrate = ~~(targetBitrate * 0.7);
// eslint-disable-next-line no-bitwise
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 comes out as 0 then something has gone wrong and bitrates could not be calculated.
if (targetBitrate == "0") { // Cancel plugin completely.
if (targetBitrate === 0) {
response.processFile = false; response.processFile = false;
response.infoLog += response.infoLog += 'Target bitrate could not be calculated. Skipping this plugin. \n';
"☒Target bitrate could not be calculated. Skipping this plugin. \n";
return response; return response;
} }
// Check if inputs.bitrate cutoff has something entered (Entered means user actually wants something to happen, empty would disable this). // Check if inputs.bitrate cutoff has something entered.
if (inputs.bitrate_cutoff != "") { // (Entered means user actually wants something to happen, empty would disable this).
// Checks if currentBitrate is below inputs.bitrate_cutoff, if so then cancel plugin without touching original files. 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) { if (currentBitrate <= inputs.bitrate_cutoff) {
response.processFile = false; 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; 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. // Check if force_conform option is checked.
if (inputs.force_conform == "true") { // If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.container.toLowerCase() == "mkv") { if (inputs.force_conform === 'true') {
extraArguments += `-map -0:d `; if (inputs.container.toLowerCase() === 'mkv') {
for (var i = 0; i < file.ffProbeData.streams.length; i++) { extraArguments += '-map -0:d ';
if ( for (let i = 0; i < file.ffProbeData.streams.length; i++) {
file.ffProbeData.streams[i].codec_name try {
.toLowerCase() == "mov_text" || if (
file.ffProbeData.streams[i].codec_name file.ffProbeData.streams[i].codec_name
.toLowerCase() == "eia_608" .toLowerCase() === 'mov_text'
) { || file.ffProbeData.streams[i].codec_name
extraArguments += `-map -0:${i} `; .toLowerCase() === 'eia_608'
} || file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
} }
}
} }
if (inputs.container.toLowerCase() == "mp4") { if (inputs.container.toLowerCase() === 'mp4') {
for (var i = 0; i < file.ffProbeData.streams.length; i++) { for (let i = 0; i < file.ffProbeData.streams.length; i++) {
if ( try {
file.ffProbeData.streams[i].codec_name if (
.toLowerCase() == "hdmv_pgs_subtitle" || file.ffProbeData.streams[i].codec_name
file.ffProbeData.streams[i].codec_name .toLowerCase() === 'hdmv_pgs_subtitle'
.toLowerCase() == "eia_608" || || file.ffProbeData.streams[i].codec_name
file.ffProbeData.streams[i].codec_name .toLowerCase() === 'eia_608'
.toLowerCase() == "subrip" || file.ffProbeData.streams[i].codec_name
) { .toLowerCase() === 'subrip'
extraArguments += `-map -0:${i} `; || file.ffProbeData.streams[i].codec_name
} .toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
} }
}
} }
} }
// Check if 10bit variable is true. // Check if 10bit variable is true.
if (inputs.enable_10bit == "true") { if (inputs.enable_10bit === 'true') {
// If set to true then add 10bit argument // 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 set to true then add b frames argument
extraArguments += '-bf 5 ';
} }
// Go through each stream in the file. // 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. // Check if stream is a video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "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. // Check if codec of stream is mjpeg/png, if so then remove this "video" stream.
if (file.ffProbeData.streams[i].codec_name == "mjpeg" || file.ffProbeData.streams[i].codec_name == "png") { // 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} `; extraArguments += `-map -v:${videoIdx} `;
} }
// Check if codec of stream is hevc AND check if file.container matches inputs.container. If so nothing for plugin to do. // 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 ( if (
file.ffProbeData.streams[i].codec_name == "hevc" && (
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.processFile = false;
response.infoLog += `☑File is already hevc & in ${inputs.container}. \n`; response.infoLog += `File is already hevc or vp9 & in ${inputs.container}. \n`;
return response; return response;
} }
// Check if codec of stream is hevc 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 ( if (
file.ffProbeData.streams[i].codec_name == "hevc" && (
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 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.preset = `, -map 0 -c copy ${extraArguments}`;
response.processFile = true; response.processFile = true;
return response; return response;
} }
// Check if video stream is HDR or 10bit // 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" ) { if (
CPU10 = true file.ffProbeData.streams[i].profile === 'High 10'
|| file.ffProbeData.streams[i].bits_per_raw_sample === '10'
) {
CPU10 = true;
} }
// Increment videoIdx. // Increment videoIdx.
videoIdx++; videoIdx += 1;
} }
} }
// Set bitrateSettings variable using bitrate information calulcated earlier. // Set bitrateSettings variable using bitrate information calulcated earlier.
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`; bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k `
+ `-maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`;
// Print to infoLog information around file & bitrate settings. // Print to infoLog information around file & bitrate settings.
response.infoLog += `Container for output selected as ${ response.infoLog += `Container for output selected as ${inputs.container}. \n`;
inputs.container response.infoLog += `Current bitrate = ${currentBitrate} \n`;
}. \n Current bitrate = ${~~( response.infoLog += 'Bitrate settings: \n';
file.file_size / response.infoLog += `Target = ${targetBitrate} \n`;
(duration * 0.0075) response.infoLog += `Minimum = ${minimumBitrate} \n`;
)} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n`; response.infoLog += `Maximum = ${maximumBitrate} \n`;
// Codec will be checked so it can be transcoded correctly // Codec will be checked so it can be transcoded correctly
if (file.video_codec_name == "h263") { if (file.video_codec_name === 'h263') {
response.preset = `-c:v h263_cuvid`; response.preset = '-c:v h263_cuvid';
} else if (file.video_codec_name == "h264") { } else if (file.video_codec_name === 'h264') {
if (CPU10 == false) { if (CPU10 === false) {
response.preset = `-c:v h264_cuvid`; response.preset = '-c:v h264_cuvid';
} }
} else if (file.video_codec_name == "mjpeg") { } else if (file.video_codec_name === 'mjpeg') {
response.preset = `c:v mjpeg_cuvid`; response.preset = 'c:v mjpeg_cuvid';
} else if (file.video_codec_name == "mpeg1") { } else if (file.video_codec_name === 'mpeg1') {
response.preset = `-c:v mpeg1_cuvid`; response.preset = '-c:v mpeg1_cuvid';
} else if (file.video_codec_name == "mpeg2") { } else if (file.video_codec_name === 'mpeg2') {
response.preset = `-c:v mpeg2_cuvid`; response.preset = '-c:v mpeg2_cuvid';
} else if (file.video_codec_name == "vc1") { } else if (file.video_codec_name === 'vc1') {
response.preset = `-c:v vc1_cuvid`; response.preset = '-c:v vc1_cuvid';
} else if (file.video_codec_name == "vp8") { } else if (file.video_codec_name === 'vp8') {
response.preset = `-c:v vp8_cuvid`; response.preset = '-c:v vp8_cuvid';
} else if (file.video_codec_name == "vp9") {
response.preset = `-c:v vp9_cuvid`;
} }
response.preset += `,-map 0 -c:v hevc_nvenc -rc:v vbr_hq -cq:v 19 ${bitrateSettings} -spatial_aq:v 1 -rc-lookahead:v 32 -c:a copy -c:s copy -max_muxing_queue_size 4096 ${extraArguments}`; response.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.processFile = true;
response.infoLog += `☒File is not hevc. Transcoding. \n`; response.infoLog += 'File is not hevc or vp9. Transcoding. \n';
return response; return response;
} }
module.exports.details = details; module.exports.details = details;

View File

@ -1,205 +1,242 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MC93_Migz1FFMPEG_CPU", id: 'Tdarr_Plugin_MC93_Migz1FFMPEG_CPU',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "Migz-Transcode Using CPU & FFMPEG", Name: 'Migz-Transcode Using CPU & FFMPEG',
Type: "Video", Type: 'Video',
Operation: "Transcode", Operation: 'Transcode',
Description: `Files not in H265 will be transcoded into H265 using CPU with ffmpeg, settings are dependant on file bitrate, working by the logic that H265 can support the same ammount of data at half the bitrate of H264. \n\n`, Description: `Files not in H265 will be transcoded into H265 using Nvidia GPU with ffmpeg.
Version: "1.4", \\n Settings are dependant on file bitrate
Link: \\n Working by the logic that H265 can support the same ammount of data at half the bitrate of H264.
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js", \\n This plugin will skip any files that are in the VP9 codec. \n\n`,
Tags: "pre-processing,ffmpeg,video only,configurable,h265", Version: '1.9',
Inputs: [ Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz1FFMPEG_CPU.js',
{ Tags: 'pre-processing,ffmpeg,video only,configurable,h265',
name: "container", Inputs: [{
tooltip: `Specify output container of file, ensure that all stream types you may have are supported by your chosen container. mkv is recommended. name: 'container',
\\nExample:\\n tooltip: `Specify output container of file.
mkv \\n Ensure that all stream types you may have are supported by your chosen container.
\\n mkv is recommended.
\\nExample:\\n
mkv
\\nExample:\\n \\nExample:\\n
mp4`, mp4`,
}, },
{ {
name: "bitrate_cutoff", name: 'bitrate_cutoff',
tooltip: `Specify bitrate cutoff, files with a current bitrate lower then this will not be transcoded. Rate is in kbps. Leave empty to disable. tooltip: `Specify bitrate cutoff, files with a current bitrate lower then this will not be transcoded.
\\nExample:\\n \\n Rate is in kbps.
6000 \\n Leave empty to disable.
\\nExample:\\n
6000
\\nExample:\\n \\nExample:\\n
4000`, 4000`,
}, },
{ {
name: "enable_10bit", name: 'enable_10bit',
tooltip: `Specify if output file should be 10bit. Default is false. tooltip: `Specify if output file should be 10bit. Default is false.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
{ {
name: "force_conform", name: 'force_conform',
tooltip: `Make the file conform to output containers requirements. tooltip: `Make the file conform to output containers requirements.
\\n Drop hdmv_pgs_subtitle/eia_608/subrip subtitles for MP4. \\n Drop hdmv_pgs_subtitle/eia_608/subrip/timed_id3 for MP4.
\\n Drop data streams and mov_text/eia_608 subtitles for MKV. \\n Drop data streams/mov_text/eia_608/timed_id3 for MKV.
\\n Default is false. \\n Default is false.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
], ],
}; };
} }
function plugin(file, librarySettings, inputs) { function plugin(file, librarySettings, inputs) {
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: true, FFmpegMode: true,
reQueueAfter: true, reQueueAfter: true,
infoLog: "", infoLog: '',
}; };
let duration = '';
// Check if inputs.container has been configured. If it hasn't then exit plugin. // Check if inputs.container has been configured. If it hasn't then exit plugin.
if (!inputs || inputs.container == "") { if (inputs.container === '') {
response.infoLog += response.infoLog += 'Plugin has not been configured, please configure required options. Skipping this plugin. \n';
"☒Container has not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false; response.processFile = false;
return response; return response;
} else {
response.container = "." + inputs.container;
} }
response.container = `.${inputs.container}`;
// Check if file is a video. If it isn't then exit plugin. // 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.processFile = false;
response.infoLog += "☒File is not a video. \n"; response.infoLog += 'File is not a video. \n';
return response; 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. // Check if duration info is filled, if so times it by 0.0166667 to get time in minutes.
if (typeof file.meta.Duration != "undefined") { // If not filled then get duration of stream 0 and do the same.
var duration = file.meta.Duration * 0.0166667; if (typeof file.meta.Duration !== 'undefined') {
duration = file.meta.Duration * 0.0166667;
} else { } else {
var duration = file.ffProbeData.streams[0].duration * 0.0166667; duration = file.ffProbeData.streams[0].duration * 0.0166667;
} }
// Set up required variables. // Set up required variables.
var videoIdx = -1; let videoIdx = -1;
var extraArguments = ""; let extraArguments = '';
var bitrateSettings = ""; 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/ // Work out currentBitrate using "Bitrate = file size / (number of minutes * .0075)"
var currentBitrate = ~~(file.file_size / (duration * 0.0075)); // Used from here https://blog.frame.io/2017/03/06/calculate-video-bitrates/
// 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. // eslint-disable-next-line no-bitwise
var targetBitrate = ~~(file.file_size / (duration * 0.0075) / 2); 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.
// eslint-disable-next-line no-bitwise
const targetBitrate = ~~(file.file_size / (duration * 0.0075) / 2);
// Allow some leeway under and over the targetBitrate. // Allow some leeway under and over the targetBitrate.
var minimumBitrate = ~~(targetBitrate * 0.7); // eslint-disable-next-line no-bitwise
var maximumBitrate = ~~(targetBitrate * 1.3); const minimumBitrate = ~~(targetBitrate * 0.7);
// eslint-disable-next-line no-bitwise
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 comes out as 0 then something has gone wrong and bitrates could not be calculcated.
if (targetBitrate == "0") { // Cancel plugin completely.
if (targetBitrate === 0) {
response.processFile = false; response.processFile = false;
response.infoLog += response.infoLog += 'Target bitrate could not be calculated. Skipping this plugin. \n';
"☒Target bitrate could not be calculated. Skipping this plugin. \n";
return response; return response;
} }
// Check if inputs.bitrate cutoff has something entered (Entered means user actually wants something to happen, empty would disable this). // Check if inputs.bitrate cutoff has something entered.
if (inputs.bitrate_cutoff != "") { // (Entered means user actually wants something to happen, empty would disable this).
// Checks if currentBitrate is below inputs.bitrate_cutoff, if so then cancel plugin without touching original files. 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) { if (currentBitrate <= inputs.bitrate_cutoff) {
response.processFile = false; 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; 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. // Check if force_conform option is checked.
if (inputs.force_conform == "true") { // If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.container.toLowerCase() == "mkv") { if (inputs.force_conform === 'true') {
extraArguments += `-map -0:d `; if (inputs.container.toLowerCase() === 'mkv') {
for (var i = 0; i < file.ffProbeData.streams.length; i++) { extraArguments += '-map -0:d ';
if ( for (let i = 0; i < file.ffProbeData.streams.length; i++) {
file.ffProbeData.streams[i].codec_name try {
.toLowerCase() == "mov_text" || if (
file.ffProbeData.streams[i].codec_name file.ffProbeData.streams[i].codec_name
.toLowerCase() == "eia_608" .toLowerCase() === 'mov_text'
) { || file.ffProbeData.streams[i].codec_name
extraArguments += `-map -0:${i} `; .toLowerCase() === 'eia_608'
} || file.ffProbeData.streams[i].codec_name
.toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
} }
}
} }
if (inputs.container.toLowerCase() == "mp4") { if (inputs.container.toLowerCase() === 'mp4') {
for (var i = 0; i < file.ffProbeData.streams.length; i++) { for (let i = 0; i < file.ffProbeData.streams.length; i++) {
if ( try {
file.ffProbeData.streams[i].codec_name if (
.toLowerCase() == "hdmv_pgs_subtitle" || file.ffProbeData.streams[i].codec_name
file.ffProbeData.streams[i].codec_name .toLowerCase() === 'hdmv_pgs_subtitle'
.toLowerCase() == "eia_608" || || file.ffProbeData.streams[i].codec_name
file.ffProbeData.streams[i].codec_name .toLowerCase() === 'eia_608'
.toLowerCase() == "subrip" || file.ffProbeData.streams[i].codec_name
) { .toLowerCase() === 'subrip'
extraArguments += `-map -0:${i} `; || file.ffProbeData.streams[i].codec_name
} .toLowerCase() === 'timed_id3'
) {
extraArguments += `-map -0:${i} `;
}
} catch (err) {
// Error
} }
}
} }
} }
// Check if 10bit variable is true. // Check if 10bit variable is true.
if (inputs.enable_10bit == "true") { if (inputs.enable_10bit === 'true') {
// If set to true then add 10bit argument // If set to true then add 10bit argument
extraArguments += `-pix_fmt p010le `; extraArguments += '-pix_fmt p010le ';
} }
// Go through each stream in the file. // 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. // Check if stream is a video.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "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. // Check if codec of stream is mjpeg/png.
if (file.ffProbeData.streams[i].codec_name == "mjpeg" || file.ffProbeData.streams[i].codec_name == "png") { // If so then remove this "video" stream.
extraArguments += `-map -v:${videoIdx} `; // 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') {
// Check if codec of stream is hevc AND check if file.container matches inputs.container. If so nothing for plugin to do. 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 ( if (
file.ffProbeData.streams[i].codec_name == "hevc" && (file.ffProbeData.streams[i].codec_name === 'hevc' || file.ffProbeData.streams[i].codec_name === 'vp9')
file.container == inputs.container && file.container === `${inputs.container}`
) { ) {
response.processFile = false; response.processFile = false;
response.infoLog += `File is already hevc & in ${inputs.container}. \n`; response.infoLog += `File is already hevc or vp9 & in ${inputs.container}. \n`;
return response; return response;
} }
// Check if codec of stream is hevc 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 ( if (
file.ffProbeData.streams[i].codec_name == "hevc" && (file.ffProbeData.streams[i].codec_name === 'hevc' || file.ffProbeData.streams[i].codec_name === 'vp9')
file.container != "${inputs.container}" && file.container !== `${inputs.container}`
) { ) {
response.infoLog += `File is hevc 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.preset = `, -map 0 -c copy ${extraArguments}`;
response.processFile = true; response.processFile = true;
return response; return response;
} }
// Increment videoIdx. // Increment videoIdx.
videoIdx++; videoIdx += 1;
} }
} }
// Set bitrateSettings variable using bitrate information calulcated earlier. // Set bitrateSettings variable using bitrate information calulcated earlier.
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`; bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k `
+ `-maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`;
// Print to infoLog information around file & bitrate settings. // Print to infoLog information around file & bitrate settings.
response.infoLog += `Container for output selected as ${ response.infoLog += `Container for output selected as ${inputs.container}. \n`;
inputs.container response.infoLog += `Current bitrate = ${currentBitrate} \n`;
}. \n Current bitrate = ${~~( response.infoLog += 'Bitrate settings: \n';
file.file_size / response.infoLog += `Target = ${targetBitrate} \n`;
(duration * 0.0075) response.infoLog += `Minimum = ${minimumBitrate} \n`;
)} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n`; response.infoLog += `Maximum = ${maximumBitrate} \n`;
response.preset += `,-map 0 -c:v libx265 ${bitrateSettings} -c:a copy -c:s copy -max_muxing_queue_size 4096 ${extraArguments}`; response.preset += `,-map 0 -c:v libx265 ${bitrateSettings} `
+ `-c:a copy -c:s copy -max_muxing_queue_size 9999 ${extraArguments}`;
response.processFile = true; response.processFile = true;
response.infoLog += `☒File is not hevc. Transcoding. \n`; response.infoLog += 'File is not hevc or vp9. Transcoding. \n';
return response; return response;
} }
module.exports.details = details; module.exports.details = details;

View File

@ -0,0 +1,132 @@
/* 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;
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

View File

@ -1,123 +1,194 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MC93_Migz2CleanTitle", id: 'Tdarr_Plugin_MC93_Migz2CleanTitle',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "Migz-Clean title metadata", Name: 'Migz-Clean title metadata',
Type: "Video", Type: 'Video',
Operation: "Clean", 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`, Description: 'This plugin removes title metadata from video/audio/subtitles.\n\n',
Version: "1.2", Version: '1.9',
Link: Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js',
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz2CleanTitle.js", Tags: 'pre-processing,ffmpeg,configurable',
Tags: "pre-processing,ffmpeg,configurable", Inputs: [{
Inputs: [ name: 'clean_audio',
{ tooltip: `Specify if audio titles should be checked & cleaned. Optional.
name: "clean_audio", \\nExample:\\n
tooltip: `Specify if audio titles should be checked & cleaned. Optional. true
\\nExample:\\n
true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
{ {
name: "clean_subtitles", name: 'clean_subtitles',
tooltip: `Specify if subtitle titles should be checked & cleaned. Optional. tooltip: `Specify if subtitle titles should be checked & cleaned. Optional.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, 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!`,
},
], ],
}; };
} }
function plugin(file, librarySettings, inputs) { function plugin(file, librarySettings, inputs) {
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
container: "." + file.container, container: `.${file.container}`,
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: true, FFmpegMode: true,
reQueueAfter: false, reQueueAfter: false,
infoLog: "", infoLog: '',
}; };
// Set up required variables. // Set up required variables.
var ffmpegCommandInsert = "";
var videoIdx = 0; let ffmpegCommandInsert = '';
var audioIdx = 0; let videoIdx = 0;
var subtitleIdx = 0; let audioIdx = 0;
var convert = false; 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') {
custom_title_matching = inputs.custom_title_matching.toLowerCase().split(',');
}
// Check if file is a video. If it isn't then exit plugin. // Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
response.infoLog += "☒File is not video \n"; console.log('File is not video');
response.infoLog += '☒File is not video \n';
response.processFile = false; response.processFile = false;
return response; return response;
} }
// Check if overall file metadata title is not empty, if it's not empty set to "". // 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 { try {
ffmpegCommandInsert += ` -metadata title="" `; ffmpegCommandInsert += ' -metadata title="" ';
convert = true; convert = true;
} catch (err) {} } catch (err) {
// Error
}
}
// Go through each stream in the file. // 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 a video.
// Check if stream is a video. if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'video') {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "video") { try {
// Check if stream title is not empty, if it's nto empty set to "". // Check if stream title is not empty, if it's not empty set to "".
if (typeof file.ffProbeData.streams[i].tags.title != "undefined") { if (typeof file.ffProbeData.streams[i].tags.title !== 'undefined') {
response.infoLog += `☒Video stream title is not empty, most likely junk metadata. Removing title from stream ${i} \n`; response.infoLog += `☒Video stream title is not empty. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:v:${videoIdx} title="" `; ffmpegCommandInsert += ` -metadata:s:v:${videoIdx} title="" `;
convert = true; convert = true;
} }
// Increment videoIdx. // 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. // Check if title metadata of audio stream has more then 3 full stops.
if ( // If so then it's likely to be junk metadata so remove.
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && // Then check if any audio streams match with user input custom_title_matching variable, if so then remove.
inputs.clean_audio.toLowerCase() == "true" if (
) { file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
if (file.ffProbeData.streams[i].tags.title.split(".").length - 1 > 3) { && inputs.clean_audio.toLowerCase() === 'true'
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="" `; try {
convert = 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 in audio title. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:a:${audioIdx} title="" `;
convert = true;
} 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. // Increment audioIdx.
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. // Check if title metadata of subtitle stream has more then 3 full stops.
if ( // If so then it's likely to be junk metadata so remove.
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" && // Then check if any streams match with user input custom_title_matching variable, if so then remove.
inputs.clean_subtitles.toLowerCase() == "true" if (
) { file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle'
if (file.ffProbeData.streams[i].tags.title.split(".").length - 1 > 3) { && inputs.clean_subtitles.toLowerCase() === 'true'
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="" `; try {
convert = 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 in subtitle title. Removing title from stream ${i} \n`;
ffmpegCommandInsert += ` -metadata:s:s:${subtitleIdx} title="" `;
convert = true;
} 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. // Increment subtitleIdx.
subtitleIdx++; subtitleIdx += 1;
} catch (err) {
// Error
} }
} catch (err) {} }
}
// Convert file if convert variable is set to true. // Convert file if convert variable is set to true.
if (convert == true) { if (convert === true) {
response.infoLog += "☒File has title metadata. Removing \n"; response.infoLog += '☒File has title metadata. Removing \n';
response.preset = `,${ffmpegCommandInsert} -c copy -map 0 -max_muxing_queue_size 4096`; response.preset = `,${ffmpegCommandInsert} -c copy -map 0 -max_muxing_queue_size 9999`;
response.reQueueAfter = true; response.reQueueAfter = true;
response.processFile = true; response.processFile = true;
} else { } else {
response.infoLog += "☑File has no title metadata \n"; response.infoLog += '☑File has no title metadata \n';
} }
return response; return response;
} }

View File

@ -1,140 +1,154 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MC93_Migz3CleanAudio", id: 'Tdarr_Plugin_MC93_Migz3CleanAudio',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "Migz-Clean audio streams", Name: 'Migz-Clean audio streams',
Type: "Audio", Type: 'Audio',
Operation: "Clean", Operation: 'Clean',
Description: `This plugin keeps only specified language audio tracks & can tags those that have an unknown language. \n\n`, Description: 'This plugin keeps only specified language tracks & can tags tracks with an unknown language. \n\n',
Version: "2.2", Version: '2.4',
Link: Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js',
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz3CleanAudio.js", Tags: 'pre-processing,ffmpeg,audio only,configurable',
Tags: "pre-processing,ffmpeg,audio only,configurable", Inputs: [{
Inputs: [ name: 'language',
{ tooltip: `Specify language tag/s here for the audio tracks you'd like to keep
name: "language", \\nRecommended to keep "und" as this stands for undertermined
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 \\nSome files may not have the language specified.
\\nExample:\\n \\nMust follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
eng \\nExample:\\n
eng
\\nExample:\\n \\nExample:\\n
eng,und eng,und
\\nExample:\\n \\nExample:\\n
eng,und,jap`, eng,und,jap`,
}, },
{ {
name: "commentary", name: 'commentary',
tooltip: `Specify if audio tracks that contain commentary/description should be removed. tooltip: `Specify if audio tracks that contain commentary/description should be removed.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
{ {
name: "tag_language", name: 'tag_language',
tooltip: `Specify a single language for audio tracks with no language or unknown language to be tagged with, leave empty to disable, you must have "und" in your list of languages to keep for this to function. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes tooltip: `Specify a single language for audio tracks with no language or unknown language to be tagged with.
\\nExample:\\n \\nYou must have "und" in your list of languages to keep for this to function.
eng \\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 \\nExample:\\n
por`, por`,
}, },
{ {
name: "tag_title", name: 'tag_title',
tooltip: `Specify audio tracks with no title to be tagged with the number of channels they contain. Do NOT use this with mp4, as mp4 does not support title tags. tooltip: `Specify audio tracks with no title to be tagged with the number of channels they contain.
\\nExample:\\n \\nDo NOT use this with mp4, as mp4 does not support title tags.
true \\nExample:\\n
true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
], ],
}; };
} }
function plugin(file, librarySettings, inputs) { function plugin(file, librarySettings, inputs) {
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
container: "." + file.container, container: `.${file.container}`,
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: true, FFmpegMode: true,
reQueueAfter: false, reQueueAfter: false,
infoLog: "", infoLog: '',
}; };
// Check if file is a video. If it isn't then exit plugin. // Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
response.infoLog += "☒File is not video \n"; console.log('File is not video');
response.infoLog += '☒File is not video \n';
response.processFile = false; response.processFile = false;
return response; return response;
} }
// Check if inputs.language has been configured. If it hasn't then exit plugin. // Check if inputs.language has been configured. If it hasn't then exit plugin.
if (inputs.language == "") { if (inputs.language === '') {
response.infoLog += response.infoLog += '☒Language/s options not set, please configure required options. Skipping this plugin. \n';
"☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false; response.processFile = false;
return response; return response;
} }
// Set up required variables. // Set up required variables.
var language = inputs.language.split(","); const language = inputs.language.split(',');
var ffmpegCommandInsert = ""; let ffmpegCommandInsert = '';
var convert = false; let convert = false;
var audioIdx = 0; let audioIdx = 0;
var audioStreamsRemoved = 0; let audioStreamsRemoved = 0;
var audioStreamCount = file.ffProbeData.streams.filter( const audioStreamCount = file.ffProbeData.streams.filter(
(row) => row.codec_type.toLowerCase() == "audio" (row) => row.codec_type.toLowerCase() === 'audio',
).length; ).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. // Catch error here incase the language metadata is completely missing.
try { 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 ( if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
language.indexOf( && language.indexOf(
file.ffProbeData.streams[i].tags.language.toLowerCase() file.ffProbeData.streams[i].tags.language.toLowerCase(),
) === -1 ) === -1
) { ) {
audioStreamsRemoved++; audioStreamsRemoved += 1;
ffmpegCommandInsert += `-map -0:a:${audioIdx} `; ffmpegCommandInsert += `-map -0:a:${audioIdx} `;
response.infoLog += `☒Audio stream detected as being an unwanted language, removing. Audio stream 0:a:${audioIdx} - ${file.ffProbeData.streams[ response.infoLog += `☒Audio stream detected as being unwanted, removing. Audio stream 0:a:${audioIdx} \n`;
i
].tags.language.toLowerCase()} \n`;
convert = true; convert = true;
} }
} catch (err) {} } catch (err) {
// Error
}
// Catch error here incase the title metadata is completely missing. // Catch error here incase the title metadata is completely missing.
try { 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 ( if (
inputs.commentary.toLowerCase() == "true" && inputs.commentary.toLowerCase() === 'true'
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && && file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
(file.ffProbeData.streams[i].tags.title && (file.ffProbeData.streams[i].tags.title
.toLowerCase() .toLowerCase()
.includes("commentary") || .includes('commentary')
file.ffProbeData.streams[i].tags.title || file.ffProbeData.streams[i].tags.title
.toLowerCase() .toLowerCase()
.includes("description") || .includes('description')
file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh")) || file.ffProbeData.streams[i].tags.title.toLowerCase().includes('sdh'))
) { ) {
audioStreamsRemoved++; audioStreamsRemoved += 1;
ffmpegCommandInsert += `-map -0:a:${audioIdx} `; 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; 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 ( if (
inputs.tag_language != "" && inputs.tag_language !== ''
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio'
) { ) {
// Catch error here incase the metadata is completely missing. // Catch error here incase the metadata is completely missing.
try { try {
@ -142,64 +156,69 @@ function plugin(file, librarySettings, inputs) {
if ( if (
file.ffProbeData.streams[i].tags.language file.ffProbeData.streams[i].tags.language
.toLowerCase() .toLowerCase()
.includes("und") .includes('und')
) { ) {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `; 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; 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") {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
} }
// Checks if the tags.language metadata is completely missing, if so this would cause playback to show language as "undefined". No catch error here otherwise it would never detect the metadata as missing.
else { // Checks if the tags metadata is completely missing.
if (typeof file.ffProbeData.streams[i].tags.language == "undefined") { // If so this would cause playback to show language as "undefined".
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} language=${inputs.tag_language} `; // No catch error here otherwise it would never detect the metadata as missing.
response.infoLog += `☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`; if (typeof file.ffProbeData.streams[i].tags === 'undefined') {
convert = true; 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;
} 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;
} }
} }
try { 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 ( if (
typeof file.ffProbeData.streams[i].tags.title == "undefined" && typeof file.ffProbeData.streams[i].tags.title === 'undefined'
inputs.tag_title.toLowerCase() == "true" && && inputs.tag_title.toLowerCase() === 'true'
file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio" && 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" `; 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; convert = true;
} }
if (file.ffProbeData.streams[i].channels == "6") { if (file.ffProbeData.streams[i].channels === 6) {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="5.1" `; 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; convert = true;
} }
if (file.ffProbeData.streams[i].channels == "2") { if (file.ffProbeData.streams[i].channels === 2) {
ffmpegCommandInsert += `-metadata:s:a:${audioIdx} title="2.0" `; 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; convert = true;
} }
} }
} catch (err) {} } catch (err) {
// Error
}
// Check if stream type is audio and increment audioIdx if true. // Check if stream type is audio and increment audioIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") { if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
audioIdx++; audioIdx += 1;
} }
} }
// Failsafe to cancel processing if all streams would be removed following this plugin. We don't want no audio. // Failsafe to cancel processing if all streams would be removed following this plugin. We don't want no audio.
if (audioStreamsRemoved == audioStreamCount) { if (audioStreamsRemoved === audioStreamCount) {
response.infoLog += response.infoLog += '☒Cancelling plugin otherwise all audio tracks would be removed. \n';
"☒Cancelling plugin otherwise all audio tracks would be removed. \n";
response.processFile = false; response.processFile = false;
return response; return response;
} }
@ -207,13 +226,12 @@ function plugin(file, librarySettings, inputs) {
// Convert file if convert variable is set to true. // Convert file if convert variable is set to true.
if (convert === true) { if (convert === true) {
response.processFile = true; response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`; response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 9999`;
response.container = "." + file.container; response.container = `.${file.container}`;
response.reQueueAfter = true; response.reQueueAfter = true;
} else { } else {
response.processFile = false; response.processFile = false;
response.infoLog += response.infoLog += "☑File doesn't contain audio tracks which are unwanted or that require tagging.\n";
"☑File doesn't contain audio tracks which are unwanted or that require tagging.\n";
} }
return response; return response;
} }

View File

@ -1,123 +1,133 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MC93_Migz4CleanSubs", id: 'Tdarr_Plugin_MC93_Migz4CleanSubs',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "Migz-Clean subtitle streams", Name: 'Migz-Clean subtitle streams',
Type: "subtitles", Type: 'subtitles',
Operation: "Clean", Operation: 'Clean',
Description: `This plugin keeps only specified language subtitle tracks & can tag those that have an unknown language. \n\n`, Description: 'This plugin keeps only specified language tracks & can tag tracks with an unknown language. \n\n',
Version: "2.2", Version: '2.4',
Link: Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js',
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_Migz4CleanSubs.js", Tags: 'pre-processing,ffmpeg,subtitle only,configurable',
Tags: "pre-processing,ffmpeg,subtitle only,configurable", Inputs: [{
Inputs: [ name: 'language',
{ tooltip: `Specify language tag/s here for the subtitle tracks you'd like to keep.
name: "language", \\nMust follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
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
\\nExample:\\n eng
eng
\\nExample:\\n \\nExample:\\n
eng,jap`, eng,jap`,
}, },
{ {
name: "commentary", name: 'commentary',
tooltip: `Specify if subtitle tracks that contain commentary/description should be removed. tooltip: `Specify if subtitle tracks that contain commentary/description should be removed.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
{ {
name: "tag_language", name: 'tag_language',
tooltip: `Specify a single language for subtitle tracks with no language or unknown language to be tagged with, leave empty to disable. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes tooltip: `Specify a single language for subtitle tracks with no language or unknown language to be tagged with.
\\nExample:\\n \\nMust follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
eng \\nLeave empty to disable.
\\nExample:\\n
eng
\\nExample:\\n \\nExample:\\n
por`, por`,
}, },
], ],
}; };
} }
function plugin(file, librarySettings, inputs) { function plugin(file, librarySettings, inputs) {
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
container: "." + file.container, container: `.${file.container}`,
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: true, FFmpegMode: true,
reQueueAfter: false, reQueueAfter: false,
infoLog: "", infoLog: '',
}; };
// Check if file is a video. If it isn't then exit plugin. // Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
response.infoLog += "☒File is not video \n"; console.log('File is not video');
response.infoLog += '☒File is not video \n';
response.processFile = false; response.processFile = false;
return response; return response;
} }
// Check if inputs.language has been configured. If it hasn't then exit plugin. // Check if inputs.language has been configured. If it hasn't then exit plugin.
if (inputs.language == "") { if (inputs.language === '') {
response.infoLog += response.infoLog += '☒Language/s to keep have not been configured, '
"☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n"; + 'please configure required options. Skipping this plugin. \n';
response.processFile = false; response.processFile = false;
return response; return response;
} }
// Set up required variables. // Set up required variables.
var language = inputs.language.split(","); const language = inputs.language.split(',');
var ffmpegCommandInsert = ""; let ffmpegCommandInsert = '';
var subtitleIdx = 0; let subtitleIdx = 0;
var convert = false; let convert = false;
// Go through each stream in the file. // 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. // Catch error here incase the language metadata is completely missing.
try { 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 ( if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" && file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle'
language.indexOf( && language.indexOf(
file.ffProbeData.streams[i].tags.language.toLowerCase() file.ffProbeData.streams[i].tags.language.toLowerCase(),
) === -1 ) === -1
) { ) {
ffmpegCommandInsert += `-map -0:s:${subtitleIdx} `; ffmpegCommandInsert += `-map -0:s:${subtitleIdx} `;
response.infoLog += `☒Subtitle stream detected as being an unwanted language, removing. Subtitle stream 0:s:${subtitleIdx} - ${file.ffProbeData.streams[ response.infoLog += `☒Subtitle stream detected as being unwanted, removing. Stream 0:s:${subtitleIdx} \n`;
i
].tags.language.toLowerCase()} \n`;
convert = true; convert = true;
} }
} catch (err) {} } catch (err) {
// Error
}
// Catch error here incase the title metadata is completely missing. // Catch error here incase the title metadata is completely missing.
try { 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 ( if (
inputs.commentary.toLowerCase() == "true" && inputs.commentary.toLowerCase() === 'true'
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" && && file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle'
(file.ffProbeData.streams[i].tags.title && (file.ffProbeData.streams[i].tags.title
.toLowerCase() .toLowerCase()
.includes("commentary") || .includes('commentary')
file.ffProbeData.streams[i].tags.title || file.ffProbeData.streams[i].tags.title
.toLowerCase() .toLowerCase()
.includes("description") || .includes('description'))
file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh"))
) { ) {
ffmpegCommandInsert += `-map -0:s:${subtitleIdx} `; 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; 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 ( if (
inputs.tag_language != "" && inputs.tag_language !== ''
file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle" && file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle'
) { ) {
// Catch error here incase the metadata is completely missing. // Catch error here incase the metadata is completely missing.
try { try {
@ -125,46 +135,48 @@ function plugin(file, librarySettings, inputs) {
if ( if (
file.ffProbeData.streams[i].tags.language file.ffProbeData.streams[i].tags.language
.toLowerCase() .toLowerCase()
.includes("und") .includes('und')
) { ) {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `; 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; 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") {
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `;
response.infoLog += `☒Subtitle stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`;
convert = true;
} }
// Checks if the tags.language metadata is completely missing, if so this would cause playback to show language as "undefined". No catch error here otherwise it would never detect the metadata as missing.
else { // Checks if the tags metadata is completely missing.
if (typeof file.ffProbeData.streams[i].tags.language == "undefined") { // If so this would cause playback to show language as "undefined".
ffmpegCommandInsert += `-metadata:s:s:${subtitleIdx} language=${inputs.tag_language} `; // No catch error here otherwise it would never detect the metadata as missing.
response.infoLog += `☒Subtitle stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`; if (typeof file.ffProbeData.streams[i].tags === 'undefined') {
convert = true; 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;
} 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;
} }
} }
// Check if stream type is subtitle and increment subtitleIdx if true. // Check if stream type is subtitle and increment subtitleIdx if true.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "subtitle") { if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle') {
subtitleIdx++; subtitleIdx += 1;
} }
} }
// Convert file if convert variable is set to true. // Convert file if convert variable is set to true.
if (convert === true) { if (convert === true) {
response.processFile = true; response.processFile = true;
response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 4096`; response.preset = `, -map 0 ${ffmpegCommandInsert} -c copy -max_muxing_queue_size 9999`;
response.container = "." + file.container; response.container = `.${file.container}`;
response.reQueueAfter = true; response.reQueueAfter = true;
} else { } else {
response.processFile = false; response.processFile = false;
response.infoLog += response.infoLog += "☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n";
"☑File doesn't contain subtitle tracks which are unwanted or that require tagging.\n";
} }
return response; return response;
} }

View File

@ -1,148 +1,155 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MC93_Migz5ConvertAudio", id: 'Tdarr_Plugin_MC93_Migz5ConvertAudio',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "Migz-Convert audio streams", Name: 'Migz-Convert audio streams',
Type: "Audio", Type: 'Audio',
Operation: "Transcode", Operation: 'Transcode',
Description: `This plugin can convert any 2.0 audio track/s to AAC and can create downmixed audio tracks. \n\n`, Description: 'This plugin can convert any 2.0 audio track/s to AAC and can create downmixed audio tracks. \n\n',
Version: "2.1", Version: '2.3',
Link: "", Link: '',
Tags: "pre-processing,ffmpeg,audio only,configurable", Tags: 'pre-processing,ffmpeg,audio only,configurable',
Inputs: [ Inputs: [{
{ name: 'aac_stereo',
name: "aac_stereo", tooltip: `Specify if any 2.0 audio tracks should be converted to aac for maximum compatability with devices.
tooltip: `Specify if any 2.0 audio tracks should be converted to aac for maximum compatability with devices. Optional. \\nOptional.
\\nExample:\\n \\nExample:\\n
true true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
{ {
name: "downmix", name: 'downmix',
tooltip: `Specify if downmixing should be used to create extra audio tracks. I.e if you have an 8ch but no 2ch or 6ch, create the missing audio tracks from the 8 ch. Likewise if you only have 6ch, create the missing 2ch from it. Optional. tooltip: `Specify if downmixing should be used to create extra audio tracks.
\\nExample:\\n \\nI.e if you have an 8ch but no 2ch or 6ch, create the missing audio tracks from the 8 ch.
true \\nLikewise if you only have 6ch, create the missing 2ch from it. Optional.
\\nExample:\\n
true
\\nExample:\\n \\nExample:\\n
false`, false`,
}, },
], ],
}; };
} }
function plugin(file, librarySettings, inputs) { function plugin(file, librarySettings, inputs) {
var response = { const response = {
processFile: false, processFile: false,
container: "." + file.container, container: `.${file.container}`,
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: true, FFmpegMode: true,
reQueueAfter: true, reQueueAfter: true,
infoLog: "", infoLog: '',
}; };
// Check if both inputs.aac_stereo AND inputs.downmix have been left empty. If they have then exit plugin. // 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 == "") { if (inputs && inputs.aac_stereo === '' && inputs.downmix === '') {
response.infoLog += response.infoLog += '☒Plugin has not been configured, please configure required options. Skipping this plugin. \n';
"☒Neither aac_stereo or downmix options have been configured within plugin settings, please configure required options. Skipping this plugin. \n";
response.processFile = false; response.processFile = false;
return response; return response;
} }
// Check if file is a video. If it isn't then exit plugin. // Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
response.infoLog += "☒File is not video. \n"; console.log('File is not video');
response.infoLog += '☒File is not video. \n';
response.processFile = false; response.processFile = false;
return response; return response;
} }
// Set up required variables. // Set up required variables.
var ffmpegCommandInsert = ""; let ffmpegCommandInsert = '';
var audioIdx = 0; let audioIdx = 0;
var has2Channel = false; let has2Channel = false;
var has6Channel = false; let has6Channel = false;
var has8Channel = false; let has8Channel = false;
var convert = false; let convert = false;
// Go through each stream in the file. // 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 { try {
// Go through all audio streams and check if 2,6 & 8 channel tracks exist or not. // 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].codec_type.toLowerCase() === 'audio') {
if (file.ffProbeData.streams[i].channels == "2") { if (file.ffProbeData.streams[i].channels === 2) {
has2Channel = true; has2Channel = true;
} }
if (file.ffProbeData.streams[i].channels == "6") { if (file.ffProbeData.streams[i].channels === 6) {
has6Channel = true; has6Channel = true;
} }
if (file.ffProbeData.streams[i].channels == "8") { if (file.ffProbeData.streams[i].channels === 8) {
has8Channel = true; has8Channel = true;
} }
} }
} catch (err) {} } catch (err) {
// Error
}
} }
// Go through each stream in the file. // 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. // 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. // Catch error here incase user left inputs.downmix empty.
try { try {
// Check if inputs.downmix is set to true. // 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. // Check if file has 8 channel audio but no 6 channel, if so then create extra downmix from the 8 channel.
if ( if (
has8Channel == true && has8Channel === true
has6Channel == false && && has6Channel === false
file.ffProbeData.streams[i].channels == "8" && file.ffProbeData.streams[i].channels === 8
) { ) {
ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} ac3 -ac 6 -metadata:s:a:${audioIdx} title="5.1 " `; ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} ac3 -ac 6 -metadata:s:a:${audioIdx} title="5.1 " `;
response.infoLog += response.infoLog += '☒Audio track is 8 channel, no 6 channel exists. Creating 6 channel from 8 channel. \n';
"☒Audio track is 8 channel, no 6 channel exists. Creating 6 channel from 8 channel. \n";
convert = true; convert = true;
} }
// Check if file has 6 channel audio but no 2 channel, if so then create extra downmix from the 6 channel. // Check if file has 6 channel audio but no 2 channel, if so then create extra downmix from the 6 channel.
if ( if (
has6Channel == true && has6Channel === true
has2Channel == false && && has2Channel === false
file.ffProbeData.streams[i].channels == "6" && file.ffProbeData.streams[i].channels === 6
) { ) {
ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} aac -ac 2 -metadata:s:a:${audioIdx} title="2.0 " `; ffmpegCommandInsert += `-map 0:${i} -c:a:${audioIdx} aac -ac 2 -metadata:s:a:${audioIdx} title="2.0 " `;
response.infoLog += response.infoLog += '☒Audio track is 6 channel, no 2 channel exists. Creating 2 channel from 6 channel. \n';
"☒Audio track is 6 channel, no 2 channel exists. Creating 2 channel from 6 channel. \n";
convert = true; convert = true;
} }
} }
} catch (err) {} } catch (err) {
// Error
}
// Catch error here incase user left inputs.downmix empty. // Catch error here incase user left inputs.downmix empty.
try { try {
// Check if inputs.aac_stereo is set to true. // 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. // Check if codec_name for stream is NOT aac AND check if channel ammount is 2.
if ( if (
file.ffProbeData.streams[i].codec_name != "aac" && file.ffProbeData.streams[i].codec_name !== 'aac'
file.ffProbeData.streams[i].channels == "2" && file.ffProbeData.streams[i].channels === 2
) { ) {
ffmpegCommandInsert += `-c:a:${audioIdx} aac `; ffmpegCommandInsert += `-c:a:${audioIdx} aac `;
response.infoLog += response.infoLog += '☒Audio track is 2 channel but is not AAC. Converting. \n';
"☒Audio track is 2 channel but is not AAC. Converting. \n";
convert = true; convert = true;
} }
} }
} catch (err) {} } catch (err) {
audioIdx++; // Error
}
audioIdx += 1;
} }
} }
// Convert file if convert variable is set to true. // Convert file if convert variable is set to true.
if (convert == true) { if (convert === true) {
response.processFile = true; response.processFile = true;
response.preset = `, -map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} -strict -2 -c:s copy -max_muxing_queue_size 4096 `; response.preset = `, -map 0 -c:v copy -c:a copy ${ffmpegCommandInsert} `
+ '-strict -2 -c:s copy -max_muxing_queue_size 9999 ';
} else { } else {
response.infoLog += "☑File contains all required audio formats. \n"; response.infoLog += '☑File contains all required audio formats. \n';
response.processFile = false; response.processFile = false;
} }
return response; return response;

View File

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

View File

@ -1,67 +1,68 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MC93_MigzImageRemoval", id: 'Tdarr_Plugin_MC93_MigzImageRemoval',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "Migz-Remove image formats from file", Name: 'Migz-Remove image formats from file',
Type: "Video", Type: 'Video',
Operation: "Clean", Operation: 'Clean',
Description: `Identify any unwanted image formats in the file and remove those streams. MJPEG & PNG \n\n`, Description: 'Identify any unwanted image formats in the file and remove those streams. MJPEG & PNG \n\n',
Version: "1.1", Version: '1.3',
Link: Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js", 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_MC93_MigzImageRemoval.js',
Tags: "pre-processing,ffmpeg,video only", Tags: 'pre-processing,ffmpeg,video only',
}; };
} }
function plugin(file, librarySettings, inputs) { function plugin(file) {
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
handBrakeMode: false, handBrakeMode: false,
container: "." + file.container, container: `.${file.container}`,
FFmpegMode: true, FFmpegMode: true,
reQueueAfter: true, reQueueAfter: true,
infoLog: "", infoLog: '',
}; };
// Check if file is a video. If it isn't then exit plugin. // 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.processFile = false;
response.infoLog += "☒File is not a video. \n"; response.infoLog += '☒File is not a video. \n';
return response; return response;
} }
// Set up required variables. // Set up required variables.
var videoIdx = 0; let videoIdx = 0;
var extraArguments = ""; let extraArguments = '';
var convert = false; let convert = false;
// Go through each stream in the file. // 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. // 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. // Check if stream codec is mjpeg or png. Remove if so.
if ( if (
file.ffProbeData.streams[i].codec_name == "mjpeg" || file.ffProbeData.streams[i].codec_name === 'mjpeg'
file.ffProbeData.streams[i].codec_name == "png" || file.ffProbeData.streams[i].codec_name === 'png'
) { ) {
convert = true; convert = true;
extraArguments += `-map -v:${videoIdx} `; extraArguments += `-map -v:${videoIdx} `;
} }
// Increment videoIdx. // Increment videoIdx.
videoIdx++; videoIdx += 1;
} }
} }
// Convert file if convert variable is set to true. // Convert file if convert variable is set to true.
if (convert === true) { if (convert === true) {
response.preset += `,-map 0 -c copy -max_muxing_queue_size 4096 ${extraArguments}`; 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; response.processFile = true;
} else { } else {
response.processFile = false; response.processFile = false;
response.infoLog += response.infoLog
"☑File doesn't contain any unwanted image format streams.\n"; += "☑File doesn't contain any unwanted image format streams.\n";
} }
return response; return response;
} }

View File

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

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_MP01_MichPasCleanSubsAndAudioCodecs", id: "Tdarr_Plugin_MP01_MichPasCleanSubsAndAudioCodecs",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
const vaapiPrefix = ` -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi `; const vaapiPrefix = ` -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi `;
module.exports.details = function details() { module.exports.details = function details() {

View File

@ -1,4 +1,4 @@
/* eslint-disable */
//PLugin runs multipass loudnorm filter //PLugin runs multipass loudnorm filter
//first run gets the required details and stores for the next pass //first run gets the required details and stores for the next pass
//second pass applies the values //second pass applies the values

View File

@ -1,3 +1,4 @@
/* eslint-disable */
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
if (fs.existsSync(path.join(process.cwd(), '/npm'))) { if (fs.existsSync(path.join(process.cwd(), '/npm'))) {

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta", id: "Tdarr_Plugin_a37x_Drawmonster_MP4_No_Title_Meta",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30", id: "Tdarr_Plugin_a8hc_HaveAGitGat_HandBrake_H264_VeryFast1080p30",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30", id: "Tdarr_Plugin_a9hc_HaveAGitGat_HandBrake_H264_Fast1080p30",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_a9hd_FFMPEG_Transcode_Specific_Audio_Stream_Codecs", id: "Tdarr_Plugin_a9hd_FFMPEG_Transcode_Specific_Audio_Stream_Codecs",
@ -34,6 +35,16 @@ module.exports.details = function details() {
\\nExample:\\n \\nExample:\\n
eac3 eac3
`,
},
{
name: "bitrate",
tooltip: `Specify the transcoded audio bitrate (optional):
\\n 384k
\\n 640k
\\nExample:\\n
640k
`, `,
}, },
], ],
@ -53,7 +64,7 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
infoLog: "", infoLog: "",
}; };
if (inputs.codecs_to_transcode === undefined || inputs.codec === undefined) { if (inputs.codecs_to_transcode === undefined || inputs.codec === undefined ) {
response.processFile = false; response.processFile = false;
response.infoLog += "☒ Inputs not entered! \n"; response.infoLog += "☒ Inputs not entered! \n";
return response; return response;
@ -81,6 +92,9 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
) )
) { ) {
ffmpegCommand += ` -map 0:${i} -c:${i} ${encoder} `; ffmpegCommand += ` -map 0:${i} -c:${i} ${encoder} `;
if (inputs.bitrate != undefined) {
ffmpegCommand += `-b:a ${inputs.bitrate} `;
}
hasStreamsToTranscode = true; hasStreamsToTranscode = true;
} else if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") { } else if (file.ffProbeData.streams[i].codec_type.toLowerCase() == "audio") {
ffmpegCommand += ` -map 0:${i}`; ffmpegCommand += ` -map 0:${i}`;
@ -104,4 +118,4 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
response.infoLog += `☒ File has streams which aren't in desired codec! \n`; response.infoLog += `☒ File has streams which aren't in desired codec! \n`;
return response; return response;
} }
}; };

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta", id: "Tdarr_Plugin_b38x_Nosirus_h265_aac_no_meta",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3", id: "Tdarr_Plugin_b39x_the1poet_surround_sound_to_ac3",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_c0r1_SetDefaultAudioStream", id: "Tdarr_Plugin_c0r1_SetDefaultAudioStream",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV", id: "Tdarr_Plugin_d5d3_iiDrakeii_FFMPEG_NVENC_Tiered_MKV",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_d5d4_iiDrakeii_Not_A_Video_Mjpeg_Fix", id: "Tdarr_Plugin_d5d4_iiDrakeii_Not_A_Video_Mjpeg_Fix",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4", id: "Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_drdd_standardise_all_in_one", id: "Tdarr_Plugin_drdd_standardise_all_in_one",
@ -230,8 +231,8 @@ function buildAudioConfiguration(_inputs, file, logger) {
function buildSubtitleConfiguration(inputs, file, logger) { function buildSubtitleConfiguration(inputs, file, logger) {
var configuration = new Configurator(["-c:s copy"]); var configuration = new Configurator(["-c:s copy"]);
if (!inputs.wanted_subtitle_languages) return configuration;
var languages = inputs.wanted_subtitle_languages.split(","); var languages = inputs.wanted_subtitle_languages.split(",");
if (languages.length === 0) return configuration;
loopOverStreamsOfType(file, "subtitle", function (stream, id) { loopOverStreamsOfType(file, "subtitle", function (stream, id) {
if (stream.codec_name === "eia_608") { if (stream.codec_name === "eia_608") {

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_e3jc_Tharic_H.264_MKV_480p30_No_Subs_No_Title_Meta", id: "Tdarr_Plugin_e3jc_Tharic_H.264_MKV_480p30_No_Subs_No_Title_Meta",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_e3jd_Tharic_H.264_MKV_720p30_No_Subs_No_Title_Meta", id: "Tdarr_Plugin_e3jd_Tharic_H.264_MKV_720p30_No_Subs_No_Title_Meta",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_e3je_Tharic_H.264_MKV_1080p30_No_Subs_No_Title_Meta", id: "Tdarr_Plugin_e3je_Tharic_H.264_MKV_1080p30_No_Subs_No_Title_Meta",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
const fs = require("fs"); const fs = require("fs");
const execSync = require("child_process").execSync; const execSync = require("child_process").execSync;

View File

@ -1,3 +1,4 @@
/* eslint-disable */
const exec = require("child_process").exec; const exec = require("child_process").exec;
const fs = require("fs"); const fs = require("fs");

View File

@ -1,3 +1,4 @@
/* eslint-disable */
const fs = require("fs"); const fs = require("fs");
const execSync = require("child_process").execSync; const execSync = require("child_process").execSync;

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs", id: "Tdarr_Plugin_fd5T_Sparticus_4K_AC3_No_Subs",

View File

@ -0,0 +1,114 @@
/* eslint-disable */
function details () {
return {
id: 'Tdarr_Plugin_henk_Add_Specific_Audio_Codec',
Stage: 'Pre-processing',
Name: '[TESTING][MKV ONLY] Transcode given codec to other given codec and keep original',
Type: 'Audio',
Operation: 'Transcode',
Description: `Re-encodes all audio tracks in a given codec to another given codec.`,
Version: '1.00',
Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_henk_Add_Specific_Audio_Codec.js',
Tags: 'post-processing,configurable',
Inputs: [{
name: 'input_codecs',
tooltip: 'Comma separated list of input codecs to be processed. Defaults to dts.' +
'\\nExample:\\n' +
'dts,aac,ac3'
}, {
name: 'output_codec',
tooltip: 'FFMPEG encoder used for the output of the new tracks. Defaults to ac3.'
}, {
name: 'bitrate',
tooltip: `Specifies the (stereo) bitrate for the new audio codec. Defaults to 128k. Only numbers.`
}, {
name: 'auto_adjust',
tooltip: '[true/false] Multi-channel audio requires a higher bitrate for the same quality, do you want the plugin to calculate this? (bitrate * (channels / 2))'
}, {
name: 'custom_bitrate_input',
tooltip: 'DIRECT ACCESS TO FFMPEG, USE WITH CAUTION. If filled, can be used for custom bitrate arguments.'
}],
}
}
function plugin (file, librarySettings, inputs) {
var response = {
processFile: false,
preset: ', -c copy -map 0:v ',
container: '.' + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
}
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== 'video') {
response.infoLog += '☒File is not video \n'
return response
}
// Check if file is mkv. If it isn't then exit plugin.
if (file.container !== 'mkv') {
response.infoLog += '☒File is not mkv \n'
return response
}
var convertCount = 0
var streamCount = 0
var indexCount = 0
var killPlugin = false
var inputCodecs = inputs.input_codecs ? inputs.input_codecs.split(',') : ['dts']
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
var currStream = file.ffProbeData.streams[i]
if (currStream.tags.COPYRIGHT) {
if (currStream.tags.COPYRIGHT === 'henk_asac') {
killPlugin = true
}
}
}
if (killPlugin) {
response.infoLog +=
`☑File has already been processed by this plugin.\n`
return response
}
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
var currStream = file.ffProbeData.streams[i]
if (currStream.codec_type.toLowerCase() === 'audio') {
response.preset += ` -map 0:a:${indexCount}? -c:a:${streamCount} copy `
streamCount++
if (inputCodecs.includes(currStream.codec_name.toLowerCase())) {
convertCount++
var bitrate = `-b:a:${streamCount} `
if (inputs.custom_bitrate_input) {
bitrate += inputs.custom_bitrate_input
} else if (inputs.bitrate) {
bitrate += (inputs.auto_adjust ? (inputs.bitrate * (currStream.channels / 2)) : inputs.bitrate) + 'k'
} else {
bitrate = '128k'
}
response.preset += ` -map 0:a:${indexCount}? -c:a:${streamCount} ${inputs.output_codec || 'ac3'} ${bitrate} ` +
`-metadata:s:a:${streamCount} title="" -metadata:s:a:${streamCount} copyright="henk_asac"`
}
indexCount++
}
}
if (convertCount > 0) {
response.processFile = true
response.container = '.' + file.container
response.reQueueAfter = true
} else {
response.infoLog +=
'☑File doesn\'t contain audio tracks with the specified codec.\n'
}
return response
}
module.exports.details = details
module.exports.plugin = plugin

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle", id: "Tdarr_Plugin_hk75_Drawmonster_MP4_AAC_No_Subs_No_metaTitle",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle", id: "Tdarr_Plugin_hk76_GilbN_MP4_AAC_No_metaTitle",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_lmg1_Reorder_Streams", id: "Tdarr_Plugin_lmg1_Reorder_Streams",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta", id: "Tdarr_Plugin_nc7x_Drawmonster_No_Title_Meta",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_r002_rootuser_FFMPEG_HQ_HEVC_MKV_Animation", id: "Tdarr_Plugin_r002_rootuser_FFMPEG_HQ_HEVC_MKV_Animation",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_raf4_Floorpie_FFmpeg_Tiered_HEVC_MKV", id: "Tdarr_Plugin_raf4_Floorpie_FFmpeg_Tiered_HEVC_MKV",

View File

@ -0,0 +1,115 @@
const fs = require('fs');
module.exports.details = function details() {
return {
id: 'Tdarr_Plugin_rr01_drpeppershaker_extract_subs_to_SRT',
Stage: 'Pre-processing',
Name: 'drpeppershaker Extract embedded subtitles and optionally remove them',
Type: 'Video',
Operation: 'Transcode',
Description: 'This plugin extracts embedded subs in one pass inside Tdarr and will optionally remove them. \n\n '
+ 'All processes happen within Tdarr without the use of any exec() functions, which lets the progress bar '
+ 'report the status correctly. AND all subtitles are extracted in one pass, which is much faster than '
+ 'other options.',
// Created by drpeppershaker with help from reddit user /u/jakejones48, lots of
// improvements made after looking at "Tdarr_Plugin_078d" by HaveAGitGat.
Version: '1.04',
Link: '',
Tags: 'pre-processing,subtitle only,ffmpeg,configurable',
Inputs: [
{
name: 'remove_subs',
tooltip: `Do you want to remove subtitles after they are extracted?
\\nExample:\\n
yes
\\nExample:\\n
no
`,
},
],
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs) {
// Must return this object at some point in the function else plugin will fail.
const response = {
processFile: true,
preset: '',
container: `.${file.container}`,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: '',
};
if (inputs.remove_subs === undefined) {
response.processFile = false;
response.infoLog += '☒ Inputs not entered! \n';
return response;
}
const subsArr = file.ffProbeData.streams.filter((row) => row.codec_name === 'subrip');
if (subsArr.length === 0) {
response.infoLog += 'No subs in file to extract!\n';
response.processFile = false;
return response;
}
response.infoLog += 'Found subs to extract!\n';
let command = '-y,';
for (let i = 0; i < subsArr.length; i += 1) {
const subStream = subsArr[i];
let lang = '';
let title = 'none';
if (subStream.tags) {
lang = subStream.tags.language;
}
if (subStream.tags.title) {
title = subStream.tags.title;
}
let subsFile = file.file;
subsFile = subsFile.split('.');
subsFile[subsFile.length - 2] += `.${lang}`;
subsFile[subsFile.length - 1] = 'srt';
subsFile = subsFile.join('.');
const { index } = subStream;
if (fs.existsSync(`${subsFile}`)) {
response.infoLog += `${lang}.srt already exists. Skipping!\n`;
} else if (title.toLowerCase().includes('commentary') || title.toLowerCase().includes('description')) {
response.infoLog += `Stream ${i} ${lang}.srt is a ${title} track. Skipping!\n`;
} else {
response.infoLog += `Extracting ${lang}.srt\n`;
command += ` -map 0:${index} "${subsFile}"`;
}
}
if (command === '-y,') {
response.infoLog += 'All subs already extracted!\n';
if (inputs.remove_subs === 'no') {
response.processFile = false;
return response;
}
}
response.preset = command;
if (inputs.remove_subs === 'yes') {
response.preset += ' -map 0 -map -0:s -c copy';
}
if (inputs.remove_subs === 'no') {
response.preset += ' -map 0 -c copy';
}
return response;
};

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_s710_nick_h265_nvenc_4K", id: "Tdarr_Plugin_s710_nick_h265_nvenc_4K",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_s7x8_winsome_h265", id: "Tdarr_Plugin_s7x8_winsome_h265",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_s7x9_winsome_h265_10bit", id: "Tdarr_Plugin_s7x9_winsome_h265_10bit",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_s7x9_winsome_h265_nvenc", id: "Tdarr_Plugin_s7x9_winsome_h265_nvenc",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_sdd3_Remove_Commentary_Tracks", id: "Tdarr_Plugin_sdd3_Remove_Commentary_Tracks",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio", id: "Tdarr_Plugin_sdf5_Thierrrrry_Remove_Non_English_Audio",

View File

@ -0,0 +1,68 @@
/* eslint-disable */
function details() {
return {
id: "Tdarr_Plugin_vdka_Remove_DataStreams",
Stage: "Pre-processing",
Name: "Remove Data Streams ",
Type: "Video",
Description: `[Contains built-in filter] This plugin removes data streams if detected. The output container is the same as the original. Helps with issues like bin_data making files impossible to process. \n\n`,
Version: "1.00",
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_vdka_Remove_DataStreams.js",
Tags: "pre-processing,ffmpeg",
};
}
function plugin(file) {
//Must return this object
var response = {
processFile: false,
preset: "",
container: ".mp4",
handBrakeMode: false,
FFmpegMode: false,
reQueueAfter: false,
infoLog: "",
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
return response;
} else {
response.FFmpegMode = true;
response.container = ".mkv";
var hasData = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
file.ffProbeData.streams[i].codec_type.toLowerCase() == "data"
) {
hasData = true;
}
} catch (err) {}
}
if (hasData) {
response.infoLog += "☒File has data streams \n";
response.preset = ",-map 0 -c copy -dn -map_chapters -1";
response.reQueueAfter = true;
response.processFile = true;
return response;
} else {
response.infoLog += "☑File has no data streams! \n";
}
response.infoLog += "☑File meets conditions! \n";
return response;
}
}
module.exports.details = details;
module.exports.plugin = plugin;

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details () { function details () {
return { return {
id: 'Tdarr_Plugin_vdka_Tiered_NVENC_CQV_BASED_CONFIGURABLE', id: 'Tdarr_Plugin_vdka_Tiered_NVENC_CQV_BASED_CONFIGURABLE',
@ -22,28 +23,28 @@ function details () {
tooltip: `Enter the CQ:V value you want for 480p and 576p content. tooltip: `Enter the CQ:V value you want for 480p and 576p content.
\\nExample:\\n \\nExample:\\n
18` 21`
}, },
{ {
name: 'hdCQV', name: 'hdCQV',
tooltip: `Enter the CQ:V value you want for 720p content. tooltip: `Enter the CQ:V value you want for 720p content.
\\nExample:\\n \\nExample:\\n
17` 23`
}, },
{ {
name: 'fullhdCQV', name: 'fullhdCQV',
tooltip: `Enter the CQ:V value you want for 1080p content. tooltip: `Enter the CQ:V value you want for 1080p content.
\\nExample:\\n \\nExample:\\n
18` 25`
}, },
{ {
name: 'uhdCQV', name: 'uhdCQV',
tooltip: `Enter the CQ:V value you want for 4K/UHD/2160p content. tooltip: `Enter the CQ:V value you want for 4K/UHD/2160p content.
\\nExample:\\n \\nExample:\\n
22` 28`
}, },
{ {
name: 'bframe', name: 'bframe',
@ -185,7 +186,7 @@ module.exports.plugin = function plugin (file, librarySettings, inputs) {
//codec will be checked so it can be transcoded correctly //codec will be checked so it can be transcoded correctly
if (file.video_resolution === '480p' || file.video_resolution === '576p') { if (file.video_resolution === '480p' || file.video_resolution === '576p') {
cqvinuse = `${inputs.sdCQV}` cqvinuse = `${inputs.sdCQV}`
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v ${inputs.sdCQV} -preset ${ffmpeg_preset} -rc-lookahead 32 -bf ${inputs.bframe} -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}` response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc vbr_hq -b:v 0 -preset ${ffmpeg_preset} -cq ${inputs.sdCQV} -rc-lookahead 32 -bf ${inputs.bframe} -a53cc 0 -c:a copy ${subcli}${maxmux}`
transcode = 1 transcode = 1
} }
@ -193,21 +194,21 @@ module.exports.plugin = function plugin (file, librarySettings, inputs) {
//codec will be checked so it can be transcoded correctly //codec will be checked so it can be transcoded correctly
if (file.video_resolution === '720p') { if (file.video_resolution === '720p') {
cqvinuse = `${inputs.hdCQV}` cqvinuse = `${inputs.hdCQV}`
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v ${inputs.hdCQV} -preset ${ffmpeg_preset} -rc-lookahead 32 -bf ${inputs.bframe} -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}` response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc vbr_hq -b:v 0 -preset ${ffmpeg_preset} -cq ${inputs.hdCQV} -rc-lookahead 32 -bf ${inputs.bframe} -a53cc 0 -c:a copy ${subcli}${maxmux}`
transcode = 1 transcode = 1
} }
//file will be encoded if the resolution is 1080p //file will be encoded if the resolution is 1080p
//codec will be checked so it can be transcoded correctly //codec will be checked so it can be transcoded correctly
if (file.video_resolution === '1080p') { if (file.video_resolution === '1080p') {
cqvinuse = `${inputs.fullhdCQV}` cqvinuse = `${inputs.fullhdCQV}`
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v ${inputs.fullhdCQV} -preset ${ffmpeg_preset} -rc-lookahead 32 -bf ${inputs.bframe} -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}` response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc vbr_hq -b:v 0 -preset ${ffmpeg_preset} -cq ${inputs.fullhdCQV} -rc-lookahead 32 -bf ${inputs.bframe} -a53cc 0 -c:a copy ${subcli}${maxmux}`
transcode = 1 transcode = 1
} }
//file will be encoded if the resolution is 4K //file will be encoded if the resolution is 4K
//codec will be checked so it can be transcoded correctly //codec will be checked so it can be transcoded correctly
if (file.video_resolution === '4KUHD') { if (file.video_resolution === '4KUHD') {
cqvinuse = `${inputs.uhdCQV}` cqvinuse = `${inputs.uhdCQV}`
response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc:v vbr_hq -qmin 0 -cq:v ${inputs.uhdCQV} -preset ${ffmpeg_preset} -rc-lookahead 32 -bf ${inputs.bframe} -spatial_aq:v 1 -aq-strength:v 8 -a53cc 0 -c:a copy ${subcli}${maxmux}` response.preset += `,${map} -dn -c:v hevc_nvenc -pix_fmt p010le -rc vbr_hq -b:v 0 -preset ${ffmpeg_preset} -cq ${inputs.uhdCQV} -rc-lookahead 32 -bf ${inputs.bframe} -a53cc 0 -c:a copy ${subcli}${maxmux}`
transcode = 1 transcode = 1
} }
//check if the file is eligible for transcoding //check if the file is eligible for transcoding

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_x7ab_Remove_Subs", id: "Tdarr_Plugin_x7ab_Remove_Subs",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function details() { function details() {
return { return {
id: "Tdarr_Plugin_x7ac_Remove_Closed_Captions", id: "Tdarr_Plugin_x7ac_Remove_Closed_Captions",

View File

@ -1,142 +1,137 @@
function details() { function details() {
return { return {
id: "Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium", id: 'Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "TheRealShadoh FFmpeg Subs Medium, video MP4, audio AAC, keep subs. ", Name: 'TheRealShadoh FFmpeg Subs Medium, video MP4, audio AAC, keep subs. ',
Type: "Video", Type: 'Video',
Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'Medium' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n Description: '[Contains built-in filter] This plugin transcodes into H264 using FFmpeg\'s '
+ '\'Medium\' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata'
+ ` (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n
`, `,
Version: "1.00", Version: '1.00',
Link: Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js", 'https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/'
Tags: "pre-processing,ffmpeg,h264", + 'Tdarr_Plugin_z0ab_TheRealShadoh_FFmpeg_Subs_H264_Medium.js',
Tags: 'pre-processing,ffmpeg,h264',
}; };
} }
function plugin(file) { function plugin(file) {
//Must return this object // Must return this object
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
container: ".mp4", container: '.mp4',
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: false, FFmpegMode: false,
reQueueAfter: false, reQueueAfter: false,
infoLog: "", infoLog: '',
}; };
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
console.log('File is not video');
response.infoLog += "☒File is not video \n"; response.infoLog += '☒File is not video \n';
response.processFile = false; response.processFile = false;
return response; return response;
} else { }
var jsonString = JSON.stringify(file); const jsonString = JSON.stringify(file);
var hasSubs = false; let hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) { for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {
try { try {
let streamData = file.ffProbeData.streams[i]; const streamData = file.ffProbeData.streams[i];
if ( if (
streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_type.toLowerCase() === 'subtitle'
streamData.codec_name != "mov_text" && streamData.codec_name !== 'mov_text'
) { ) {
hasSubs = true; hasSubs = true;
} }
} catch (err) {} } catch (err) {
// err
} }
}
if (file.ffProbeData.streams[0].codec_name != "h264") { if (file.ffProbeData.streams[0].codec_name !== 'h264') {
response.infoLog += "☒File is not in h264! \n"; response.infoLog += '☒File is not in h264! \n';
response.preset = response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a '
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset medium -c:a aac -c:s mov_text"; + '-c:v libx264 -preset medium -c:a aac -c:s mov_text';
response.reQueueAfter = true; response.reQueueAfter = true;
response.processFile = true; response.processFile = true;
response.FFmpegMode = true; response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n";
}
if (!jsonString.includes("aac")) {
response.infoLog += "☒File has no aac track \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n";
return response; return response;
} }
response.infoLog += '☑File is already in h264! \n';
///
if (
file.meta.Title !== undefined
&& !jsonString.includes('aac')
&& hasSubs
) {
response.infoLog += '☒File has title metadata and no aac and subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes('aac') && hasSubs) {
response.infoLog += '☒File has no aac track and has subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title !== undefined && hasSubs) {
response.infoLog += '☒File has title and has subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title !== undefined) {
response.infoLog += '☒File has title metadata \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no title metadata \n';
if (!jsonString.includes('aac')) {
response.infoLog += '☒File has no aac track \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has aac track \n';
if (hasSubs) {
response.infoLog += '☒File has incompatible subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no/compatible subs \n';
response.infoLog += '☑File meets conditions! \n';
return response;
} }
module.exports.details = details; module.exports.details = details;

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_z18s_rename_files_based_on_codec", id: "Tdarr_Plugin_z18s_rename_files_based_on_codec",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports.details = function details() { module.exports.details = function details() {
return { return {
id: "Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution", id: "Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution",

View File

@ -1,143 +1,137 @@
function details() { function details() {
return { return {
id: "Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast", id: 'Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "TheRealShadoh FFmpeg Subs Fast, video MP4, audio AAC, keep subs. ", Name: 'TheRealShadoh FFmpeg Subs Fast, video MP4, audio AAC, keep subs. ',
Type: "Video", Type: 'Video',
Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'Fast' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n Description: '[Contains built-in filter] This plugin transcodes into H264 using '
+ 'FFmpeg\'s \'Fast\' preset if the file is not in H264 already. It maintains all subtitles. '
+ `It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n
`, `,
Version: "1.00", Version: '1.00',
Link: Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js", 'https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/'
Tags: "pre-processing,ffmpeg,h264", + 'Tdarr_Plugin_z1ab_TheRealShadoh_FFmpeg_Subs_H264_Fast.js',
Tags: 'pre-processing,ffmpeg,h264',
}; };
} }
function plugin(file) { function plugin(file) {
//Must return this object // Must return this object
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
container: ".mp4", container: '.mp4',
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: false, FFmpegMode: false,
reQueueAfter: false, reQueueAfter: false,
infoLog: "", infoLog: '',
}; };
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
console.log('File is not video');
response.infoLog += "☒File is not video \n"; response.infoLog += '☒File is not video \n';
response.processFile = false; response.processFile = false;
return response; return response;
} else { }
var jsonString = JSON.stringify(file); const jsonString = JSON.stringify(file);
var hasSubs = false; let hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) { for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {
try { try {
let streamData = file.ffProbeData.streams[i]; const streamData = file.ffProbeData.streams[i];
if ( if (
streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_type.toLowerCase() === 'subtitle'
streamData.codec_name != "mov_text" && streamData.codec_name !== 'mov_text'
) { ) {
hasSubs = true; hasSubs = true;
} }
} catch (err) {} } catch (err) {
// err
} }
}
if (file.ffProbeData.streams[0].codec_name != "h264") { if (file.ffProbeData.streams[0].codec_name !== 'h264') {
response.infoLog += "☒File is not in h264! \n"; response.infoLog += '☒File is not in h264! \n';
response.preset = response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset fast -c:a aac -c:s mov_text';
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset fast -c:a aac -c:s mov_text"; response.reQueueAfter = true;
response.reQueueAfter = true; response.processFile = true;
response.processFile = true; response.FFmpegMode = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n";
}
if (!jsonString.includes("aac")) {
response.infoLog += "☒File has no aac track \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n";
return response; return response;
} }
response.infoLog += '☑File is already in h264! \n';
///
if (
file.meta.Title !== undefined
&& !jsonString.includes('aac')
&& hasSubs
) {
response.infoLog += '☒File has title metadata and no aac and subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes('aac') && hasSubs) {
response.infoLog += '☒File has no aac track and has subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title !== undefined && hasSubs) {
response.infoLog += '☒File has title and has subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title !== undefined) {
response.infoLog += '☒File has title metadata \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no title metadata \n';
if (!jsonString.includes('aac')) {
response.infoLog += '☒File has no aac track \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has aac track \n';
if (hasSubs) {
response.infoLog += '☒File has incompatible subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no/compatible subs \n';
response.infoLog += '☑File meets conditions! \n';
return response;
} }
module.exports.details = details; module.exports.details = details;

View File

@ -1,143 +1,137 @@
function details() { function details() {
return { return {
id: "Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow", id: 'Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: "TheRealShadoh FFmpeg Subs Slow, video MP4, audio AAC, keep subs. ", Name: 'TheRealShadoh FFmpeg Subs Slow, video MP4, audio AAC, keep subs. ',
Type: "Video", Type: 'Video',
Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'Slow' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n Description: '[Contains built-in filter] This plugin transcodes into H264 using FFmpeg\'s \'Slow\' preset'
+ ' if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), '
+ `and maintains all audio tracks. The output container is MP4. \n\n
`, `,
Version: "1.00", Version: '1.00',
Link: Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js", 'https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/'
Tags: "pre-processing,ffmpeg,h264", + 'Tdarr_Plugin_z2ab_TheRealShadoh_FFmpeg_Subs_H264_Slow.js',
Tags: 'pre-processing,ffmpeg,h264',
}; };
} }
function plugin(file) { function plugin(file) {
//Must return this object // Must return this object
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
container: ".mp4", container: '.mp4',
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: false, FFmpegMode: false,
reQueueAfter: false, reQueueAfter: false,
infoLog: "", infoLog: '',
}; };
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
console.log('File is not video');
response.infoLog += "☒File is not video \n"; response.infoLog += '☒File is not video \n';
response.processFile = false; response.processFile = false;
return response; return response;
} else { }
var jsonString = JSON.stringify(file); const jsonString = JSON.stringify(file);
var hasSubs = false; let hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) { for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {
try { try {
let streamData = file.ffProbeData.streams[i]; const streamData = file.ffProbeData.streams[i];
if ( if (
streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_type.toLowerCase() === 'subtitle'
streamData.codec_name != "mov_text" && streamData.codec_name !== 'mov_text'
) { ) {
hasSubs = true; hasSubs = true;
} }
} catch (err) {} } catch (err) {
// err
} }
}
if (file.ffProbeData.streams[0].codec_name != "h264") { if (file.ffProbeData.streams[0].codec_name !== 'h264') {
response.infoLog += "☒File is not in h264! \n"; response.infoLog += '☒File is not in h264! \n';
response.preset = response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset slow -c:a aac -c:s mov_text';
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset slow -c:a aac -c:s mov_text"; response.reQueueAfter = true;
response.reQueueAfter = true; response.processFile = true;
response.processFile = true; response.FFmpegMode = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n";
}
if (!jsonString.includes("aac")) {
response.infoLog += "☒File has no aac track \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n";
return response; return response;
} }
response.infoLog += '☑File is already in h264! \n';
///
if (
file.meta.Title !== undefined
&& !jsonString.includes('aac')
&& hasSubs
) {
response.infoLog += '☒File has title metadata and no aac and subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes('aac') && hasSubs) {
response.infoLog += '☒File has no aac track and has subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title !== undefined && hasSubs) {
response.infoLog += '☒File has title and has subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title !== undefined) {
response.infoLog += '☒File has title metadata \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no title metadata \n';
if (!jsonString.includes('aac')) {
response.infoLog += '☒File has no aac track \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has aac track \n';
if (hasSubs) {
response.infoLog += '☒File has incompatible subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no/compatible subs \n';
response.infoLog += '☑File meets conditions! \n';
return response;
} }
module.exports.details = details; module.exports.details = details;

View File

@ -1,144 +1,139 @@
function details() { function details() {
return { return {
id: "Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast", id: 'Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_VeryFast',
Stage: "Pre-processing", Stage: 'Pre-processing',
Name: Name:
"TheRealShadoh FFmpeg Subs VeryFast, video MP4, audio AAC, keep subs. ", 'TheRealShadoh FFmpeg Subs VeryFast, video MP4, audio AAC, keep subs. ',
Type: "Video", Type: 'Video',
Description: `[Contains built-in filter] This plugin transcodes into H264 using FFmpeg's 'VeryFast' preset if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), and maintains all audio tracks. The output container is MP4. \n\n Description: '[Contains built-in filter] This plugin transcodes into H264 using FFmpeg\'s \'VeryFast\' preset '
+ 'if the file is not in H264 already. It maintains all subtitles. It removes metadata (if a title exists), '
+ `and maintains all audio tracks. The output container is MP4. \n\n
`, `,
Version: "1.00", Version: '1.00',
Link: Link:
"https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_Veryfast.js", 'https://github.com/TheRealShadoh/Tdarr_Plugins/blob/master/Community/'
Tags: "pre-processing,ffmpeg,h264", + 'Tdarr_Plugin_z3ab_TheRealShadoh_FFmpeg_Subs_H264_Veryfast.js',
Tags: 'pre-processing,ffmpeg,h264',
}; };
} }
function plugin(file) { function plugin(file) {
//Must return this object // Must return this object
var response = { const response = {
processFile: false, processFile: false,
preset: "", preset: '',
container: ".mp4", container: '.mp4',
handBrakeMode: false, handBrakeMode: false,
FFmpegMode: false, FFmpegMode: false,
reQueueAfter: false, reQueueAfter: false,
infoLog: "", infoLog: '',
}; };
if (file.fileMedium !== "video") { if (file.fileMedium !== 'video') {
console.log("File is not video"); // eslint-disable-next-line no-console
console.log('File is not video');
response.infoLog += "☒File is not video \n"; response.infoLog += '☒File is not video \n';
response.processFile = false; response.processFile = false;
return response; return response;
} else { }
var jsonString = JSON.stringify(file); const jsonString = JSON.stringify(file);
var hasSubs = false; let hasSubs = false;
for (var i = 0; i < file.ffProbeData.streams.length; i++) { for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {
try { try {
let streamData = file.ffProbeData.streams[i]; const streamData = file.ffProbeData.streams[i];
if ( if (
streamData.codec_type.toLowerCase() == "subtitle" && streamData.codec_type.toLowerCase() === 'subtitle'
streamData.codec_name != "mov_text" && streamData.codec_name !== 'mov_text'
) { ) {
hasSubs = true; hasSubs = true;
} }
} catch (err) {} } catch (err) {
// err
} }
}
if (file.ffProbeData.streams[0].codec_name != "h264") { if (file.ffProbeData.streams[0].codec_name !== 'h264') {
response.infoLog += "☒File is not in h264! \n"; response.infoLog += '☒File is not in h264! \n';
response.preset = response.preset = ', -map_metadata -1 -map 0:v -map 0:s? '
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v libx264 -preset veryfast -c:a aac -c:s mov_text"; + '-map 0:a -c:v libx264 -preset veryfast -c:a aac -c:s mov_text';
response.reQueueAfter = true; response.reQueueAfter = true;
response.processFile = true; response.processFile = true;
response.FFmpegMode = true; response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File is already in h264! \n";
}
///
if (
file.meta.Title != undefined &&
!jsonString.includes("aac") &&
hasSubs
) {
response.infoLog += "☒File has title metadata and no aac and subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes("aac") && hasSubs) {
response.infoLog += "☒File has no aac track and has subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title != undefined && hasSubs) {
response.infoLog += "☒File has title and has subs \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title != undefined) {
response.infoLog += "☒File has title metadata \n";
response.preset =
", -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no title metadata \n";
}
if (!jsonString.includes("aac")) {
response.infoLog += "☒File has no aac track \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has aac track \n";
}
if (hasSubs) {
response.infoLog += "☒File has incompatible subs \n";
response.preset =
", -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text";
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
} else {
response.infoLog += "☑File has no/compatible subs \n";
}
response.infoLog += "☑File meets conditions! \n";
return response; return response;
} }
response.infoLog += '☑File is already in h264! \n';
///
if (
file.meta.Title !== undefined
&& !jsonString.includes('aac')
&& hasSubs
) {
response.infoLog += '☒File has title metadata and no aac and subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (!jsonString.includes('aac') && hasSubs) {
response.infoLog += '☒File has no aac track and has subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
if (file.meta.Title !== undefined && hasSubs) {
response.infoLog += '☒File has title and has subs \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
///
if (file.meta.Title !== undefined) {
response.infoLog += '☒File has title metadata \n';
response.preset = ', -map_metadata -1 -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no title metadata \n';
if (!jsonString.includes('aac')) {
response.infoLog += '☒File has no aac track \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a aac -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has aac track \n';
if (hasSubs) {
response.infoLog += '☒File has incompatible subs \n';
response.preset = ', -map 0:v -map 0:s? -map 0:a -c:v copy -c:a copy -c:s mov_text';
response.reQueueAfter = true;
response.processFile = true;
response.FFmpegMode = true;
return response;
}
response.infoLog += '☑File has no/compatible subs \n';
response.infoLog += '☑File meets conditions! \n';
return response;
} }
module.exports.details = details; module.exports.details = details;

648
README.md
View File

@ -89,243 +89,411 @@ Note, to access FFprobe inside a plugin, use this:
Example file object: Example file object:
let file = { let file = {
_id: 'C:/Users/H/Desktop/Test Input1/Sample.mp4', "meta": {
DB: 'ZRPDmnmpyuAEQi7nG', "SourceFile": "C:/Users/H/Desktop/Transcode/Source/SampleVideo_1280x720_30mb - Copy (5).mp4",
HealthCheck: 'Not attempted', "errors": [],
TranscodeDecisionMaker: 'Not attempted', "Duration": 170.902,
bit_rate: 1690430.4, "PreviewDuration": 0,
container: 'mp4', "SelectionDuration": 0,
createdAt: 2019-09-26T06:46:31.929Z, "TrackDuration": 170.861,
ffProbeData: "MediaDuration": 170.901333333333,
{ streams: "ExifToolVersion": 12.1,
[ { index: 0, "FileName": "SampleVideo_1280x720_30mb - Copy (5).mp4",
codec_name: 'h264', "Directory": "C:/Users/H/Desktop/Transcode/Source",
codec_long_name: 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10', "FileSize": "16 MB",
profile: 'Main', "FileModifyDate": {
codec_type: 'video', "year": 2020,
codec_time_base: '1/50', "month": 12,
codec_tag_string: 'avc1', "day": 26,
codec_tag: '0x31637661', "hour": 12,
width: 1280, "minute": 29,
height: 720, "second": 11,
coded_width: 1280, "millisecond": 0,
coded_height: 720, "tzoffsetMinutes": 60,
has_b_frames: 0, "rawValue": "2020:12:26 12:29:11+01:00"
sample_aspect_ratio: '1:1', },
display_aspect_ratio: '16:9', "FileAccessDate": {
pix_fmt: 'yuv420p', "year": 2020,
level: 31, "month": 12,
chroma_location: 'left', "day": 27,
refs: 1, "hour": 11,
is_avc: 'true', "minute": 42,
nal_length_size: '4', "second": 53,
r_frame_rate: '25/1', "millisecond": 0,
avg_frame_rate: '25/1', "tzoffsetMinutes": 60,
time_base: '1/12800', "rawValue": "2020:12:27 11:42:53+01:00"
start_pts: 0, },
start_time: '0.000000', "FileCreateDate": {
duration_ts: 67584, "year": 2020,
duration: '5.280000', "month": 12,
bit_rate: '1205959', "day": 26,
bits_per_raw_sample: '8', "hour": 12,
nb_frames: '132', "minute": 29,
disposition: "second": 22,
{ default: 1, "millisecond": 0,
dub: 0, "tzoffsetMinutes": 60,
original: 0, "rawValue": "2020:12:26 12:29:22+01:00"
comment: 0, },
lyrics: 0, "FilePermissions": "rw-rw-rw-",
karaoke: 0, "FileType": "MP4",
forced: 0, "FileTypeExtension": "mp4",
hearing_impaired: 0, "MIMEType": "video/mp4",
visual_impaired: 0, "MajorBrand": "MP4 v2 [ISO 14496-14]",
clean_effects: 0, "MinorVersion": "0.2.0",
attached_pic: 0, "CompatibleBrands": [
timed_thumbnails: 0 }, "isom",
tags: "iso2",
{ creation_time: '1970-01-01T00:00:00.000000Z', "avc1",
language: 'und', "mp41"
handler_name: 'VideoHandler' } }, ],
{ index: 1, "MediaDataSize": 16831682,
codec_name: 'aac', "MediaDataOffset": 48,
codec_long_name: 'AAC (Advanced Audio Coding)', "MovieHeaderVersion": 0,
profile: 'LC', "CreateDate": {
codec_type: 'audio', "year": 2020,
codec_time_base: '1/48000', "month": 12,
codec_tag_string: 'mp4a', "day": 26,
codec_tag: '0x6134706d', "hour": 11,
sample_fmt: 'fltp', "minute": 28,
sample_rate: '48000', "second": 53,
channels: 6, "millisecond": 0,
channel_layout: '5.1', "rawValue": "2020:12:26 11:28:53"
bits_per_sample: 0, },
r_frame_rate: '0/0', "ModifyDate": {
avg_frame_rate: '0/0', "year": 2020,
time_base: '1/48000', "month": 12,
start_pts: 0, "day": 26,
start_time: '0.000000', "hour": 11,
duration_ts: 254976, "minute": 28,
duration: '5.312000', "second": 53,
bit_rate: '384828', "millisecond": 0,
max_bit_rate: '400392', "rawValue": "2020:12:26 11:28:53"
nb_frames: '249', },
disposition: "TimeScale": 1000,
{ default: 1, "PreferredRate": 1,
dub: 0, "PreferredVolume": "100.00%",
original: 0, "PreviewTime": "0 s",
comment: 0, "PosterTime": "0 s",
lyrics: 0, "SelectionTime": "0 s",
karaoke: 0, "CurrentTime": "0 s",
forced: 0, "NextTrackID": 3,
hearing_impaired: 0, "TrackHeaderVersion": 0,
visual_impaired: 0, "TrackCreateDate": {
clean_effects: 0, "year": 2020,
attached_pic: 0, "month": 12,
timed_thumbnails: 0 }, "day": 26,
tags: "hour": 11,
{ creation_time: '1970-01-01T00:00:00.000000Z', "minute": 28,
language: 'und', "second": 53,
handler_name: 'SoundHandler' } } ] }, "millisecond": 0,
ffProbeRead: 'success', "rawValue": "2020:12:26 11:28:53"
file: 'C:/Users/H/Desktop/Test Input1/Sample.mp4', },
fileMedium: 'video', "TrackModifyDate": {
file_size: 1.056519, "year": 2020,
meta: "month": 12,
{ SourceFile: 'C:/Users/H/Desktop/Test Input1/Sample.mp4', "day": 26,
errors: [], "hour": 11,
Duration: 5.312, "minute": 28,
PreviewDuration: 0, "second": 53,
SelectionDuration: 0, "millisecond": 0,
TrackDuration: 5.28, "rawValue": "2020:12:26 11:28:53"
MediaDuration: 5.312, },
ExifToolVersion: 11.65, "TrackID": 1,
FileName: 'Sample.mp4', "TrackLayer": 0,
Directory: 'C:/Users/H/Desktop/Test Input1', "TrackVolume": "0.00%",
FileSize: '1032 kB', "ImageWidth": 1280,
FileModifyDate: "ImageHeight": 720,
{ year: 2019, "GraphicsMode": "srcCopy",
month: 9, "OpColor": "0 0 0",
day: 24, "CompressorID": "avc1",
hour: 7, "SourceImageWidth": 1280,
minute: 24, "SourceImageHeight": 720,
second: 22, "XResolution": 72,
millisecond: 0, "YResolution": 72,
tzoffsetMinutes: 60, "BitDepth": 24,
rawValue: '2019:09:24 07:24:22+01:00' }, "PixelAspectRatio": "1:1",
FileAccessDate: "VideoFrameRate": 24.997,
{ year: 2019, "MatrixStructure": "1 0 0 0 1 0 0 0 1",
month: 9, "MediaHeaderVersion": 0,
day: 26, "MediaCreateDate": {
hour: 7, "year": 2020,
minute: 44, "month": 12,
second: 30, "day": 26,
millisecond: 0, "hour": 11,
tzoffsetMinutes: 60, "minute": 28,
rawValue: '2019:09:26 07:44:30+01:00' }, "second": 53,
FileCreateDate: "millisecond": 0,
{ year: 2019, "rawValue": "2020:12:26 11:28:53"
month: 9, },
day: 26, "MediaModifyDate": {
hour: 7, "year": 2020,
minute: 44, "month": 12,
second: 30, "day": 26,
millisecond: 0, "hour": 11,
tzoffsetMinutes: 60, "minute": 28,
rawValue: '2019:09:26 07:44:30+01:00' }, "second": 53,
FilePermissions: 'rw-rw-rw-', "millisecond": 0,
FileType: 'MP4', "rawValue": "2020:12:26 11:28:53"
FileTypeExtension: 'mp4', },
MIMEType: 'video/mp4', "MediaTimeScale": 48000,
MajorBrand: 'MP4 Base Media v1 [IS0 14496-12:2003]', "MediaLanguageCode": "und",
MinorVersion: '0.2.0', "HandlerDescription": "Stereo",
CompatibleBrands: [ 'isom', 'iso2', 'avc1', 'mp41' ], "Balance": 0,
MovieDataSize: 0, "AudioFormat": "mp4a",
MovieDataOffset: 1051515, "AudioChannels": 2,
MovieHeaderVersion: 0, "AudioBitsPerSample": 16,
CreateDate: "AudioSampleRate": 48000,
{ year: 1970, "Track2Name": "Stereo",
month: 1, "Track2Title": "Stereo",
day: 8, "HandlerType": "Metadata",
hour: 0, "HandlerVendorID": "Apple",
minute: 0, "Encoder": "HandBrake 1.3.3 2020061300",
second: 0, "ImageSize": "1280x720",
millisecond: 0, "Megapixels": 0.922,
rawValue: '1970:01:08 00:00:00' }, "AvgBitrate": "788 kbps",
ModifyDate: "Rotation": 0
{ year: 2014, },
month: 7, "mediaInfo": {
day: 19, "@ref": "",
hour: 17, "track": [
minute: 15, {
second: 29, "@type": "General",
millisecond: 0, "VideoCount": "1",
rawValue: '2014:07:19 17:15:29' }, "AudioCount": "1",
TimeScale: 1000, "Format": "MPEG-4",
PreferredRate: 1, "Format_Profile": "Base Media",
PreferredVolume: '100.00%', "CodecID": "mp42",
PreviewTime: '0 s', "CodecID_Compatible": "isom/iso2/avc1/mp41",
PosterTime: '0 s', "FileSize": "16965336",
SelectionTime: '0 s', "Duration": "170.902",
CurrentTime: '0 s', "OverallBitRate": "794155",
NextTrackID: 3, "FrameRate": "25.000",
TrackHeaderVersion: 0, "FrameCount": "4271",
TrackCreateDate: '0000:00:00 00:00:00', "StreamSize": "133654",
TrackModifyDate: '0000:00:00 00:00:00', "HeaderSize": "40",
TrackID: 1, "DataSize": "16831690",
TrackLayer: 0, "FooterSize": "133606",
TrackVolume: '0.00%', "IsStreamable": "No",
ImageWidth: 1280, "Encoded_Date": "UTC 2020-12-26 11:28:53",
ImageHeight: 720, "Tagged_Date": "UTC 2020-12-26 11:28:53",
GraphicsMode: 'srcCopy', "Encoded_Application": "HandBrake 1.3.3 2020061300"
OpColor: '0 0 0', },
CompressorID: 'avc1', {
SourceImageWidth: 1280, "@type": "Video",
SourceImageHeight: 720, "StreamOrder": "0",
XResolution: 72, "ID": "1",
YResolution: 72, "Format": "AVC",
BitDepth: 24, "Format_Profile": "Main",
VideoFrameRate: 25, "Format_Level": "4",
MatrixStructure: '1 0 0 0 1 0 0 0 1', "Format_Settings_CABAC": "Yes",
MediaHeaderVersion: 0, "Format_Settings_RefFrames": "4",
MediaCreateDate: '0000:00:00 00:00:00', "CodecID": "avc1",
MediaModifyDate: '0000:00:00 00:00:00', "Duration": "170.861",
MediaTimeScale: 48000, "BitRate": "627225",
MediaLanguageCode: 'und', "Width": "1280",
HandlerDescription: 'SoundHandler', "Height": "720",
Balance: 0, "Sampled_Width": "1280",
AudioFormat: 'mp4a', "Sampled_Height": "720",
AudioChannels: 2, "PixelAspectRatio": "1.000",
AudioBitsPerSample: 16, "DisplayAspectRatio": "1.778",
AudioSampleRate: 48000, "Rotation": "0.000",
HandlerType: 'Metadata', "FrameRate_Mode": "VFR",
HandlerVendorID: 'Apple', "FrameRate": "25.000",
Encoder: 'Lavf53.24.2', "FrameRate_Minimum": "16.393",
Title: 'Sample title test', "FrameRate_Maximum": "25.000",
Composer: 'th', "FrameCount": "4271",
BeatsPerMinute: '', "ColorSpace": "YUV",
ContentCreateDate: 2018, "ChromaSubsampling": "4:2:0",
Genre: 'this', "BitDepth": "8",
Artist: 'hhj', "ScanType": "Progressive",
Comment: 'hhk', "StreamSize": "13394380",
Subtitle: 'jj', "Encoded_Library": "x264 - core 157 r2935 545de2f",
Mood: 'lik', "Encoded_Library_Name": "x264",
ContentDistributor: 'cont', "Encoded_Library_Version": "core 157 r2935 545de2f",
Conductor: 'jo', "Encoded_Library_Settings": "cabac=1 / ref=1 / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=2 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=0 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=0 / threads=22 / lookahead_threads=5 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=1 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=10 / rc=crf / mbtree=1 / crf=24.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=20000 / vbv_bufsize=25000 / crf_max=0.0 / nal_hrd=none / filler=0 / ip_ratio=1.40 / aq=1:1.00",
Writer: 'writ', "Encoded_Date": "UTC 2020-12-26 11:28:53",
InitialKey: 'ho', "Tagged_Date": "UTC 2020-12-26 11:28:53",
Producer: 'prod', "colour_description_present": "Yes",
ParentalRating: 'par', "colour_description_present_Source": "Stream",
Director: 'dir', "colour_range": "Limited",
Period: 'pol', "colour_range_Source": "Stream",
Publisher: 'pub', "colour_primaries": "BT.709",
PromotionURL: 'prom', "colour_primaries_Source": "Stream",
AuthorURL: 'auth', "transfer_characteristics": "BT.709",
EncodedBy: 'enc', "transfer_characteristics_Source": "Stream",
Category: 'h', "matrix_coefficients": "BT.709",
ImageSize: '1280x720', "matrix_coefficients_Source": "Stream",
Megapixels: 0.922, "extra": {
AvgBitrate: '1.58 Mbps', "CodecConfigurationBox": "avcC"
Rotation: 0 }, }
processingStatus: false, },
video_codec_name: 'h264', {
video_resolution: '720p' } "@type": "Audio",
"StreamOrder": "1",
"ID": "2",
"Format": "AAC",
"Format_Settings_SBR": "No (Explicit)",
"Format_AdditionalFeatures": "LC",
"CodecID": "mp4a-40-2",
"Duration": "170.902",
"BitRate_Mode": "CBR",
"BitRate": "160902",
"Channels": "2",
"ChannelPositions": "Front: L R",
"ChannelLayout": "L R",
"SamplesPerFrame": "1024",
"SamplingRate": "48000",
"SamplingCount": "8203296",
"FrameRate": "46.875",
"FrameCount": "8011",
"Compression_Mode": "Lossy",
"StreamSize": "3437302",
"StreamSize_Proportion": "0.20261",
"Title": "Stereo",
"Default": "Yes",
"AlternateGroup": "1",
"Encoded_Date": "UTC 2020-12-26 11:28:53",
"Tagged_Date": "UTC 2020-12-26 11:28:53"
}
]
},
"hasClosedCaptions": false,
"container": "mp4",
"ffProbeRead": "success",
"ffProbeData": {
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "Main",
"codec_type": "video",
"codec_time_base": "170861/8542000",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 1280,
"height": 720,
"coded_width": 1280,
"coded_height": 720,
"has_b_frames": 2,
"sample_aspect_ratio": "1:1",
"display_aspect_ratio": "16:9",
"pix_fmt": "yuv420p",
"level": 40,
"color_range": "tv",
"color_space": "bt709",
"color_transfer": "bt709",
"color_primaries": "bt709",
"chroma_location": "left",
"refs": 1,
"is_avc": "true",
"nal_length_size": "4",
"r_frame_rate": "50/1",
"avg_frame_rate": "4271000/170861",
"time_base": "1/90000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 15377490,
"duration": "170.861000",
"bit_rate": "627147",
"bits_per_raw_sample": "8",
"nb_frames": "4271",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"creation_time": "2020-12-26T11:28:53.000000Z",
"language": "und",
"handler_name": "VideoHandler"
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"profile": "LC",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "fltp",
"sample_rate": "48000",
"channels": 2,
"channel_layout": "stereo",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 8202240,
"duration": "170.880000",
"bit_rate": "160902",
"max_bit_rate": "160902",
"nb_frames": "8011",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"creation_time": "2020-12-26T11:28:53.000000Z",
"language": "und",
"handler_name": "Stereo"
}
}
]
},
"file_size": 16.179405212402344,
"bit_rate": 794155.0596248143,
"video_resolution": "720p",
"fileMedium": "video",
"video_codec_name": "h264",
"_id": "C:/Users/H/Desktop/Transcode/Source/SampleVideo_1280x720_30mb - Copy (5).mp4",
"file": "C:/Users/H/Desktop/Transcode/Source/SampleVideo_1280x720_30mb - Copy (5).mp4",
"DB": "WratRWZpe",
"lastPluginDetails": "none",
"processingStatus": false,
"createdAt": "2020-12-27T10:42:55.642Z",
"statSync": {
"dev": 3832468976,
"mode": 33206,
"nlink": 1,
"uid": 0,
"gid": 0,
"rdev": 0,
"blksize": 4096,
"ino": 5066549580826442,
"size": 16965336,
"blocks": 33136,
"atimeMs": 1609065774191.6953,
"mtimeMs": 1608982151506.065,
"ctimeMs": 1608982164201.0798,
"birthtimeMs": 1608982162081.075,
"atime": "2020-12-27T10:42:54.192Z",
"mtime": "2020-12-26T11:29:11.506Z",
"ctime": "2020-12-26T11:29:24.201Z",
"birthtime": "2020-12-26T11:29:22.081Z"
},
"history": ""
}

View File

@ -1,21 +1,25 @@
var fs = require("fs"); const fs = require('fs');
var path = require("path"); const path = require('path');
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd(), "/npm/node_modules/"); let rootModules;
if (fs.existsSync(path.join(process.cwd(), '/npm'))) {
rootModules = path.join(process.cwd(), '/npm/node_modules/');
} else { } else {
var rootModules = ""; rootModules = '';
} }
const importFresh = require(rootModules + "import-fresh");
// eslint-disable-next-line import/no-dynamic-require
const importFresh = require(`${rootModules}import-fresh`);
module.exports.remuxContainer = importFresh( module.exports.remuxContainer = importFresh(
"./library/actions/remuxContainer.js" './library/actions/remuxContainer.js',
); );
module.exports.transcodeStandardiseAudioCodecs = importFresh( module.exports.transcodeStandardiseAudioCodecs = importFresh(
"./library/actions/transcodeStandardiseAudioCodecs.js" './library/actions/transcodeStandardiseAudioCodecs.js',
); );
module.exports.transcodeAddAudioStream = importFresh( module.exports.transcodeAddAudioStream = importFresh(
"./library/actions/transcodeAddAudioStream.js" './library/actions/transcodeAddAudioStream.js',
); );
module.exports.transcodeKeepOneAudioStream = importFresh( module.exports.transcodeKeepOneAudioStream = importFresh(
"./library/actions/transcodeKeepOneAudioStream.js" './library/actions/transcodeKeepOneAudioStream.js',
); );

View File

@ -1,3 +1,4 @@
/* eslint-disable */
var fs = require("fs"); var fs = require("fs");
var path = require("path"); var path = require("path");
if (fs.existsSync(path.join(process.cwd(), "/npm"))) { if (fs.existsSync(path.join(process.cwd(), "/npm"))) {

View File

@ -1,3 +1,4 @@
/* eslint-disable */
var fs = require("fs"); var fs = require("fs");
var path = require("path"); var path = require("path");
if (fs.existsSync(path.join(process.cwd(), "/npm"))) { if (fs.existsSync(path.join(process.cwd(), "/npm"))) {

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function remuxContainer(file, container) { function remuxContainer(file, container) {
try { try {
if (file.container != container) { if (file.container != container) {

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports = function transcodeAddAudioStream( module.exports = function transcodeAddAudioStream(
file, file,
audioEncoder, audioEncoder,

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports = function transcodeKeepOneAudioStream( module.exports = function transcodeKeepOneAudioStream(
file, file,
audioEncoder, audioEncoder,

View File

@ -1,3 +1,4 @@
/* eslint-disable */
module.exports = function transcodeStandardiseAudioCodecs(file, audioEncoder) { module.exports = function transcodeStandardiseAudioCodecs(file, audioEncoder) {
//Function required responses //Function required responses
// preset // preset

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function filterByAge(file, ageCutOff_Seconds) { function filterByAge(file, ageCutOff_Seconds) {
try { try {
var timeNow = new Date(); var timeNow = new Date();

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function filterByCodec(file, mode, codecs) { function filterByCodec(file, mode, codecs) {
try { try {
// console.log(file,mode,codecs) // console.log(file,mode,codecs)

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function filterByMedium(file, medium) { function filterByMedium(file, medium) {
try { try {
if (file.fileMedium !== medium) { if (file.fileMedium !== medium) {

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function filterByResolution(file, mode, resolution) { function filterByResolution(file, mode, resolution) {
try { try {
if (mode === "exclude") { if (mode === "exclude") {

View File

@ -1,3 +1,4 @@
/* eslint-disable */
function filterBySize(file, lowerBound, upperBound) { function filterBySize(file, lowerBound, upperBound) {
try { try {
if ( if (

15
node_modules/.bin/prettier generated vendored
View File

@ -1,15 +0,0 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../prettier/bin-prettier.js" "$@"
ret=$?
else
node "$basedir/../prettier/bin-prettier.js" "$@"
ret=$?
fi
exit $ret

17
node_modules/.bin/prettier.cmd generated vendored
View File

@ -1,17 +0,0 @@
@ECHO off
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
"%_prog%" "%dp0%\..\prettier\bin-prettier.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b

18
node_modules/.bin/prettier.ps1 generated vendored
View File

@ -1,18 +0,0 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
& "$basedir/node$exe" "$basedir/../prettier/bin-prettier.js" $args
$ret=$LASTEXITCODE
} else {
& "node$exe" "$basedir/../prettier/bin-prettier.js" $args
$ret=$LASTEXITCODE
}
exit $ret

7
node_modules/prettier/LICENSE generated vendored
View File

@ -1,7 +0,0 @@
Copyright © James Long and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

111
node_modules/prettier/README.md generated vendored
View File

@ -1,111 +0,0 @@
![Prettier Banner](https://raw.githubusercontent.com/prettier/prettier-logo/master/images/prettier-banner-light.png)
<h2 align="center">Opinionated Code Formatter</h2>
<p align="center">
<em>
JavaScript
· TypeScript
· Flow
· JSX
· JSON
</em>
<br />
<em>
CSS
· SCSS
· Less
</em>
<br />
<em>
HTML
· Vue
· Angular
</em>
<br />
<em>
GraphQL
· Markdown
· YAML
</em>
<br />
<em>
<a href="https://prettier.io/docs/en/plugins.html">
Your favorite language?
</a>
</em>
</p>
<p align="center">
<a href="https://github.com/prettier/prettier/actions?query=workflow%3AProd+branch%3Amaster">
<img alt="Github Actions Build Status" src="https://img.shields.io/github/workflow/status/prettier/prettier/Prod?label=Prod&style=flat-square"></a>
<a href="https://github.com/prettier/prettier/actions?query=workflow%3ADev+branch%3Amaster">
<img alt="Github Actions Build Status" src="https://img.shields.io/github/workflow/status/prettier/prettier/Dev?label=Dev&style=flat-square"></a>
<a href="https://github.com/prettier/prettier/actions?query=workflow%3ALint+branch%3Amaster">
<img alt="Github Actions Build Status" src="https://img.shields.io/github/workflow/status/prettier/prettier/Lint?label=Lint&style=flat-square"></a>
<a href="https://codecov.io/gh/prettier/prettier">
<img alt="Codecov Coverage Status" src="https://img.shields.io/codecov/c/github/prettier/prettier.svg?style=flat-square"></a>
<a href="https://twitter.com/acdlite/status/974390255393505280">
<img alt="Blazing Fast" src="https://img.shields.io/badge/speed-blazing%20%F0%9F%94%A5-brightgreen.svg?style=flat-square"></a>
<br/>
<a href="https://www.npmjs.com/package/prettier">
<img alt="npm version" src="https://img.shields.io/npm/v/prettier.svg?style=flat-square"></a>
<a href="https://www.npmjs.com/package/prettier">
<img alt="weekly downloads from npm" src="https://img.shields.io/npm/dw/prettier.svg?style=flat-square"></a>
<a href="#badge">
<img alt="code style: prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square"></a>
<a href="https://gitter.im/jlongster/prettier">
<img alt="Chat on Gitter" src="https://img.shields.io/gitter/room/jlongster/prettier.svg?style=flat-square"></a>
<a href="https://twitter.com/PrettierCode">
<img alt="Follow Prettier on Twitter" src="https://img.shields.io/twitter/follow/prettiercode.svg?label=follow+prettier&style=flat-square"></a>
</p>
## Intro
Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.
### Input
<!-- prettier-ignore -->
```js
foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne());
```
### Output
```js
foo(
reallyLongArg(),
omgSoManyParameters(),
IShouldRefactorThis(),
isThereSeriouslyAnotherOne()
);
```
Prettier can be run [in your editor](http://prettier.io/docs/en/editors.html) on-save, in a [pre-commit hook](https://prettier.io/docs/en/precommit.html), or in [CI environments](https://prettier.io/docs/en/cli.html#list-different) to ensure your codebase has a consistent style without devs ever having to post a nit-picky comment on a code review ever again!
---
**[Documentation](https://prettier.io/docs/en/)**
<!-- prettier-ignore -->
[Install](https://prettier.io/docs/en/install.html) ·
[Options](https://prettier.io/docs/en/options.html) ·
[CLI](https://prettier.io/docs/en/cli.html) ·
[API](https://prettier.io/docs/en/api.html)
**[Playground](https://prettier.io/playground/)**
---
## Badge
Show the world you're using _Prettier_ → [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
```md
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
```
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).

54351
node_modules/prettier/bin-prettier.js generated vendored

File diff suppressed because one or more lines are too long

2137
node_modules/prettier/doc.js generated vendored

File diff suppressed because one or more lines are too long

51680
node_modules/prettier/index.js generated vendored

File diff suppressed because one or more lines are too long

56
node_modules/prettier/package.json generated vendored
View File

@ -1,56 +0,0 @@
{
"_from": "prettier",
"_id": "prettier@2.0.5",
"_inBundle": false,
"_integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
"_location": "/prettier",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "prettier",
"name": "prettier",
"escapedName": "prettier",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#DEV:/",
"#USER"
],
"_resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
"_shasum": "d6d56282455243f2f92cc1716692c08aa31522d4",
"_spec": "prettier",
"_where": "C:\\Users\\H\\Documents\\GitHub\\Tdarr_Plugins",
"author": {
"name": "James Long"
},
"bin": {
"prettier": "bin-prettier.js"
},
"bugs": {
"url": "https://github.com/prettier/prettier/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Prettier is an opinionated code formatter",
"engines": {
"node": ">=10.13.0"
},
"files": [
"*.js"
],
"homepage": "https://prettier.io",
"license": "MIT",
"main": "./index.js",
"name": "prettier",
"repository": {
"type": "git",
"url": "git+https://github.com/prettier/prettier.git"
},
"scripts": {
"prepublishOnly": "node -e \"assert.equal(require('.').version, require('..').version)\""
},
"version": "2.0.5"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More