mirror of
https://github.com/gabehf/Tdarr_Plugins.git
synced 2026-03-17 11:16:26 -07:00
Updated with better hw control
- Removed mkvpropedit remux behaviour - No longer seems to be needed (It's upto the user to have the mkvpropedit option enabled on Tdarr side) - Corrected parts of the ffmpeg cmd to define the output format based on container - Updated win32 hwaccel cmd to use a more correct type - Enabled hwupload & hwupload frames
This commit is contained in:
parent
9494a2fcad
commit
c7c47a16b0
1 changed files with 44 additions and 87 deletions
|
|
@ -334,7 +334,6 @@ let videoBR = 0;
|
||||||
const plugin = (file, librarySettings, inputs, otherArguments) => {
|
const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
const lib = require('../methods/lib')();
|
const lib = require('../methods/lib')();
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const proc = require('child_process');
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign
|
||||||
inputs = lib.loadDefaultValues(inputs, details);
|
inputs = lib.loadDefaultValues(inputs, details);
|
||||||
const response = {
|
const response = {
|
||||||
|
|
@ -353,79 +352,6 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MKVPROPEDIT - Refresh video stats
|
|
||||||
const intStatsDays = 7; // Use 1 week threshold for new stats
|
|
||||||
let statsUptoDate = false;
|
|
||||||
const currentFileName = file._id;
|
|
||||||
let statsError = false;
|
|
||||||
let metadataEncode = '';
|
|
||||||
|
|
||||||
// Only process MKV files
|
|
||||||
if (file.container === 'mkv') {
|
|
||||||
let datStats = Date.parse(new Date(70, 1).toISOString()); // Placeholder date
|
|
||||||
metadataEncode = `-map_metadata:g -1 -metadata JBDONEDATE=${datStats}`;
|
|
||||||
if (file.mediaInfo.track[0].extra !== undefined && file.mediaInfo.track[0].extra.JBDONEDATE !== undefined) {
|
|
||||||
datStats = Date.parse(file.mediaInfo.track[0].extra.JBDONEDATE);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
file.mediaInfo.track[0].extra !== undefined
|
|
||||||
&& file.ffProbeData.streams[0].tags['_STATISTICS_WRITING_DATE_UTC-eng'] !== undefined
|
|
||||||
) {
|
|
||||||
// Set stats date to match info inside file
|
|
||||||
datStats = Date.parse(`${file.ffProbeData.streams[0].tags['_STATISTICS_WRITING_DATE_UTC-eng']} GMT`);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// Catch error - Ignore & carry on - If check can bomb out if the tag doesn't exist...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Threshold for stats date
|
|
||||||
const statsThres = Date.parse(new Date(new Date().setDate(new Date().getDate() - intStatsDays)).toISOString());
|
|
||||||
|
|
||||||
// Strings for easy to read dates in info log
|
|
||||||
let statsThresString = new Date(statsThres);
|
|
||||||
statsThresString = statsThresString.toUTCString();
|
|
||||||
statsThresString = `${statsThresString.slice(0, 22)}:00 GMT`;
|
|
||||||
let datStatsString = new Date(datStats);
|
|
||||||
datStatsString = datStatsString.toUTCString();
|
|
||||||
datStatsString = `${datStatsString.slice(0, 22)}:00 GMT`;
|
|
||||||
response.infoLog += `Checking file stats - If stats are older than ${intStatsDays} days we'll grab new stats.\n
|
|
||||||
Stats threshold: ${statsThresString}\n
|
|
||||||
Current stats date: ${datStatsString}\n`;
|
|
||||||
|
|
||||||
// Are the stats out of date?
|
|
||||||
if (datStats >= statsThres) {
|
|
||||||
statsUptoDate = true;
|
|
||||||
response.infoLog += '☑ File stats are upto date! - Continuing...\n';
|
|
||||||
} else {
|
|
||||||
response.infoLog += '☒ File stats are out of date! - Will attempt to use mkvpropedit to refresh stats\n';
|
|
||||||
try {
|
|
||||||
if (otherArguments.mkvpropeditPath !== '') { // Try to use mkvpropedit path if it is set
|
|
||||||
proc.execSync(`"${otherArguments.mkvpropeditPath}" --add-track-statistics-tags "${currentFileName}"`);
|
|
||||||
} else { // Otherwise just use standard mkvpropedit cmd
|
|
||||||
proc.execSync(`mkvpropedit --add-track-statistics-tags "${currentFileName}"`);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
response.infoLog += '☒ Error updating file stats - Possible mkvpropedit failure or file issue - '
|
|
||||||
+ ' Ensure mkvpropedit is set correctly in the node settings & check the filename for unusual characters.\n'
|
|
||||||
+ ' Continuing but file stats will likely be inaccurate...\n';
|
|
||||||
statsError = true;
|
|
||||||
}
|
|
||||||
if (statsError !== true) {
|
|
||||||
// File now updated with new stats
|
|
||||||
response.infoLog += 'Remuxing file to write in updated file stats! \n';
|
|
||||||
response.preset += `-fflags +genpts <io> -map 0 -c copy -max_muxing_queue_size 9999 -map_metadata:g -1
|
|
||||||
-metadata JBDONEDATE=${new Date().toISOString()}`;
|
|
||||||
response.processFile = true;
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
response.infoLog += 'Input file is not MKV so cannot use mkvpropedit to get new file stats. '
|
|
||||||
+ 'Continuing but file stats will likely be inaccurate...\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {
|
for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {
|
||||||
const strstreamType = file.ffProbeData.streams[i].codec_type.toLowerCase();
|
const strstreamType = file.ffProbeData.streams[i].codec_type.toLowerCase();
|
||||||
videoIdx = -1;
|
videoIdx = -1;
|
||||||
|
|
@ -649,12 +575,6 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
// which can be inaccurate. We may inflate the current bitrate check so we don't keep looping this logic.
|
// which can be inaccurate. We may inflate the current bitrate check so we don't keep looping this logic.
|
||||||
} else if (inputs.reconvert_hevc === true && (file.ffProbeData.streams[i].codec_name === 'hevc'
|
} else if (inputs.reconvert_hevc === true && (file.ffProbeData.streams[i].codec_name === 'hevc'
|
||||||
|| file.ffProbeData.streams[i].codec_name === 'vp9' || file.ffProbeData.streams[i].codec_name === 'av1')) {
|
|| file.ffProbeData.streams[i].codec_name === 'vp9' || file.ffProbeData.streams[i].codec_name === 'av1')) {
|
||||||
if (statsUptoDate !== true) {
|
|
||||||
currentBitrate = overallBitRate; // User overall bitrate if we don't have upto date stats
|
|
||||||
response.infoLog += `☒ Unable to get accurate stats for HEVC so falling back to Overall file Bitrate.
|
|
||||||
Remux to MKV to allow generation of accurate video bitrate statistics.
|
|
||||||
File overall bitrate is ${overallBitRate}kbps.\n`;
|
|
||||||
}
|
|
||||||
if (inputs.hevc_max_bitrate > 0) {
|
if (inputs.hevc_max_bitrate > 0) {
|
||||||
if (currentBitrate > inputs.hevc_max_bitrate) {
|
if (currentBitrate > inputs.hevc_max_bitrate) {
|
||||||
// If bitrate is higher then hevc_max_bitrate then need to re-encode
|
// If bitrate is higher then hevc_max_bitrate then need to re-encode
|
||||||
|
|
@ -709,6 +629,17 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Specify the output format
|
||||||
|
switch (inputs.container) {
|
||||||
|
case 'mkv':
|
||||||
|
extraArguments += '-f matroska ';
|
||||||
|
break;
|
||||||
|
case 'mp4':
|
||||||
|
extraArguments += '-f mp4 ';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
// Some video codecs won't play nice with 10 bit via QSV, whitelist safe ones here
|
// Some video codecs won't play nice with 10 bit via QSV, whitelist safe ones here
|
||||||
switch (file.video_codec_name) {
|
switch (file.video_codec_name) {
|
||||||
case 'mpeg2':
|
case 'mpeg2':
|
||||||
|
|
@ -766,7 +697,7 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
break;
|
break;
|
||||||
case 'win32': // Windows - Full device, should fix child_device_type warnings
|
case 'win32': // Windows - Full device, should fix child_device_type warnings
|
||||||
response.preset += `-hwaccel qsv -hwaccel_output_format qsv
|
response.preset += `-hwaccel qsv -hwaccel_output_format qsv
|
||||||
-init_hw_device qsv:hw_any,child_device_type=d3d11va `;
|
-init_hw_device qsv=qsv:MFX_IMPL_hw `;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
response.preset += '-hwaccel qsv -hwaccel_output_format qsv -init_hw_device qsv:hw_any ';
|
response.preset += '-hwaccel qsv -hwaccel_output_format qsv -init_hw_device qsv:hw_any ';
|
||||||
|
|
@ -796,7 +727,6 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
response.preset += '-c:v av1_qsv';
|
response.preset += '-c:v av1_qsv';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
response.preset += '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -807,18 +737,45 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
// Account for different OS setup for QSV HEVC encode.
|
// Account for different OS setup for QSV HEVC encode.
|
||||||
switch (os.platform()) {
|
switch (os.platform()) {
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
response.preset += 'hevc_videotoolbox';
|
response.preset += 'hevc_videotoolbox ';
|
||||||
// Mac OS & uses hevc_videotoolbox not QSV - Only shows up on Mac installs
|
// Mac OS & uses hevc_videotoolbox not QSV - Only shows up on Mac installs
|
||||||
break;
|
break;
|
||||||
case 'linux':
|
case 'linux':
|
||||||
response.preset += 'hevc_qsv';
|
response.preset += 'hevc_qsv ';
|
||||||
break;
|
break;
|
||||||
case 'win32':
|
case 'win32':
|
||||||
response.preset += 'hevc_qsv -load_plugin hevc_hw';
|
response.preset += 'hevc_qsv -load_plugin hevc_hw ';
|
||||||
// Windows needs the additional -load_plugin. Tested working on a Win 10 - i5-10505
|
// Windows needs the additional -load_plugin. Tested working on a Win 10 - i5-10505
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
response.preset += 'hevc_qsv'; // Default to QSV
|
response.preset += 'hevc_qsv '; // Default to QSV
|
||||||
|
}
|
||||||
|
|
||||||
|
// If HW decode is happening add hwupload to encode
|
||||||
|
if (os.platform() !== 'darwin') {
|
||||||
|
if (high10 === false) { // Don't enable for High10
|
||||||
|
switch (file.video_codec_name) {
|
||||||
|
case 'mpeg2':
|
||||||
|
extraArguments += '-vf "hwupload=extra_hw_frames=64,format=qsv" ';
|
||||||
|
break;
|
||||||
|
case 'h264':
|
||||||
|
extraArguments += '-vf "hwupload=extra_hw_frames=64,format=qsv" ';
|
||||||
|
break;
|
||||||
|
case 'mjpeg':
|
||||||
|
extraArguments += '-vf "hwupload=extra_hw_frames=64,format=qsv" ';
|
||||||
|
break;
|
||||||
|
case 'hevc':
|
||||||
|
extraArguments += '-vf "hwupload=extra_hw_frames=64,format=qsv" ';
|
||||||
|
break;
|
||||||
|
case 'vp9': // Should be supported by 8th Gen +
|
||||||
|
extraArguments += '-vf "hwupload=extra_hw_frames=64,format=qsv" ';
|
||||||
|
break;
|
||||||
|
case 'av1': // Should be supported by 11th gen +
|
||||||
|
extraArguments += '-vf "hwupload=extra_hw_frames=64,format=qsv" ';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the rest of the ffmpeg command
|
// Add the rest of the ffmpeg command
|
||||||
|
|
@ -834,7 +791,7 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
|
||||||
// Normal behavior
|
// Normal behavior
|
||||||
response.preset += ` ${bitrateSettings} `
|
response.preset += ` ${bitrateSettings} `
|
||||||
+ `-preset ${inputs.encoder_speedpreset} ${inputs.extra_qsv_options} `
|
+ `-preset ${inputs.encoder_speedpreset} ${inputs.extra_qsv_options} `
|
||||||
+ `-c:a copy -c:s copy -max_muxing_queue_size 9999 ${extraArguments} ${metadataEncode}`;
|
+ `-c:a copy -c:s copy -max_muxing_queue_size 9999 ${extraArguments}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
response.processFile = true;
|
response.processFile = true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue