Description:`Files will be transcoded 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, 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`,
// Work out currentBitrate using "Bitrate = file size / (number of minutes * .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.
// Allow some leeway under and over the targetBitrate.
varminimumBitrate=~~(targetBitrate*0.7)
varminimumBitrate=~~(targetBitrate*0.7)
varmaximumBitrate=~~(targetBitrate*1.3)
varmaximumBitrate=~~(targetBitrate*1.3)
// If targetBitrate comes out as 0 then something has gone wrong and bitrates could not be calculcated. Cancel plugin completely.
if(targetBitrate=="0"){
if(targetBitrate=="0"){
response.processFile=false
response.processFile=false
response.infoLog+="☒Target bitrate could not be calculated. Skipping this plugin. \n"
response.infoLog+="☒Target bitrate could not be calculated. Skipping this plugin. \n"
returnresponse
returnresponse
}
}
// Check if inputs.bitrate cutoff has something entered (Entered means user actually wants something to happen, empty would disable this).
if(inputs.bitrate_cutoff!=""){
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){
if(file.container==inputs.container){
response.processFile=false
response.processFile=false
response.infoLog+=`☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff} & file container is already ${inputs.container}. Nothing to do, skipping. \n`
response.infoLog+=`☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff}. Nothing to do, cancelling plugin. \n`
returnresponse
}else{
response.processFile=true
response.preset+=`, -c copy ${extraArguments}`
response.infoLog+=`☒Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff} but is not in correct container. Remuxing to ${inputs.container} but not transcoding. \n`
Description:`Files will be transcoded 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 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`,
// Work out currentBitrate using "Bitrate = file size / (number of minutes * .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.
// Allow some leeway under and over the targetBitrate.
varminimumBitrate=~~(targetBitrate*0.7)
varminimumBitrate=~~(targetBitrate*0.7)
varmaximumBitrate=~~(targetBitrate*1.3)
varmaximumBitrate=~~(targetBitrate*1.3)
// If targetBitrate comes out as 0 then something has gone wrong and bitrates could not be calculcated. Cancel plugin completely.
if(targetBitrate=="0"){
if(targetBitrate=="0"){
response.processFile=false
response.processFile=false
response.infoLog+="☒Target bitrate could not be calculated. Skipping this plugin. \n"
response.infoLog+="☒Target bitrate could not be calculated. Skipping this plugin. \n"
returnresponse
returnresponse
}
}
// Check if inputs.bitrate cutoff has something entered (Entered means user actually wants something to happen, empty would disable this).
if(inputs.bitrate_cutoff!=""){
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){
if(file.container==inputs.container){
response.processFile=false
response.processFile=false
response.infoLog+=`☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff} & file container is already ${inputs.container}. Nothing to do, skipping. \n`
response.infoLog+=`☑Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff}. Nothing to do, cancelling plugin. \n`
returnresponse
}else{
response.processFile=true
response.preset+=`, -c copy ${extraArguments}`
response.infoLog+=`☒Current bitrate is below configured bitrate cutoff of ${inputs.bitrate_cutoff} but is not in correct container. Remuxing to ${inputs.container} but not transcoding. \n`
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, if it exists. Video checking is mandatory, audio and subtitles are optional.\n\n`,
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
tooltip:`Specify language tag/s here for the audio tracks you'd like to keep, recommended to keep "und" as this stands for undertermined, some files may not have the language specified. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nExample:\\n
\\nExample:\\n
@ -38,8 +37,7 @@ function details() {
eng
eng
\\nExample:\\n
\\nExample:\\n
por
por`
`
},
},
{
{
name:'tag_title',
name:'tag_title',
@ -65,6 +63,7 @@ function plugin(file, librarySettings, inputs) {
infoLog:'',
infoLog:'',
}
}
// 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")
console.log("File is not video")
response.infoLog+="☒File is not video \n"
response.infoLog+="☒File is not video \n"
@ -72,30 +71,26 @@ function plugin(file, librarySettings, inputs) {
returnresponse
returnresponse
}
}
// Check if inputs.language has been configured. If it hasn't then exit plugin.
if(inputs.language==""){
if(inputs.language==""){
response.infoLog+="☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.infoLog+="☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
@ -104,7 +99,9 @@ function plugin(file, librarySettings, inputs) {
}
}
}catch(err){}
}catch(err){}
// 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.
@ -113,23 +110,29 @@ function plugin(file, librarySettings, inputs) {
}
}
}catch(err){}
}catch(err){}
// Check if inputs.tag_language has something entered (Entered means user actually wants something to happen, empty would disable this) AND checks that stream is audio.
// 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.
response.infoLog+=`☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`
response.infoLog+=`☒Audio stream detected as having no language tagged, tagging as ${inputs.tag_language}. \n`
convert=true
convert=true
}
}
}
}
}catch(err){}
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.
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
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
@ -29,7 +28,7 @@ function details() {
false`
false`
},
},
{
{
name:'tag_title',
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, leave empty to disable. Must follow ISO-639-2 3 letter format. https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
\\nExample:\\n
\\nExample:\\n
eng
eng
@ -52,6 +51,7 @@ function plugin(file, librarySettings, inputs) {
infoLog:'',
infoLog:'',
}
}
// 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")
console.log("File is not video")
response.infoLog+="☒File is not video \n"
response.infoLog+="☒File is not video \n"
@ -59,25 +59,25 @@ function plugin(file, librarySettings, inputs) {
returnresponse
returnresponse
}
}
// Check if inputs.language has been configured. If it hasn't then exit plugin.
if(inputs.language==""){
if(inputs.language==""){
response.infoLog+="☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.infoLog+="☒Language/s keep have not been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.infoLog+=`☒Subtitle stream detected as being an unwanted language, removing. Subtitle stream 0:s:${subtitleIdx} - ${file.ffProbeData.streams[i].tags.language.toLowerCase()}\n`
response.infoLog+=`☒Subtitle stream detected as being an unwanted language, removing. Subtitle stream 0:s:${subtitleIdx} - ${file.ffProbeData.streams[i].tags.language.toLowerCase()}\n`
@ -85,7 +85,9 @@ function plugin(file, librarySettings, inputs) {
}
}
}catch(err){}
}catch(err){}
// 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.
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 Commentary or Description, removing. Subtitle stream 0:s:${SubtitleIdx} - ${file.ffProbeData.streams[i].tags.title}. \n`
@ -93,24 +95,33 @@ function plugin(file, librarySettings, inputs) {
}
}
}catch(err){}
}catch(err){}
// Check if inputs.tag_language has something entered (Entered means user actually wants something to happen, empty would disable this) AND checks that stream is audio.
response.infoLog+=`☒Subtitle stream detected as having unknown language tagged, tagging as ${inputs.tag_title}. \n`
response.infoLog+=`☒Subtitle stream detected as having unknown language tagged, tagging as ${inputs.tag_language}. \n`
convert=true
convert=true
}
}
}
}catch(err){}
}catch(err){}
try{
// 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.
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.
\\nExample:\\n
\\nExample:\\n
true
true
@ -21,7 +20,7 @@ function details() {
},
},
{
{
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.
tooltip:`Specify if downmixing should be used to create extra audio tracks. I.e if you have an 8ch but no 2ch or 6ch, create the missing audio tracks from the 8 ch. Likewise if you only have 6ch, create the missing 2ch from it. Optional.
\\nExample:\\n
\\nExample:\\n
true
true
@ -42,7 +41,14 @@ function plugin(file, librarySettings, inputs) {
infoLog:'',
infoLog:'',
}
}
// Check if both inputs.aac_stereo AND inputs.downmix have been left empty. If they have then exit plugin.
response.infoLog+="☒Neither aac_stereo or downmix options have been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.processFile=false
returnresponse
}
// 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")
console.log("File is not video")
response.infoLog+="☒File is not video. \n"
response.infoLog+="☒File is not video. \n"
@ -50,12 +56,7 @@ function plugin(file, librarySettings, inputs) {
returnresponse
returnresponse
}
}
if(inputs.aac_stereo==""&&inputs.downmix==""){
// Set up required variables.
response.infoLog+="☒Neither aac_stereo or downmix options have been configured within plugin settings, please configure required options. Skipping this plugin. \n"
response.processFile=false
returnresponse
}
varffmpegCommandInsert=''
varffmpegCommandInsert=''
varaudioIdx=0
varaudioIdx=0
varhas2Channel=false
varhas2Channel=false
@ -63,8 +64,10 @@ function plugin(file, librarySettings, inputs) {
// 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 subtitleIdx does NOT equal 0, if it does then it means a subtitle track has already appeared before an audio track so file needs to be organized.
if(subtitleIdx!="0"){
if(subtitleIdx!="0"){
convert=true
convert=true
response.infoLog+="☒ Audio not second. \n"
response.infoLog+="☒ Audio not second. \n"
}
}
// Increment audioIdx.
audioIdx++
audioIdx++
// 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.
if(audio6Idx!="0"||audio8Idx!="0"){
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++
audio2Idx++
}
}
// 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.