Adjustments based on comments

make-only-subtitle-default
HaveAGitGat 2 years ago
parent 3204bce8bb
commit abfa9af5aa

@ -9,29 +9,56 @@ const details = () => ({
Version: '3.1',
Tags: 'pre-processing,ffmpeg,video only,nvenc h265,configurable',
Inputs: [
{
name: 'encoder',
type: 'string',
defaultValue: 'hevc',
inputUI: {
type: 'dropdown',
options: [
'hevc',
'vp9',
'h264',
'vp8',
],
},
tooltip: 'Specify the codec to use',
},
{
name: 'use_gpu',
type: 'boolean',
defaultValue: true,
inputUI: {
type: 'dropdown',
options: [
'false',
'true',
],
},
tooltip: 'If enabled then will use GPU if possible.',
},
{
name: 'container',
type: 'string',
defaultValue: 'mkv',
inputUI: {
type: 'text',
type: 'dropdown',
options: [
'mkv',
'mp4',
'avi',
'ts',
'original',
],
},
tooltip: `Specify output container of file. Use 'original' wihout quotes to keep original container.
\\n Ensure that all stream types you may have are supported by your chosen container.
\\n mkv is recommended.
\\nExample:\\n
mkv
\\nExample:\\n
mp4
\\nExample:\\n
original`,
\\n mkv is recommended`,
},
{
name: 'bitrate_cutoff',
type: 'string',
defaultValue: '',
type: 'number',
defaultValue: 0,
inputUI: {
type: 'text',
},
@ -103,35 +130,6 @@ const details = () => ({
\\nExample:\\n
false`,
},
{
name: 'encoder',
type: 'string',
defaultValue: 'hevc',
inputUI: {
type: 'dropdown',
options: [
'hevc',
'vp9',
'h264',
'vp8',
],
},
tooltip: 'Specify the codec to use',
},
{
name: 'use_gpu',
type: 'boolean',
defaultValue: true,
inputUI: {
type: 'dropdown',
options: [
'false',
'true',
],
},
tooltip: 'If enabled then will use GPU if possible.',
},
],
});
@ -140,9 +138,9 @@ const hasEncoder = async ({
encoder,
}) => {
const { exec } = require('child_process');
let res = false;
let isEnabled = false;
try {
res = await new Promise((resolve) => {
isEnabled = await new Promise((resolve) => {
exec(`${ffmpegPath} -f lavfi -i color=c=black:s=256x256:d=1:r=30 -c:v ${encoder} -f null /dev/null`, (
error,
// stdout,
@ -160,7 +158,7 @@ const hasEncoder = async ({
console.log(err);
}
return res;
return isEnabled;
};
const getEncoder = async ({
@ -168,8 +166,7 @@ const getEncoder = async ({
otherArguments,
}) => {
let { encoder } = inputs;
if (inputs.use_gpu
&& (inputs.encoder === 'hevc' || inputs.encoder === 'h264')) {
if (inputs.use_gpu && (inputs.encoder === 'hevc' || inputs.encoder === 'h264')) {
const gpuEncoders = [
{
encoder: 'hevc_nvenc',
@ -209,11 +206,11 @@ const getEncoder = async ({
const filteredGpuEncoders = gpuEncoders.filter((device) => device.encoder.includes(inputs.encoder));
// eslint-disable-next-line no-restricted-syntax
for (const device of filteredGpuEncoders) {
for (const gpuEncoder of filteredGpuEncoders) {
// eslint-disable-next-line no-await-in-loop
device.enabled = await hasEncoder({
gpuEncoder.enabled = await hasEncoder({
ffmpegPath: otherArguments.ffmpegPath,
encoder: device.encoder,
encoder: gpuEncoder.encoder,
});
}
@ -246,18 +243,7 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
otherArguments,
});
let duration = '';
// 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';
response.processFile = false;
return response;
}
if (inputs.container === 'original') {
// eslint-disable-next-line no-param-reassign
inputs.container = `${file.container}`;
response.container = `.${file.container}`;
} else {
response.container = `.${inputs.container}`;
@ -265,19 +251,19 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
// Check if file is a video. If it isn't then exit plugin.
if (file.fileMedium !== 'video') {
response.processFile = false;
response.infoLog += 'File is not a video. \n';
return response;
}
// 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.
let duration = 0;
// Get duration in seconds
if (parseFloat(file.ffProbeData?.format?.duration) > 0) {
duration = parseFloat(file.ffProbeData?.format?.duration) * 0.0166667;
duration = parseFloat(file.ffProbeData?.format?.duration);
} else if (typeof file.meta.Duration !== 'undefined') {
duration = file.meta.Duration * 0.0166667;
duration = file.meta.Duration;
} else {
duration = file.ffProbeData.streams[0].duration * 0.0166667;
duration = file.ffProbeData.streams[0].duration;
}
// Set up required variables.
@ -286,49 +272,45 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
let extraArguments = '';
let genpts = '';
let bitrateSettings = '';
// Work out currentBitrate using "Bitrate = file size / (number of minutes * .0075)"
// Used from here https://blog.frame.io/2017/03/06/calculate-video-bitrates/
// eslint-disable-next-line no-bitwise
const currentBitrate = ~~(file.file_size / (duration * 0.0075));
const currentBitrate = (file.file_size * 1024 * 1024 * 8) / duration;
// 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.
// eslint-disable-next-line no-bitwise
const targetBitrate = ~~(file.file_size / (duration * 0.0075) / 2);
const targetBitrate = currentBitrate / 2;
// Allow some leeway under and over the targetBitrate.
// eslint-disable-next-line no-bitwise
const minimumBitrate = ~~(targetBitrate * 0.7);
// eslint-disable-next-line no-bitwise
const maximumBitrate = ~~(targetBitrate * 1.3);
const minimumBitrate = (targetBitrate * 0.7);
const maximumBitrate = (targetBitrate * 1.3);
// If Container .ts or .avi set genpts to fix unknown timestamp
if (inputs.container.toLowerCase() === 'ts' || inputs.container.toLowerCase() === 'avi') {
if (inputs.container === 'ts' || inputs.container === 'avi') {
genpts = '-fflags +genpts';
}
// If targetBitrate comes out as 0 then something has gone wrong and bitrates could not be calculated.
// Cancel plugin completely.
if (targetBitrate === 0) {
response.processFile = false;
response.infoLog += 'Target bitrate could not be calculated. Skipping this plugin. \n';
return response;
}
// 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 cancel plugin without touching original files.
if (currentBitrate <= inputs.bitrate_cutoff) {
response.processFile = false;
response.infoLog += `Current bitrate is below set cutoff of ${inputs.bitrate_cutoff}. Cancelling plugin. \n`;
return response;
}
// Checks if currentBitrate is below inputs.bitrate_cutoff.
// If so then cancel plugin without touching original files.
if (currentBitrate <= inputs.bitrate_cutoff) {
response.infoLog += `Current bitrate is below set cutoff of ${inputs.bitrate_cutoff}. Cancelling plugin. \n`;
return response;
}
// Check if force_conform option is checked.
// If so then check streams and add any extra parameters required to make file conform with output format.
if (inputs.force_conform === true) {
if (inputs.container.toLowerCase() === 'mkv') {
if (inputs.container === 'mkv') {
extraArguments += '-map -0:d ';
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
@ -347,7 +329,7 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
}
}
}
if (inputs.container.toLowerCase() === 'mp4') {
if (inputs.container === 'mp4') {
for (let i = 0; i < file.ffProbeData.streams.length; i++) {
try {
if (
@ -399,12 +381,9 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
// Check if codec of stream is hevc or vp9 AND check if file.container matches inputs.container.
// If so nothing for plugin to do.
if (
(
inputs.encoder === file.ffProbeData.streams[i].codec_name
)
inputs.encoder === file.ffProbeData.streams[i].codec_name
&& file.container === inputs.container
) {
response.processFile = false;
response.infoLog += `File is already ${inputs.encoder} & in ${inputs.container}. \n`;
return response;
}
@ -412,13 +391,13 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
// AND check if file.container does NOT match inputs.container.
// If so remux file.
if (
(
inputs.encoder === file.ffProbeData.streams[i].codec_name
)
inputs.encoder === file.ffProbeData.streams[i].codec_name
&& file.container !== inputs.container
) {
response.infoLog += `File is hevc or vp9 but is not in ${inputs.container} container. Remuxing. \n`;
response.preset = `, -map 0 -c copy ${extraArguments}`;
response.preset = `<io> -map 0 -c copy ${extraArguments}`;
response.processFile = true;
return response;
}
@ -427,7 +406,7 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
if (
inputs.encoder === 'hevc'
&& (file.ffProbeData.streams[i].profile === 'High 10'
|| file.ffProbeData.streams[i].bits_per_raw_sample === '10')
|| file.ffProbeData.streams[i].bits_per_raw_sample === '10')
) {
CPU10 = true;
}
@ -438,8 +417,8 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
}
// Set bitrateSettings variable using bitrate information calulcated earlier.
bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k `
+ `-maxrate ${maximumBitrate}k -bufsize ${currentBitrate}k`;
bitrateSettings = `-b:v ${targetBitrate} -minrate ${minimumBitrate} `
+ `-maxrate ${maximumBitrate} -bufsize ${currentBitrate}`;
// Print to infoLog information around file & bitrate settings.
response.infoLog += `Container for output selected as ${inputs.container}. \n`;
response.infoLog += `Current bitrate = ${currentBitrate} \n`;
@ -448,14 +427,11 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
response.infoLog += `Minimum = ${minimumBitrate} \n`;
response.infoLog += `Maximum = ${maximumBitrate} \n`;
if (encoder === 'hevc_nvenc' || encoder === 'h264_nvenc') {
// Codec will be checked so it can be transcoded correctly
if (encoder.contains('nvenc')) {
if (file.video_codec_name === 'h263') {
response.preset = '-c:v h263_cuvid';
} else if (file.video_codec_name === 'h264') {
if (CPU10 === false) {
response.preset = '-c:v h264_cuvid';
}
} else if (file.video_codec_name === 'h264' && CPU10 === false) {
response.preset = '-c:v h264_cuvid';
} else if (file.video_codec_name === 'mjpeg') {
response.preset = '-c:v mjpeg_cuvid';
} else if (file.video_codec_name === 'mpeg1') {
@ -471,8 +447,8 @@ const plugin = async (file, librarySettings, inputs, otherArguments) => {
}
}
response.preset += `${genpts}, -map 0 -c:v ${encoder} -cq:v 19 ${bitrateSettings} `
+ `-spatial_aq:v 1 -rc-lookahead:v 32 -c:a copy -c:s copy -max_muxing_queue_size 9999 ${extraArguments}`;
response.preset += `${genpts}<io> -map 0 -c copy -c:v ${encoder} -cq:v 19 ${bitrateSettings} `
+ `-spatial_aq:v 1 -rc-lookahead:v 32 -max_muxing_queue_size 9999 ${extraArguments}`;
response.processFile = true;
response.infoLog += 'File is not hevc or vp9. Transcoding. \n';
return response;

Loading…
Cancel
Save