You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Tdarr_Plugins/Community/Tdarr_Plugin_Mthr_VaapiHEVC...

135 lines
4.6 KiB

/* eslint-disable */
const vaapiPrefix = ` -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi `;
const details = () => {
return {
id: `Tdarr_Plugin_Mthr_VaapiHEVCTranscode`,
Stage: 'Pre-processing',
Name: `FFMPEG VAAPI HEVC Transcode`,
Type: `Video`,
Operation: `Transcode`,
Description: `Files not in HEVC will be transcoded into HEVC video using ffmpeg with libvaapi. ` +
`Intel QuickSync-enabled CPU required, recommended 8th generation or newer.\n ` +
`Output bitrate will be calculated based on input file size.\n\n`,
Version: `1.0`,
Tags: `pre-processing,ffmpeg,video only,h265,configurable`,
Inputs: [{
name: `remuxOnly`,
type: 'string',
defaultValue:'false',
inputUI: {
type: 'text',
},
tooltip: `Specify whether this plugin should only run on files with Remux in their names. ` +
`Valid options are true or false.` +
`\\nExample: ` +
`\\ntrue ` +
`\\nExample: ` +
`\\nfalse`
},{
name: `minBitrate`,
type: 'string',
defaultValue:'',
inputUI: {
type: 'text',
},
tooltip: `Specify the minimum bitrate at which this plugin will run. Files with a current bitrate ` +
`lower than this cutoff will not be transcoded. Leave blank to disable. ` +
`\\nExample: ` +
`\\n4000`
}]
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const plugin = (file, librarySettings, inputs, otherArguments) => {
const lib = require('../methods/lib')();
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign
inputs = lib.loadDefaultValues(inputs, details);
var response = {
processFile: false,
preset: ``,
handBrakeMode: false,
FFmpegMode: true,
reQueueAfter: false,
infoLog: ``
};
var videoProcessingRequired = false;
var ffmpegParameters = ``;
var duration = 0;
var currentBitrate = 0;
var targetBitrate = 0;
var minimumBitrate = 0;
var maximumBitrate = 0;
if (inputs.remuxOnly.toLowerCase() == `true` && !file.file.toLowerCase().includes(`remux`)) {
response.infoLog += `☒ RemuxOnly is enabled and file is not a remux. Unable to process.\n`;
return response;
}
if (file.fileMedium !== `video`) {
response.infoLog += `☒ File is not a video. Unable to process.\n`;
return response;
}
file.ffProbeData.streams.forEach(function(stream) {
if (stream.codec_type == `video`) {
if (stream.codec_name !== `mjpeg` && stream.codec_name !== `hevc`) {
videoProcessingRequired = true;
// Formula borrowed from Migz h265 transcode plugins
// Get duration in minutes, then work out currentBitrate using
// Bitrate = file size / (stream duration * .0075)
// Calculations were made based on the formula from this site:
// https://blog.frame.io/2017/03/06/calculate-video-bitrates/
if (parseFloat(file.ffProbeData?.format?.duration) > 0) {
duration = parseFloat(file.ffProbeData?.format?.duration) * 0.0166667;
} else if(file.meta.Duration !== `undefined`){
duration = file.meta.Duration* 0.0166667;
}else{
duration = stream.duration * 0.0166667;
}
currentBitrate = ~~(file.file_size / (duration * 0.0075));
targetBitrate = ~~(currentBitrate / 2);
minimumBitrate = ~~(targetBitrate * 0.7);
maximumBitrate = ~~(targetBitrate * 1.3);
if (targetBitrate == 0) {
response.infoLog += `☒ Target bitrate could not be calculated. Skipping this plugin.\n`;
return response;
}
if (inputs.minBitrate !== `` && currentBitrate <= inputs.minBitrate) {
response.infoLog += `☒ Input file's bitrate ${currentBitrate} is lower than the minimum ` +
`bitrate threshold of ${inputs.minBitrate}. Skipping this plugin.\n`;
return response;
}
response.infoLog += `☒ Video stream ${stream.index} is not HEVC, transcode required.\n `;
ffmpegParameters += ` -c:v:0 hevc_vaapi -b:v ${targetBitrate}k -minrate ${minimumBitrate}k ` +
`-maxrate ${maximumBitrate}k -bufsize 1M -max_muxing_queue_size 1024 `;
}
}
});
if (videoProcessingRequired) {
response.infoLog += `☑ Stream analysis complete, processing required.\n `;
response.preset = `${vaapiPrefix},-map 0:v -map 0:a -map 0:s? -map 0:d? -map 0:t? -c copy ${ffmpegParameters} `;
response.container = `${file.container}`;
response.processFile = true;
} else {
response.infoLog += `☑ Stream analysis complete, no processing required.\n`;
}
return response;
}
module.exports.details = details;
module.exports.plugin = plugin;