From f3aca08aea4a74d79526349972ee299e976c47bb Mon Sep 17 00:00:00 2001 From: MrMeeb Date: Sun, 21 Apr 2024 19:50:41 +0000 Subject: [PATCH] Handling of DTS-HD MA --- Tdarr_Plugin_MM1_MrMeeb_Full_Stack.js | 151 +++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 4 deletions(-) diff --git a/Tdarr_Plugin_MM1_MrMeeb_Full_Stack.js b/Tdarr_Plugin_MM1_MrMeeb_Full_Stack.js index d9b3165..224a02b 100644 --- a/Tdarr_Plugin_MM1_MrMeeb_Full_Stack.js +++ b/Tdarr_Plugin_MM1_MrMeeb_Full_Stack.js @@ -115,11 +115,15 @@ const response = { let audioIdxTruehd = -1; let trueHD = -1; let trueHDi = -1; + let audioIdxDtshdma = -1; + let dtshdma = -1; + let dtshdmai = -1; let ac3Count = 0; + let dtsHandled = 0; console.log(` === Running processAudio function === `) - // Go through all streams, hunting for TrueHD + // Go through all streams, hunting for TrueHD/DTS-HD MA for (let i = 0; i < file.ffProbeData.streams.length; i ++) { // Work with audio streams only @@ -259,6 +263,145 @@ const response = { } + // Identify if stream is DTS-HD MA + if (file.ffProbeData.streams[i].codec_name.toLowerCase() === 'dts') { + + // Check if DTS-HD MA has already been handled by a previous run + // Assume that it will be the second stream (first audio stream) - it should be, if already handled + MMChannelLayout = file.ffProbeData.streams[i].channel_layout.replace('(side)', ''); // Have to declare this here to make the if statement work. Leaving it in place further down as well + + if (file.ffProbeData.streams[i].tags.title === `DTS-HD MA - ${MMChannelLayout} - MM`) { + + console.log(`Stream ${i} (audio stream ${audioIdx}) is DTS-HD MA and has already been handled. Safe to assume this file has already been treated.`); + response.infoLog += `Stream ${i} (audio stream ${audioIdx}) is DTS-HD MA and has already been handled. Safe to assume this file has already been treated.\n` + + // Mark DTS-HD MA handling process as complete causing everything else audio-related to be skipped + dtsHandled = 1 + + } else { + + console.log(`Stream ${i} (audio stream ${audioIdx}) is DTS-HD MA and has not been handled. Commencing DTS-HD MA handling process`); + response.infoLog += `Stream ${i} (audio stream ${audioIdx}) is DTS-HD MA. Commencing DTS-HD MA handling process.\n` + + }; + + dtshdma = audioIdx; // Index of DTS-HD MA track relative to other audio tracks + dtshdmai = i; // Index of DTS-HD MA track within all tracks (audio, video, subs, etc) + let dtshdmaLang = file.ffProbeData.streams[i].tags.language // Language of DTS-HD MA track + let dtshdmaReplacementCount = 0 // Number of DTS-HD MA replacement candidates + + // Look if there is a suitable AC3 5.1 track to use alongside it + + for (let i = 0; i < file.ffProbeData.streams.length; i ++) { // Iterate through all streams + + if (dtsHandled == 0 && file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') { // If the stream is an audio stream + + audioIdxDtshdma++; // Index of replacement track + MMCodec = file.ffProbeData.streams[i].codec_name.toUpperCase(); + MMChannelLayout = file.ffProbeData.streams[i].channel_layout.replace('(side)', ''); + + try { + + // Identify if stream is commentary track + if ( + file.ffProbeData.streams[i].tags.title != undefined && + file.ffProbeData.streams[i].tags.title.toLowerCase().includes("commentary") || + file.ffProbeData.streams[i].disposition.comment == 1 + ) { + + console.log(`Stream ${i} (audio stream ${audioIdxDtshdma}) is probably a commentary track. Removing.`) + response.infoLog += `Stream ${i} (audio stream ${audioIdxDtshdma}) is probably a commentary track. Removing.\n` + + } + + // Identify if stream is AC3 5.1 + else if ( + file.ffProbeData.streams[i].codec_name.toLowerCase() === 'ac3' && // is codec AC3 + file.ffProbeData.streams[i].channels === 6 && // does it have 6 channels (5.1) + file.ffProbeData.streams[i].tags.language === dtshdmaLang // does it have the same language as the DTS-HD MA track + ) { + + console.log(`Stream ${i} (audio stream ${audioIdxDtshdma}) is AC3 5.1 and in matching language. Keeping alongside the DTS-HD MA track.`); + console.log(`${MMCodec} <- Should be AC3`) + + response.infoLog += `Stream ${i} (audio stream ${audioIdxDtshdma}) is AC3 5.1 and in matching language. Keeping alongside the DTS-HD MA track.\n` + response.infoLog +=`${MMCodec} <- Should be AC3\n` + + dtshdmaReplacementCount++ // Add to the DTS-HD MA replacement count + + if (dtshdmaReplacementCount <= 1) { // If we found a single DTS-HD MA replacement... + + ffmpegAudioFirstTrack = ` -map -0:a -map 0:a:${dtshdma} -metadata:s:a:0 "title=DTS-HD MA - ${MMChannelLayout} - MM" -disposition:a:0 default -map 0:a:${audioIdxDtshdma} -metadata:s:a:1 "title=${MMCodec} - ${MMChannelLayout} - MM"` // Keep both the DTS-HD MA and AC3 tracks, label them + + } + else { + + console.log('More than 1 suitable AC3 5.1 track has been detected - something has probably gone wrong in detection of commentary tracks. The first found track will be kept') + response.infoLog += 'More than 1 suitable AC3 5.1 track has been detected - something has probably gone wrong in detection of commentary tracks. The first found track will be kept\n' + + } + + + } + + else if ( + file.ffProbeData.streams[i].codec_name.toLowerCase() === 'ac3' && // is codec AC3 + file.ffProbeData.streams[i].channels === 6 && // does it have 6 channels (5.1) + file.ffProbeData.streams[i].tags.language !== dtshdmaLang && // does it NOT match the language of the DTS-HD MA track + file.ffProbeData.streams[i].tags.language.toLowerCase() == 'eng' // is the AC3 track in English + ) { + + console.log(`Stream ${i} (audio stream ${audioIdxDtshdma}) is AC3 5.1. It does not match the native language of the movie, but is in English. Probably want to keep.`); + response.infoLog += `Stream ${i} (audio stream ${audioIdxDtshdma}) is AC3 5.1. It does not match the native language of the movie, but is in English. Probably want to keep.\n` + + ffmpegAudioOtherTracks += ` -map 0:a:${audioIdxDtshdma}` // Add the track to the list of additional tracks + + } + + else if (file.ffProbeData.streams[i].codec_name.toLowerCase() !== 'dts') { // Remove any track that isn't AC3 since we already have DTS-HD MA to work with + + console.log(`Stream ${i} (audio stream ${audioIdxDtshdma}) isn't AC3 5.1, and DTS-HD MA is already available to create an AC3 5.1 track if not present. Removing.`) + response.infoLog += `Stream ${i} (audio stream ${audioIdxDtshdma}) isn't AC3 5.1, and DTS-HD MA is already available to create an AC3 5.1 track if not present. Removing.\n` + + }; + + } catch (error) { + + } + + }; + + }; + + if (dtsHandled == 0 && dtshdmaReplacementCount == 0) { // If we didn't find a replacement candidate + + console.log('A suitable DTS-HD MA replacement track is not available. Creating my own.') + //console.log(`${MMCodec} <- Should be AC3`) + + + if (file.ffProbeData.streams[dtshdmai].channels > 6) { // If the DTS-HD MA track has more than 6 channels, downmix to 6 channels + + response.infoLog += 'DTS-HD MA track exists, but no AC3 compatibility track is present. Creating one, and downmixing to 6 channels.\n' + + ffmpegAudioFirstTrack = ` -map -0:a -map 0:a:${dtshdma} -metadata:s:a:0 "title=DTS-HD MA - ${MMChannelLayout} - MM" -disposition:a:0 default -map 0:a:${dtshdma} -c:a:1 ac3 -b:a:1 640k -ac:a:1 6 -metadata:s:a:1 "title=AC3 - 5.1 - MM"` + + } + else { // Otherwise, create an AC3 track with the same channel layout + + response.infoLog += 'DTS-HD MA track exists, but no AC3 compatibility track is present. Creating one.\n' + + ffmpegAudioFirstTrack = ` -map -0:a -map 0:a:${dtshdma} -metadata:s:a:0 "title=DTS-HD MA - ${MMChannelLayout} - MM" -disposition:a:0 default -map 0:a:${dtshdma} -c:a:1 ac3 -b:a:1 640k -ac:a:1 ${file.ffProbeData.streams[dtshdmai].channels} -metadata:s:a:1 "title=AC3 - 5.1 - MM"` + + } + + + } + + // Mark DTS-HD MA handling process as complete, skipping the logic for no THD/DTS-HD MA. Was already set if the run had completed before. + dtsHandled = 1 + + } + } catch (error) { console.log(error) } @@ -266,9 +409,9 @@ const response = { } }; - - // Logic for if no TrueHD track present - if (trueHD < 0) { + + // Logic for if no TrueHD/DTS-HD MA track present + if (trueHD < 0 && dtsHandled == 0) { console.log('No TrueHD track is present in the file.') response.infoLog += `No TrueHD track is present.\n`