Fixed the NaN issue with BitRates. Some files had bitrate missing in the

MediaInfo data so pulling from the "extra" section for those. Also
resolved an issue with the way the findMediaInfoItem function wasn't
working with subtitle tracks (well it wasn't working for all files due
to the general section because of a previous attempted subtitle fix but
this should be much much much better and work in most all cases).
make-only-subtitle-default
Zach Gelnett 4 years ago committed by HaveAGitGat
parent 0fed4e0ddc
commit 886ce0b2ae

@ -7,7 +7,7 @@
/* /*
/// /////////////////////////////////////////////////////////////////////////////////////////////////// /// ///////////////////////////////////////////////////////////////////////////////////////////////////
Author: JarBinks, Zachg99, Jeff47 Author: JarBinks, Zachg99, Jeff47
Date: 01/13/2022 Date: 01/20/2022
This is my attempt to create an all in one routine that will maintain my library in optimal format This is my attempt to create an all in one routine that will maintain my library in optimal format
!!!!FOR MY REQUIREMENTS!!!! Chances are very good you will need to make some changes to this routine !!!!FOR MY REQUIREMENTS!!!! Chances are very good you will need to make some changes to this routine
and it's partner in order to make it work for you. and it's partner in order to make it work for you.
@ -18,8 +18,8 @@ makes my library the best it could be. Thanks to everyone involved. Especially H
whos existing code and assistance were invaluable whos existing code and assistance were invaluable
My belief is that given enough information about the video file an optimal configuration can be determined My belief is that given enough information about the video file an optimal configuration can be determined
specific to that file specific to that file
This is based on what my goals are and uses a mix of internal and external programs to gather as much This is based on what my goals are and uses external programs to gather as much useful information as possible
useful information as possible to make decisions. to make decisions.
There is a lot that goes into the gather and analysis part because: There is a lot that goes into the gather and analysis part because:
It is the basis of the decisions and "garbage in, garbage out" It is the basis of the decisions and "garbage in, garbage out"
The video files are far from perfect when we get them and we need to make sure we learn as much as possible The video files are far from perfect when we get them and we need to make sure we learn as much as possible
@ -85,16 +85,10 @@ Subtitles:
The order I run them in: The order I run them in:
Tdarr_Plugin_JB69_JBHEVCQSV_MinimalFile (JB - H265, AAC, MKV, bitrate optimized) Tdarr_Plugin_JB69_JBHEVCQSV_MinimalFile (JB - H265, AAC, MKV, bitrate optimized)
Tdarr_Plugin_JB69_JBHEVCQSZ_PostFix (JB - MKV Stats, Chapters, Audio Language) Tdarr_Plugin_JB69_JBHEVCQSZ_PostFix (JB - MKV Stats, Chapters, Audio Language)
I am running the docker image provided for Tdarr. I am running the docker image provided for Tdarr
****To get the proper video bitrate you need to run this in the docker container:
This plugin needs (but doesn't require) the mkvtoolnix package. Install command within the container:
apt install mkvtoolnix apt install mkvtoolnix
If those tools are added that no longer needs to be run.
That needs to be rerun with every rebuild of the container to get the proper mediainfo tags.
One outstanding issue is I'm getting errors from ffmpeg when I attempt to process .ts files.
Here is my docker config (I am running compose so yours might be a little different) Here is my docker config (I am running compose so yours might be a little different)
tdarr_server: tdarr_server:
container_name: tdarr_server container_name: tdarr_server
@ -137,7 +131,7 @@ Subtitles:
- TZ=${TZ} # timezone, defined in .env - TZ=${TZ} # timezone, defined in .env
- serverIP=192.168.x.x #container name of the server, should be modified if server is on another machine - serverIP=192.168.x.x #container name of the server, should be modified if server is on another machine
- serverPort=8266 - serverPort=8266
- nodeID=TDARRNODE_2 - nodeID=TDARRNODE_1
- nodeIP=192.168.x.x #container name of the node - nodeIP=192.168.x.x #container name of the node
- nodePort=9267 #not exposed via a "ports: " setting as the server/node communication is done on the internal - nodePort=9267 #not exposed via a "ports: " setting as the server/node communication is done on the internal
#docker network and can communicate on all ports #docker network and can communicate on all ports
@ -164,10 +158,122 @@ const details = () => ({
Type: 'Video', Type: 'Video',
Operation: 'Transcode', Operation: 'Transcode',
Description: `***You should not use this*** until you read the comments at the top of the code and understand Description: `***You should not use this*** until you read the comments at the top of the code and understand
how it works **this does alot** and is 1 of 2 routines you should to run **Part 1** \n`, how it works **this does a lot** and is 1 of 2 routines you should to run **Part 1** \n`,
Version: '2.2', Version: '2.2',
Tags: 'pre-processing,ffmpeg,video,audio,qsv h265,aac', Tags: 'pre-processing,ffmpeg,video,audio,qsv,h265,aac',
Inputs: [], Inputs: [{
name: 'Stats_Days',
type: 'number',
defaultValue: 21,
inputUI: {
type: 'text',
},
tooltip: `If the stats date on the file are older than this it will first update them,\\n
usually for mkv only.`,
}, {
name: 'Target_Video_Codec',
type: 'string',
defaultValue: 'hevc',
inputUI: {
type: 'text',
},
tooltip: `This is the basis of the routine, if you want to change,\\n
it you probably want to use a different script`,
}, {
name: 'Use_10bit_Video',
type: 'boolean',
defaultValue: true,
inputUI: {
type: 'dropdown',
options: [
'true',
'false',
],
},
tooltip: 'This will encode in 10 bit? Some processors can not.',
}, {
name: 'Target_Framerate',
type: 'number',
defaultValue: 25,
inputUI: {
type: 'text',
},
tooltip: 'Any frame rate greater than this will be adjusted.',
}, {
name: 'Min_Size_Difference_to_Transcode',
type: 'number',
defaultValue: 1.2,
inputUI: {
type: 'text',
},
tooltip: `If the existing bitrate is this much more than the target bitrate\\n
it is ok to transcode, otherwise there might not be enough extra\\n
to get decent quality.`,
}, {
name: 'Target_Reduction_for_Code_Switch',
type: 'number',
defaultValue: 0.8,
inputUI: {
type: 'text',
},
tooltip: `When a video codec change happens and the source bitrate is lower\\n
than optimal, we still lower the bitrate by this since hevc is ok\\n
with a lower rate.`,
}, {
name: 'Max_Video_Height',
type: 'number',
defaultValue: 2160,
inputUI: {
type: 'dropdown',
options: [
720,
1080,
2160,
4320,
],
},
tooltip: 'Any thing over this size, I.E. 8K, will be reduced to this.',
}, {
name: 'Target_Codec_Compression',
type: 'number',
defaultValue: 0.08,
inputUI: {
type: 'text',
},
tooltip: 'This effects the target bitrate by assuming a compression ratio.',
}, {
name: 'Target_Audio_Codec',
type: 'string',
defaultValue: 'aac',
inputUI: {
type: 'text',
},
tooltip: 'Desired Audio Codec, if you change this it might require code changes.',
}, {
name: 'Target_Audio_Language',
type: 'string',
defaultValue: 'eng',
inputUI: {
type: 'text',
},
tooltip: 'Desired Audio Language.',
}, {
name: 'Target_Audio_Bitrate_Per_Channel',
type: 'number',
defaultValue: 64000,
inputUI: {
type: 'text',
},
tooltip: '64K per channel gives you the good lossy quality out of AAC.',
}, {
name: 'Target_Audio_Channels',
type: 'number',
defaultValue: 6,
inputUI: {
type: 'text',
},
tooltip: 'Any thing above this number of channels will be reduced to it.',
}],
}); });
function findMediaInfoItem(file, index) { function findMediaInfoItem(file, index) {
@ -212,24 +318,16 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
// Settings // Settings
/// /////////////////////////////////////////////////////////////////////////////////////////////////// /// ///////////////////////////////////////////////////////////////////////////////////////////////////
// Process Handling // Process Handling
const intStatsDays = 21; // If the stats date on the file, usually for mkv only, const intStatsDays = inputs.Stats_Days;
// are older than this it will first update them
// Video // Video
const targetVideoCodec = 'hevc'; // This is the basis of the routine, if you want to change const targetVideoCodec = inputs.Target_Video_Codec;
// it you probably want to use a different script const bolUse10bit = inputs.Use_10bit_Video;
const bolUse10bit = true; // This will encode in 10 bit const targetFrameRate = inputs.Target_Framerate;
const targetFrameRate = 25; // Any frame rate greater than this will be adjusted const minSizeDiffForTranscode = inputs.Min_Size_Difference_to_Transcode;
const targetReductionForCodecSwitchOnly = inputs.Target_Reduction_for_Code_Switch;
const minSizeDiffForTranscode = 1.2; // If the existing bitrate is this much more than the target const maxVideoHeight = inputs.Max_Video_Height;
// bitrate it is ok to transcode, otherwise there might not be enough extra const targetCodecCompression = inputs.Target_Codec_Compression;
// to get decent quality
const targetReductionForCodecSwitchOnly = 0.8; // When a video codec change happens and the source bitrate is lower
// than optimal, we still lower the bitrate by this since hevc is ok
// with a lower rate
const maxVideoHeight = 2160; // Any thing over this size, I.E. 8K, will be reduced to this
const targetCodecCompression = 0.08; // This effects the target bitrate by assuming a compression ratio
// Since videos can have many widths and heights we need to convert to pixels (WxH) to understand what we // Since videos can have many widths and heights we need to convert to pixels (WxH) to understand what we
// are dealing with and set a minimal optimal bitrate to not go below // are dealing with and set a minimal optimal bitrate to not go below
@ -245,51 +343,18 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
const minVideoRateSD = 450000; const minVideoRateSD = 450000;
// Audio // Audio
const targetAudioCodec = 'aac'; // Desired Audio Coded, if you change this it will might require code changes const targetAudioCodec = inputs.Target_Audio_Codec;
const targetAudioLanguage = 'eng'; // Desired Audio Language const targetAudioLanguage = inputs.Target_Audio_Language;
const targetAudioBitratePerChannel = 64000; // 64K per channel gives you the good lossy quality out of AAC const targetAudioBitratePerChannel = inputs.Target_Audio_Bitrate_Per_Channel;
const targetAudioChannels = 6; // Any thing above this number of channels will be const targetAudioChannels = inputs.Target_Audio_Channels;
// reduced to it, because I cannot listen to it
// Subtitles // Subtitles
// const bolIncludeSubs = true; //not used // const bolIncludeSubs = true; //not currently used, it's possible to remove subs but not setup now
/// /////////////////////////////////////////////////////////////////////////////////////////////////// /// ///////////////////////////////////////////////////////////////////////////////////////////////////
const proc = require('child_process'); // Causes lint error, hopefully not needed const proc = require('child_process');
let bolStatsAreCurrent = false; let bolStatsAreCurrent = false;
// Run MediaInfo and load the results it into an object
/// ///////////////////////////////////////////////////////////////////////////////////////////////////
// response.infoLog += "Getting Media Info.\n";
// var objMedInfo = "";
// objMedInfo = JSON.parse(proc.execSync('mediainfo "' + currentFileName + '" --output=JSON').toString());
/// ///////////////////////////////////////////////////////////////////////////////////////////////////
// Run ffprobe with full info and load the results it into an object
/// ///////////////////////////////////////////////////////////////////////////////////////////////////
// response.infoLog += "Getting FFProbe Info.\n";
// var objFFProbeInfo = "";
// objFFProbeInfo = JSON.parse(proc.execSync('ffprobe -v error -print_format json
// -show_format -show_streams -show_chapters "' + currentFileName + '"').toString());
/// ///////////////////////////////////////////////////////////////////////////////////////////////////
// response.processFile = false;
// response.infoLog += objMedInfo + " \n";
// return response;
// response.infoLog += "HomePath:" + JSON.stringify(otherArguments, null, 4) + "\n";
// response.infoLog += "FIID:" + file._id + "\n";
// response.infoLog += "IPID:" + inputs._id + "\n";
// response.infoLog += "FIDB:" + JSON.stringify(file, null, 4) + "\n";
// response.infoLog += "CacheDir:" + librarySettings.cache + "\n";
// response.infoLog += "filename:" + require("crypto").createHash("md5").update(file._id).digest("hex") + "\n";
// response.infoLog += "MediaInfo:" + JSON.stringify(objMedInfo, null, 4) + "\n";
// response.infoLog += "FFProbeInfo:" + JSON.stringify(objFFProbeInfo, null, 4) + "\n";
// response.infoLog += "objFFProbeInfo:" + JSON.stringify(objFFProbeInfo, null, 4) + "\n";
// response.processFile = false;
// 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') {
response.processFile = false; response.processFile = false;
@ -340,6 +405,7 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
try { try {
proc.execSync(`mkvpropedit --add-track-statistics-tags "${currentFileName}"`); proc.execSync(`mkvpropedit --add-track-statistics-tags "${currentFileName}"`);
return response;
} catch (err) { } catch (err) {
response.infoLog += 'Error Updating Status Probably Bad file, A remux will probably fix, will continue\n'; response.infoLog += 'Error Updating Status Probably Bad file, A remux will probably fix, will continue\n';
} }
@ -862,4 +928,4 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
}; };
module.exports.details = details; module.exports.details = details;
module.exports.plugin = plugin; module.exports.plugin = plugin;
Loading…
Cancel
Save