Merge pull request #78 from Mthrboard/master
Add plugin to transcode video to H.265 HEVC using Intel QuickSync CPUsmake-only-subtitle-default
commit
67145625df
@ -0,0 +1,106 @@
|
||||
const vaapiPrefix = ` -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi `;
|
||||
|
||||
module.exports.details = function 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`,
|
||||
Link: `https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_Mthr_VaapiHEVCTranscode.js`,
|
||||
Tags: `pre-processing,ffmpeg,video only,h265,configurable`,
|
||||
Inputs: [{
|
||||
name: `remuxOnly`,
|
||||
tooltip: `Specify whether this plugin should only run on files with Remux in their names. ` +
|
||||
`Valid options are true or false. Defaults to false. ` +
|
||||
`\\nExample: ` +
|
||||
`\\ntrue ` +
|
||||
`\\nExample: ` +
|
||||
`\\nfalse`
|
||||
},{
|
||||
name: `minBitrate`,
|
||||
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`
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.plugin = function plugin(file, librarySettings, inputs) {
|
||||
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/
|
||||
duration = (file.meta.Duration !== `undefined` ? file.meta.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;
|
||||
}
|
||||
Loading…
Reference in new issue