@ -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 <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 ) {
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 += '' ;
}
}
}
@ -821,6 +751,33 @@ const plugin = (file, librarySettings, inputs, otherArguments) => {
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
switch ( os . platform ( ) ) {
case 'darwin' :
@ -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 ;