Merge branch 'master' into patch-1

make-only-subtitle-default
HaveAGitGat 4 years ago committed by GitHub
commit 67e4f71b43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,10 @@
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
/* eslint-disable */
/* eslint max-len: 0 */
/* eslint no-bitwise: 0 */
/* eslint no-mixed-operators: 0 */
const os = require('os');
function details() {
return {
id: 'Tdarr_Plugin_ER01_Transcode audio and video with HW (PC and Mac)',
@ -8,10 +13,10 @@ function details() {
Type: 'Video',
Operation: 'Transcode',
Description: `Files not in H265 will be transcoded into H265 using hw with ffmpeg, assuming mkv container. Plugin uses QS if the node runs on a PC, or Videotoolbox if run on a Mac.
Much thanks to Migz for bulk of the important code.
Much thanks to Migz for bulk of the important code.
Quality is controlled via bitrate adjustments - H264 to H265 assumes 0.5x bitrate. Resolution change from 1080p to 720p assumes 0.7x bitrate.
Audio conversion is either 2 channel ac3 or 6 channel ac3, for maximal compatibility and small file size. All subtitles removed.
The idea is to homogenize your collection to 1080p or higher movies with 5.1 audio, or 720p TV shows with 2.0 audio.`,
The idea is to homogenize your collection to 1080p or higher movies with 5.1 audio, or 720p TV shows with 2.0 audio.`,
Tags: 'pre-processing,ffmpeg,video only,configurable,h265',
Inputs: [{
@ -33,7 +38,7 @@ function details() {
\\nExample:\\n
no`,
},
{
{
name: 'bitrate_cutoff',
tooltip: `Specify bitrate cutoff, files with a current bitrate lower then this will not be transcoded.
\\n Rate is in kbps.
@ -65,7 +70,7 @@ function plugin(file, librarySettings, inputs) {
let convertAudio = false;
let convertVideo = false;
let extraArguments = '';
// Check if inputs.container has been configured. If it hasn't then exit plugin.
if (inputs.container === '') {
response.infoLog += 'Plugin has not been configured, please configure required options. Skipping this plugin. \n';
@ -80,23 +85,20 @@ function plugin(file, librarySettings, inputs) {
return response;
}
const os = require('os');
// VIDEO SECTION
let bitRateMultiplier = 1.00;
let videoIdx = -1;
let willBeResized = false;
let videoOptions = '-map 0:v -c:v copy ';
// VIDEO SECTION
let bitRateMultiplier = 1.00;
let videoIdx = -1;
let willBeResized = false;
let videoOptions = `-map 0:v -c:v copy `;
// video options
// hevc, 1080, false - do nothing
// hevc, not 1080 - do nothing
// hevc, 1080, true - resize, mult 0.5
// not hevc, 1080, true - resize, mult 0.25
// not hevc, 1080, false - no resize, mult 0.5
// not hevc, not 1080 - no resize, mult 0.5
// video options
// hevc, 1080, false - do nothing
// hevc, not 1080 - do nothing
// hevc, 1080, true - resize, mult 0.5
// not hevc, 1080, true - resize, mult 0.25
// not hevc, 1080, false - no resize, mult 0.5
// not hevc, not 1080 - no resize, mult 0.5
// Go through each stream in the file.
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
@ -104,44 +106,50 @@ let videoOptions = `-map 0:v -c:v copy `;
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'video') {
// Check if codec of stream is mjpeg/png. If so then remove this "video" stream.
// mjpeg/png are usually embedded pictures that can cause havoc with plugins.
if (file.ffProbeData.streams[i].codec_name === 'mjpeg' || file.ffProbeData.streams[i].codec_name === 'png' ) {
if (file.ffProbeData.streams[i].codec_name === 'mjpeg' || file.ffProbeData.streams[i].codec_name === 'png') {
extraArguments += `-map -v:${videoIdx} `;
convertVideo = true; }
/* // no video conversion if: hevc, 1080, false OR hevc, not 1080
if (file.ffProbeData.streams[i].codec_name === 'hevc'
&& ((file.video_resolution === '1080p' && inputs.resize === 'no' ) || (file.video_resolution !== '1080p' ))) {
convertVideo = true;
}
/* // no video conversion if: hevc, 1080, false OR hevc, not 1080
if (file.ffProbeData.streams[i].codec_name === 'hevc'
&& ((file.video_resolution === '1080p' && inputs.resize === 'no' ) || (file.video_resolution !== '1080p' ))) {
convertVideo = false; } */
// no video conversion if: hevc, 1080, false
if (file.ffProbeData.streams[i].codec_name === 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'no' ) {
convertVideo = false; }
// no video conversion if: hevc, not 1080
if (file.ffProbeData.streams[i].codec_name === 'hevc' && (file.ffProbeData.streams[i].width < 1800 || file.ffProbeData.streams[i].width > 2000)) {
convertVideo = false; }
// resize video if: hevc, 1080, true
if (file.ffProbeData.streams[i].codec_name === 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'yes' ) {
if (file.ffProbeData.streams[i].codec_name === 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'no') {
convertVideo = false;
}
// no video conversion if: hevc, not 1080
if (file.ffProbeData.streams[i].codec_name === 'hevc' && (file.ffProbeData.streams[i].width < 1800 || file.ffProbeData.streams[i].width > 2000)) {
convertVideo = false;
}
// resize video if: hevc, 1080, true
if (file.ffProbeData.streams[i].codec_name === 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'yes') {
convertVideo = true;
willBeResized = true;
bitRateMultiplier = 0.7; }
// resize video if: not hevc, 1080, true
if (file.ffProbeData.streams[i].codec_name !== 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'yes' ) {
willBeResized = true;
bitRateMultiplier = 0.7;
}
// resize video if: not hevc, 1080, true
if (file.ffProbeData.streams[i].codec_name !== 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'yes') {
convertVideo = true;
willBeResized = true;
bitRateMultiplier = 0.4; }
// no resize video if: not hevc, 1080, false
if (file.ffProbeData.streams[i].codec_name !== 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'no' ) {
willBeResized = true;
bitRateMultiplier = 0.4;
}
// no resize video if: not hevc, 1080, false
if (file.ffProbeData.streams[i].codec_name !== 'hevc' && file.ffProbeData.streams[i].width > 1800 && file.ffProbeData.streams[i].width < 2000 && inputs.resize === 'no') {
convertVideo = true;
bitRateMultiplier = 0.5; }
// no resize video if: not hevc, not 1080
if (file.ffProbeData.streams[i].codec_name !== 'hevc' && file.ffProbeData.streams[i].width < 1800 ) {
bitRateMultiplier = 0.5;
}
// no resize video if: not hevc, not 1080
if (file.ffProbeData.streams[i].codec_name !== 'hevc' && file.ffProbeData.streams[i].width < 1800) {
convertVideo = true;
bitRateMultiplier = 0.5; }
bitRateMultiplier = 0.5;
}
// Increment videoIdx.
videoIdx += 1;
}
// Increment videoIdx.
videoIdx += 1;
}
// figure out final bitrate
// figure out final bitrate
// Check if duration info is filled, if so times it by 0.0166667 to get time in minutes.
// If not filled then get duration of stream 0 and do the same.
if (typeof file.meta.Duration !== 'undefined') {
@ -169,21 +177,21 @@ let videoOptions = `-map 0:v -c:v copy `;
response.infoLog += 'Target bitrate could not be calculated. Skipping this plugin. \n';
return response;
}
// Check if inputs.bitrate cutoff has something entered.
// Check if inputs.bitrate cutoff has something entered.
// (Entered means user actually wants something to happen, empty would disable this).
if (inputs.bitrate_cutoff !== '') {
// Checks if currentBitrate is below inputs.bitrate_cutoff
// If so then don't convert video.
if (currentBitrate <= inputs.bitrate_cutoff) {
convertVideo = false; }
convertVideo = false;
}
}
// AUDIO SECTION
// AUDIO SECTION
// Set up required variables.
let audioOptions = `-map 0:a -c:a copy `;
// Set up required variables.
let audioOptions = '-map 0:a -c:a copy ';
let audioIdx = 0;
let numberofAudioChannels = 0;
let has2Channels = false;
@ -197,197 +205,194 @@ let videoOptions = `-map 0:v -c:v copy `;
let type8Channels = '';
let keepAudioIdx = -1;
let keepIGuessAudioIdx = -1;
// const keepIGuessAudioIdx = -1;
let encodeAudioIdx = -1;
let keepAudioStream = -1;
let encodeAudioStream = -1;
let originalAudio = '';
// Go through each stream in the file.
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
// Go through all audio streams and check if 2,6 & 8 channel tracks exist or not.
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
numberofAudioChannels += 1;
if (file.ffProbeData.streams[i].channels === 2 && has2Channels === false) {
has2Channels = true;
lang2Channels = file.ffProbeData.streams[i].tags.language.toLowerCase();
type2Channels = file.ffProbeData.streams[i].codec_name.toLowerCase();
if (file.ffProbeData.streams[i].channels === 2 && has2Channels === false) {
has2Channels = true;
lang2Channels = file.ffProbeData.streams[i].tags.language.toLowerCase();
type2Channels = file.ffProbeData.streams[i].codec_name.toLowerCase();
}
if (file.ffProbeData.streams[i].channels === 6 && has6Channels === false) {
has6Channels = true;
lang6Channels = file.ffProbeData.streams[i].tags.language.toLowerCase();
type6Channels = file.ffProbeData.streams[i].codec_name.toLowerCase();
has6Channels = true;
lang6Channels = file.ffProbeData.streams[i].tags.language.toLowerCase();
type6Channels = file.ffProbeData.streams[i].codec_name.toLowerCase();
}
if (file.ffProbeData.streams[i].channels === 8 && has8Channels === false) {
has8Channels = true;
lang8Channels = file.ffProbeData.streams[i].tags.language.toLowerCase();
type8Channels = file.ffProbeData.streams[i].codec_name.toLowerCase();
has8Channels = true;
lang8Channels = file.ffProbeData.streams[i].tags.language.toLowerCase();
type8Channels = file.ffProbeData.streams[i].codec_name.toLowerCase();
}
}
} catch (err) {
// Error
}
}
// Are we processing for 6 channels?
if (inputs.audio_channels == 6) {
audioIdx = -1;
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
audioIdx += 1;
if (file.ffProbeData.streams[i].tags.language.toLowerCase() === 'eng' || file.ffProbeData.streams[i].tags.language.toLowerCase() === 'und') {
if (file.ffProbeData.streams[i].channels == 6 ) {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() === 'ac3') {
//response.infoLog += `Found 6 channel audio in proper language and codec, audio stream ${audioIdx}\n`;
if (keepAudioIdx === -1) {
keepAudioIdx = audioIdx;
keepAudioStream = i;}
} else {
//response.infoLog += `Found 6 channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
if (encodeAudioIdx === -1) {
encodeAudioIdx = audioIdx;
encodeAudioStream = i;}
}}
if (file.ffProbeData.streams[i].channels > 6 ) {
//response.infoLog += `Found existing multi-channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
if (encodeAudioIdx === -1) {
encodeAudioIdx = audioIdx;
encodeAudioStream = i;}
}
}
}
} catch (err) {
// Error
}
// Are we processing for 6 channels?
if (inputs.audio_channels === 6) {
audioIdx = -1;
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
audioIdx += 1;
if (file.ffProbeData.streams[i].tags.language.toLowerCase() === 'eng' || file.ffProbeData.streams[i].tags.language.toLowerCase() === 'und') {
if (file.ffProbeData.streams[i].channels === 6) {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() === 'ac3') {
// response.infoLog += `Found 6 channel audio in proper language and codec, audio stream ${audioIdx}\n`;
if (keepAudioIdx === -1) {
keepAudioIdx = audioIdx;
keepAudioStream = i;
}
} else if (encodeAudioIdx === -1) {
// response.infoLog += `Found 6 channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
encodeAudioIdx = audioIdx;
encodeAudioStream = i;
}
}
if (file.ffProbeData.streams[i].channels > 6) {
// response.infoLog += `Found existing multi-channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
if (encodeAudioIdx === -1) {
encodeAudioIdx = audioIdx;
encodeAudioStream = i;
}
}
}
}
} catch (err) {
// Error
}
}
}
if (keepAudioIdx === -1 && encodeAudioIdx === -1) { // didn't find any 5.1 or better audio streams in proper language, defaulting to using 2 channels
inputs.audio_channels = '2';}
}
// Are we processing for 2 channels?
if (inputs.audio_channels == 2) {
audioIdx = -1;
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
audioIdx += 1;
if (file.ffProbeData.streams[i].tags.language.toLowerCase() === 'eng' || file.ffProbeData.streams[i].tags.language.toLowerCase() === 'und') {
if (file.ffProbeData.streams[i].channels == 2 ) {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() === 'aac' || file.ffProbeData.streams[i].codec_name.toLowerCase() === 'ac3') {
//response.infoLog += `Found 2 channel audio in proper language and codec, audio stream ${audioIdx}\n`;
if (keepAudioIdx === -1) {
keepAudioIdx = audioIdx;
keepAudioStream = i;}
} else {
//response.infoLog += `Found 2 channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
if (encodeAudioIdx === -1) {
encodeAudioIdx = audioIdx;
encodeAudioStream = i;}
}
} else {
//response.infoLog += `Found existing multi-channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
if (encodeAudioIdx === -1) {
encodeAudioIdx = audioIdx;
encodeAudioStream = i;}
}
}
// response.infoLog += `a ${audioIdx}. k ${keepAudioIdx}. e ${encodeAudioIdx}\n `;
}
} catch (err) {
// Error
if (keepAudioIdx === -1 && encodeAudioIdx === -1) { // didn't find any 5.1 or better audio streams in proper language, defaulting to using 2 channels
// eslint-disable-next-line no-param-reassign
inputs.audio_channels = '2';
}
}
}
}
// Are we processing for 2 channels?
if (inputs.audio_channels === 2) {
audioIdx = -1;
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
audioIdx += 1;
if (file.ffProbeData.streams[i].tags.language.toLowerCase() === 'eng' || file.ffProbeData.streams[i].tags.language.toLowerCase() === 'und') {
if (file.ffProbeData.streams[i].channels === 2) {
if (file.ffProbeData.streams[i].codec_name.toLowerCase() === 'aac' || file.ffProbeData.streams[i].codec_name.toLowerCase() === 'ac3') {
// response.infoLog += `Found 2 channel audio in proper language and codec, audio stream ${audioIdx}\n`;
if (keepAudioIdx === -1) {
keepAudioIdx = audioIdx;
keepAudioStream = i;
}
} else if (encodeAudioIdx === -1) {
// response.infoLog += `Found 2 channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
encodeAudioIdx = audioIdx;
encodeAudioStream = i;
}
} else if (encodeAudioIdx === -1) {
// response.infoLog += `Found existing multi-channel audio in proper language, need to re-encode, audio stream ${audioIdx}\n`;
encodeAudioIdx = audioIdx;
encodeAudioStream = i;
}
}
// response.infoLog += `a ${audioIdx}. k ${keepAudioIdx}. e ${encodeAudioIdx}\n `;
}
} catch (err) {
// Error
}
}
}
let audioMessage = '';
// selecting channels to keep, only if 2 or 6 channels processed
// selecting channels to keep, only if 2 or 6 channels processed
if (keepAudioIdx !== -1) {
//keep audio, exclude everything else
if (numberofAudioChannels !== 1) {
convertAudio = true;
audioMessage += `keeping audio stream ${keepAudioIdx}.`;
audioOptions = `-map 0:a:${keepAudioIdx} -c:a copy `;
originalAudio += `${file.ffProbeData.streams[keepAudioStream].channels} channel ${file.ffProbeData.streams[keepAudioStream].codec_name} --> ${inputs.audio_channels} channel ac3`;}
// keep audio, exclude everything else
if (numberofAudioChannels !== 1) {
convertAudio = true;
audioMessage += `keeping audio stream ${keepAudioIdx}.`;
audioOptions = `-map 0:a:${keepAudioIdx} -c:a copy `;
originalAudio += `${file.ffProbeData.streams[keepAudioStream].channels} channel ${file.ffProbeData.streams[keepAudioStream].codec_name} --> ${inputs.audio_channels} channel ac3`;
}
} else if (encodeAudioIdx !== -1) {
// encode this audio
convertAudio = true;
audioMessage += `encoding audio stream ${encodeAudioIdx}. `;
audioOptions = `-map 0:a:${encodeAudioIdx} -c:a ac3 -ac ${inputs.audio_channels} `; // 2 or 6 channels encoding
originalAudio += `${file.ffProbeData.streams[encodeAudioStream].channels} channel ${file.ffProbeData.streams[encodeAudioStream].codec_name} --> ${inputs.audio_channels} channel ac3`;
} else {
if (encodeAudioIdx !== -1) {
// encode this audio
convertAudio = true;
audioMessage += `encoding audio stream ${encodeAudioIdx}. `;
audioOptions = `-map 0:a:${encodeAudioIdx} -c:a ac3 -ac ${inputs.audio_channels} `; // 2 or 6 channels encoding
originalAudio += `${file.ffProbeData.streams[encodeAudioStream].channels} channel ${file.ffProbeData.streams[encodeAudioStream].codec_name} --> ${inputs.audio_channels} channel ac3`;
} else {
// do not encode audio
convertAudio = false;
audioMessage += `no audio to encode.`;
}
// do not encode audio
convertAudio = false;
audioMessage += 'no audio to encode.';
}
// test for whether the file needs to be processed - separate for video and audio convertAudio, convertVideo
// test for whether the file needs to be processed - separate for video and audio convertAudio, convertVideo
if (convertAudio === false && convertVideo === false) { // if nothing to do, exit
response.infoLog += `File is processed already, nothing to do`;
response.processFile = false;
return response; }
response.infoLog += 'File is processed already, nothing to do';
response.processFile = false;
return response;
}
// Generate ffmpeg command line arguments in total
// Generate ffmpeg command line arguments in total
// few defaults
response.preset = `, -sn `;
response.preset = ', -sn ';
if (convertVideo === true) {
// Set bitrateSettings variable using bitrate information calculated earlier.
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k `
+ `-maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`;
// Set bitrateSettings variable using bitrate information calculated earlier.
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k `
+ `-maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`;
if (willBeResized === true) {
extraArguments += `-filter:v scale=1280:-1 `; }
if (willBeResized === true) {
extraArguments += '-filter:v scale=1280:-1 ';
}
if (os.platform() === 'darwin') {
videoOptions = `-map 0:v -c:v hevc_videotoolbox -profile main `;
}
if (os.platform() === 'darwin') {
videoOptions = '-map 0:v -c:v hevc_videotoolbox -profile main ';
}
if (os.platform() === 'win32') {
videoOptions = `-map 0:v -c:v hevc_qsv -load_plugin hevc_hw `;
}
if (os.platform() === 'win32') {
videoOptions = '-map 0:v -c:v hevc_qsv -load_plugin hevc_hw ';
}
}
response.preset += `${videoOptions} ${bitrateSettings} ${extraArguments} ${audioOptions} `;
let outputResolution = file.video_resolution;
if (willBeResized === true) {
outputResolution = '720p';}
outputResolution = '720p';
}
if (convertVideo === false) {
response.infoLog += `NOT converting video ${file.video_resolution}, ${file.video_codec_name}, bitrate = ${currentBitrate} \n`;
response.infoLog += `NOT converting video ${file.video_resolution}, ${file.video_codec_name}, bitrate = ${currentBitrate} \n`;
} else {
response.infoLog += `Converting video, `;
if (willBeResized === false ) { response.infoLog += `NOT `; }
response.infoLog += `resizing. ${file.video_resolution}, ${file.video_codec_name} --> ${outputResolution}, hevc. bitrate = ${currentBitrate} --> ${targetBitrate}, multiplier ${bitRateMultiplier}. \n`;
response.infoLog += 'Converting video, ';
if (willBeResized === false) { response.infoLog += 'NOT '; }
response.infoLog += `resizing. ${file.video_resolution}, ${file.video_codec_name} --> ${outputResolution}, hevc. bitrate = ${currentBitrate} --> ${targetBitrate}, multiplier ${bitRateMultiplier}. \n`;
}
if (convertAudio === true) {
response.infoLog += `Converting audio, ${audioMessage} ${originalAudio}. \n`;
response.infoLog += `Converting audio, ${audioMessage} ${originalAudio}. \n`;
} else {
response.infoLog += `Not converting audio. \n`;}
response.infoLog += 'Not converting audio. \n';
}
response.infoLog += `2 channels - ${lang2Channels} ${type2Channels} \n`;
response.infoLog += `6 channels - ${lang6Channels} ${type6Channels} \n`;
response.infoLog += `8 channels - ${lang8Channels} ${type8Channels} `;
response.processFile = true;
return response;
}

@ -34,7 +34,7 @@
// If the source video is less than this rate the script will either:
// Copy the existing stream, if the codec is hevc
// Transcode the stream to hevc using 80% of the original streams bitrate
// It could probably be less but if the source is of low bitrate we dont want to compromise too much on the transcode
// It could probably be less but if the source is of low bitrate we don<EFBFBD>t want to compromise too much on the transcode
//
// If the source media bitrate is close, within 10%, of the target bitrate and the codec is hevc, it will copy instead of transcode to preserve quality
//
@ -53,7 +53,7 @@
// If the source audio is less than this rate the script will either:
// Copy the existing stream, if the codec is aac
// Transcode the stream to aac using 100% of the original streams bitrate
// It could probably be less but if the source is of low bitrate but, we dont want to compromise too much on the transcode
// It could probably be less but if the source is of low bitrate but, we don<EFBFBD>t want to compromise too much on the transcode
//
// Subtitles:
// All are removed?? (TODO: ensure this is correct and mention the flag to keep them if desired)
@ -761,7 +761,7 @@ function findMediaInfoItem(file, index) {
currMIOrder = file.mediaInfo.track[i].ID - 1;
}
if (currMIOrder == index || currMIOrder == "0-" + index) {
if (currMIOrder == index|| currMIOrder == "0-" + index) {
return i;
}
}

@ -123,7 +123,7 @@ function plugin(file, librarySettings, inputs) {
response.preset =
", -map_metadata -1 -map 0:V " +
subMap +
" -map 0:a -c:v libx264 -preset medium -c:a aac -strict -2 " +
" -map 0:a -c:v libx264 -preset " + preset + " -c:a aac -strict -2 " +
subType;
response.reQueueAfter = true;
response.processFile = true;

@ -10,7 +10,7 @@ const details = () => ({
(requires TMDB api key) and English.
'Native' languages are the ones that are listed on imdb. It does an API call to
Radarr, Sonarr to check if the movie/series exists and grabs the IMDB id. As a last resort it
falls back to '[imdb-ttDIGITS] in the filename.`,
falls back to the IMDB id in the filename.`,
Version: '1.00',
Link: 'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/'
+ 'Tdarr_Plugin_henk_Keep_Native_Lang_Plus_Eng.js',
@ -32,7 +32,7 @@ const details = () => ({
},
{
name: 'api_key',
tooltip: 'Input your TMDB api key here. (https://www.themoviedb.org/)',
tooltip: 'Input your TMDB api (v3) key here. (https://www.themoviedb.org/)',
},
{
name: 'radarr_api_key',
@ -139,7 +139,7 @@ const tmdbApi = async (filename, api_key, axios) => {
if (filename.substr(0, 2) === 'tt') {
fileName = filename;
} else {
const idRegex = /\[imdb-(tt\d*)]/;
const idRegex = /(tt\d{7,8})/;
const fileMatch = filename.match(idRegex);
// eslint-disable-next-line prefer-destructuring
if (fileMatch) fileName = fileMatch[1];

@ -72,6 +72,20 @@ function details() {
\\nExample:\\n
veryfast`,
},
{
name: 'sdDisabled',
tooltip: `Input "true" if you want to skip SD (480p and 576p) files
\\nExample:\\n
true`,
},
{
name: 'uhdDisabled',
tooltip: `Input "true" if you want to skip 4k (UHD) files
\\nExample:\\n
true`,
},
],
};
}
@ -97,6 +111,22 @@ function plugin(file, librarySettings, inputs) {
}
response.infoLog += '☑File is a video! \n';
// check if the file is SD and sdDisable is enabled
// skip this plugin if so
if (['480p', '576p'].includes(file.video_resolution) && inputs.sdDisabled) {
response.processFile = false;
response.infoLog += '☒File is SD, not processing\n';
return response;
}
// check if the file is 4k and 4kDisable is enabled
// skip this plugin if so
if (file.video_resolution === '4KUHD' && inputs.uhdDisabled) {
response.processFile = false;
response.infoLog += '☒File is 4k/UHD, not processing\n';
return response;
}
// check if the file is already hevc
// it will not be transcoded if true and the plugin will be stopped immediately
for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {

@ -1,62 +1,51 @@
/* eslint-disable */
function details() {
return {
id: "Tdarr_Plugin_x7ac_Remove_Closed_Captions",
Stage: "Pre-processing",
Name: "Remove closed captions",
Type: "Video",
Operation: "Remux",
id: 'Tdarr_Plugin_x7ac_Remove_Closed_Captions',
Stage: 'Pre-processing',
Name: 'Remove burned closed captions',
Type: 'Video',
Operation: 'Remux',
Description:
"[Contains built-in filter] If detected, closed captions (XDS,608,708) will be removed.",
Version: "1.00",
'[Contains built-in filter] If detected, closed captions (XDS,608,708) will be removed from streams.',
Version: '1.01',
Link:
"https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js",
Tags: "pre-processing,ffmpeg,subtitle only",
'https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_x7ac_Remove_Closed_Captions.js',
Tags: 'pre-processing,ffmpeg,subtitle only',
};
}
function plugin(file) {
//Must return this object
var response = {
const response = {
processFile: false,
preset: "",
container: ".mp4",
// eslint-disable-next-line no-useless-escape
preset: ',-map 0 -codec copy -bsf:v \"filter_units=remove_types=6\"',
container: `.${file.container}`,
handBrakeMode: false,
FFmpegMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "",
infoLog: '',
};
if (file.fileMedium !== "video") {
console.log("File is not video");
response.infoLog += "☒File is not video \n";
response.processFile = false;
if (file.fileMedium !== 'video') {
response.infoLog += '☒File is not video \n';
return response;
} else {
if (file.hasClosedCaptions === true) {
response = {
processFile: true,
preset: ',-map 0 -codec copy -bsf:v "filter_units=remove_types=6"',
container: "." + file.container,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: "☒This file has closed captions \n",
};
return response;
} else {
response.infoLog +=
"☑Closed captions have not been detected on this file \n";
response.processFile = false;
return response;
}
}
}
// Check if Closed Captions are set at file level
if (file.hasClosedCaptions) {
response.processFile = true;
response.infoLog += '☒This file has closed captions \n';
return response;
}
// If not, check for Closed Captions in the streams
const { streams } = file.ffProbeData;
streams.forEach((stream) => {
if (stream.closed_captions) {
response.processFile = true;
}
});
response.infoLog += response.processFile ? '☒This file has burnt closed captions \n'
: '☑Closed captions have not been detected on this file \n';
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;

@ -1,9 +1,5 @@
/* eslint-disable */
module.exports.dependencies = [
'fs-extra',
];
module.exports.details = function details() {
return {
id: "Tdarr_Plugin_z18s_rename_files_based_on_codec",
@ -11,7 +7,7 @@ module.exports.details = function details() {
Name: "Rename based on codec",
Type: "Video",
Operation: "",
Description: `[Contains built-in filter]This plugin renames 264 files to 265 or vice versa depending on codec. \n\n`,
Description: `[Contains built-in filter] If the filename contains '264' or '265', this plugin renames 264 files to 265 or vice versa depending on codec. \n\n`,
Version: "1.00",
Link: "",
Tags: "post-processing",
@ -21,15 +17,6 @@ module.exports.details = function details() {
module.exports.plugin = function plugin(file, librarySettings, inputs) {
try {
var fs = require("fs");
var path = require("path");
if (fs.existsSync(path.join(process.cwd(), "/npm"))) {
var rootModules = path.join(process.cwd(), "/npm/node_modules/");
} else {
var rootModules = "";
}
var fsextra = require(rootModules + "fs-extra");
var fileNameOld = file._id;
if (
@ -39,6 +26,15 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
file._id = file._id.replace("264", "265");
file.file = file.file.replace("264", "265");
}
//added handling for files with AVC in the name instead of h264/x264
if (
file.ffProbeData.streams[0].codec_name == "hevc" &&
file._id.includes("AVC")
) {
file._id = file._id.replace("AVC", "HEVC");
file.file = file.file.replace("AVC", "HEVC");
}
if (
file.ffProbeData.streams[0].codec_name == "h264" &&
@ -57,7 +53,7 @@ module.exports.plugin = function plugin(file, librarySettings, inputs) {
}
if (fileNameOld != file._id) {
fsextra.moveSync(fileNameOld, file._id, {
fs.renameSync(fileNameOld, file._id, {
overwrite: true,
});

@ -1,7 +1,3 @@
module.exports.dependencies = [
'fs-extra',
];
module.exports.details = function details() {
return {
id: 'Tdarr_Plugin_z18t_rename_files_based_on_codec_and_resolution',
@ -20,17 +16,6 @@ module.exports.plugin = function plugin(file) {
try {
// eslint-disable-next-line global-require
const fs = require('fs');
// eslint-disable-next-line global-require
const path = require('path');
let rootModules;
if (fs.existsSync(path.join(process.cwd(), '/npm'))) {
rootModules = path.join(process.cwd(), '/npm/node_modules/');
} else {
rootModules = '';
}
// eslint-disable-next-line global-require,import/no-dynamic-require
const fsextra = require(`${rootModules}fs-extra`);
const fileNameOld = file._id;
const resolutions = {
@ -133,7 +118,7 @@ module.exports.plugin = function plugin(file) {
file.file = fileName;
if (fileNameOld !== file._id) {
fsextra.moveSync(fileNameOld, file._id, {
fs.renameSync(fileNameOld, file._id, {
overwrite: true,
});

@ -6,7 +6,7 @@ module.exports.dependencies = [
module.exports.details = function details() {
return {
id: 'Tdarr_Plugin_aaaa_Pre_Proc_Example',
Stage: 'Pre-processing', // Preprocessing or Post-processing. Determines when the plugin will be executed.
Stage: 'Pre-processing', // Pre-processing or Post-processing. Determines when the plugin will be executed.
Name: 'No title meta data ',
Type: 'Video',
Operation: 'Transcode',

@ -0,0 +1,37 @@
module.exports.details = function details() {
return {
id: 'Tdarr_Plugin_a9he_New_file_size_check',
Stage: 'Pre-processing',
Name: 'New file size check',
Type: 'Video',
Operation: 'Transcode',
Description: 'Give an error if new file is larger than the original \n\n',
Version: '1.00',
Link: '',
Tags: '',
};
};
module.exports.plugin = function plugin(file, librarySettings, inputs, otherArguments) {
// Must return this object at some point in the function else plugin will fail.
const response = {
processFile: false,
preset: '',
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: true,
infoLog: '',
};
const newSize = file.file_size;
const oldSize = otherArguments.originalLibraryFile.file_size;
if (newSize > oldSize) {
// Item will be errored in UI
throw new Error(`Error! New file has size ${newSize} which is larger than original file ${oldSize}`);
} else if (newSize < oldSize) {
response.infoLog += `New file has size ${newSize} which is smaller than original file ${oldSize}`;
}
// if file sizes are exactly the same then file has not been transcoded yet
return response;
};

@ -0,0 +1,35 @@
module.exports.details = function details() {
return {
id: 'Tdarr_Plugin_bbbc_Filter_Example',
Stage: 'Pre-processing',
Name: 'Filter resolutions',
Type: 'Video',
Operation: 'Filter',
Description: 'This plugin prevents processing files with specified resolutions \n\n',
Version: '1.00',
Link: '',
Tags: '',
};
};
module.exports.plugin = function plugin(file) {
const response = {
processFile: true,
infoLog: '',
};
const resolutionsToSkip = [
'1080p',
'4KUHD',
];
for (let i = 0; i < resolutionsToSkip.length; i += 1) {
if (file.video_resolution === resolutionsToSkip[i]) {
response.processFile = false;
response.infoLog += `Filter preventing processing. File has resolution ${resolutionsToSkip[i]}`;
break;
}
}
return response;
};

@ -12,8 +12,8 @@
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint Community methods --ext js",
"lint:fix": "eslint Community methods --ext js --fix"
"lint": "eslint Community methods examples --ext js",
"lint:fix": "eslint Community methods examples --ext js --fix"
},
"repository": {
"type": "git",

Loading…
Cancel
Save