diff --git a/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js b/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js index 2720d0a..234696e 100644 --- a/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js +++ b/Community/Tdarr_Plugin_bsh1_Boosh_FFMPEG_QSV_HEVC.js @@ -334,7 +334,6 @@ let videoBR = 0; const plugin = (file, librarySettings, inputs, otherArguments) => { const lib = require('../methods/lib')(); const os = require('os'); - const proc = require('child_process'); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign inputs = lib.loadDefaultValues(inputs, details); const response = { @@ -353,79 +352,6 @@ const plugin = (file, librarySettings, inputs, otherArguments) => { 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 -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) { const strstreamType = file.ffProbeData.streams[i].codec_type.toLowerCase(); 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. } 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')) { - 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 (currentBitrate > inputs.hevc_max_bitrate) { // 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 switch (file.video_codec_name) { case 'mpeg2': @@ -766,7 +697,7 @@ const plugin = (file, librarySettings, inputs, otherArguments) => { break; case 'win32': // Windows - Full device, should fix child_device_type warnings 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; default: 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'; break; default: - response.preset += ''; } } } @@ -807,18 +737,45 @@ const plugin = (file, librarySettings, inputs, otherArguments) => { // Account for different OS setup for QSV HEVC encode. switch (os.platform()) { case 'darwin': - response.preset += 'hevc_videotoolbox'; + response.preset += 'hevc_videotoolbox '; // Mac OS & uses hevc_videotoolbox not QSV - Only shows up on Mac installs break; case 'linux': - response.preset += 'hevc_qsv'; + response.preset += 'hevc_qsv '; break; 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 break; 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 @@ -834,7 +791,7 @@ const plugin = (file, librarySettings, inputs, otherArguments) => { // Normal behavior response.preset += ` ${bitrateSettings} ` + `-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;