Identify if file has DTS or TureHD audio stream

Any questions? Need some help?
Post Reply
ca81
Posts: 27
Joined: 14 Dec 2019, 20:08

Identify if file has DTS or TureHD audio stream

Post by ca81 »

Hello,

Among a ton of files, I have a few files that have DTS or TrueHD audio streams and wanted to check if FileBot can easily rename/identify
  • Option 1: files that have a DTS or TrueHD audio stream of the 'eng' language
  • Option 2: files that have any audio stream (of the 'eng' language) other than of the format 'AAC'
I don't want to list down the audio format for all the audio streams in the file and want to list only if any of the above criteria are met.
Any suggestions would be greatly appreciated.

peace,
~kg
User avatar
rednoah
The Source
Posts: 20170
Joined: 16 Nov 2011, 08:59

Re: Identify if file has DTS or TureHD audio stream

Post by rednoah »

I'd start by looking at the MediaInfo table:
viewtopic.php?t=4285


FileBot can identify DTS / TrueHD audio streams if you can identify them based on one MediaInfo property or another, and then add some if-then-else checks for that in your custom format to add the exactly the information you want to the proposed file path.
:idea: Please read the FAQ and How to Request Help.
ca81
Posts: 27
Joined: 14 Dec 2019, 20:08

Re: Identify if file has DTS or TureHD audio stream

Post by ca81 »

rednoah wrote: 22 Sep 2021, 03:02 I'd start by looking at the MediaInfo table:
viewtopic.php?t=4285

FileBot can identify DTS / TrueHD audio streams if you can identify them based on one MediaInfo property or another, and then add some if-then-else checks for that in your custom format to add the exactly the information you want to the proposed file path.
Thanks @rednoah

1) I did look up the MediaInfo property and the information that I looking for is available with the field "CodecID" for each for the Audio tabs (MediaInfo details below). The issue is that even after searching around and doing some trial iterations, I am unable to figure out how to get the "CodecID" information or know how to remove the extra "A_" in the "CodecID".

2) I am a n00b with Groovy and am unable to write if-then-else statements by my own. I can modify a statement to some extent but cannot write one from scratch :( and thus am requesting some help in the area

3) I did some trial iterations with FileBot v4.9.4 (code snippets below) and am unable to understand what I am doing wrong, can you please help :? :

Code: Select all

when any{ audio.take(3).collect	
		{ a ->allOf
		{af} /* provides the information in the expected format "8ch" but only for the 1st audio stream */
		}

Code: Select all

when any{ audio.take(3).collect	
		{ a ->allOf
		{a.af} /* does not seem to work and does not provide any output */
		}

Code: Select all

when any{ audio.take(3).collect	
		{ a ->allOf
		{Channels} /* provides the information in the expected format "7.1" but only for 1st audio stream */
		}

Code: Select all

when any{ audio.take(3).collect	
		{ a ->allOf
		{a.Channels} /* works partially as in it provides the information for each audio stream similar to {af} but without the "ch" */
		}
Below are the MediaInfo audio details for the file used in the trial (3 audio streams, all of 'eng' language where 1st stream is 8ch AAC, 2nd is 6ch DTS and 3rd is 8ch TrueHD):

Code: Select all

[Audio]
Count                      : 280
StreamCount                : 3
StreamKind                 : Audio
StreamKind/String          : Audio
StreamKindID               : 0
StreamKindPos              : 1
StreamOrder                : 1
ID                         : 2
ID/String                  : 2
UniqueID                   : 14793711726077703427
Format                     : AAC
Format/String              : AAC LC SBR
Format/Info                : Advanced Audio Codec Low Complexity with Spectral Band Replication
Format_Commercial          : HE-AAC
Format_Commercial_IfAny    : HE-AAC
Format_Settings            : Explicit
Format_Settings_SBR        : Yes (Explicit)
Format_Settings_SBR/String : Yes (Explicit)
Format_Settings_PS         : No (Explicit)
Format_Settings_PS/String  : No (Explicit)
Format_AdditionalFeatures  : LC SBR
CodecID                    : A_AAC-2
Duration                   : 10949461.000000
Duration/String            : 3 h 2 min
Duration/String1           : 3 h 2 min 29 s 461 ms
Duration/String2           : 3 h 2 min
Duration/String3           : 03:02:29.461
Duration/String4           : 03:05:57:17
Duration/String5           : 03:02:29.461 (03:05:57:17)
BitRate                    : 309137
BitRate/String             : 309 kb/s
Channel(s)                 : 8
Channel(s)/String          : 8 channels
ChannelPositions           : Front: L C R, Side: L R, Back: L R, LFE
ChannelPositions/String2   : 3/4/0.1
ChannelLayout              : C L R Ls Rs Lw Rw LFE
SamplesPerFrame            : 2048
SamplingRate               : 48000
SamplingRate/String        : 48.0 kHz
SamplingCount              : 525574128
FrameRate                  : 23.438
FrameRate/String           : 23.438 FPS (2048 SPF)
FrameCount                 : 256628
Compression_Mode           : Lossy
Compression_Mode/String    : Lossy
Delay                      : 31
Delay/String               : 31 ms
Delay/String1              : 31 ms
Delay/String2              : 31 ms
Delay/String3              : 00:00:00.031
Delay_Source               : Container
Delay_Source/String        : Container
Video_Delay                : 31
Video_Delay/String         : 31 ms
Video_Delay/String1        : 31 ms
Video_Delay/String2        : 31 ms
Video_Delay/String3        : 00:00:00.031
StreamSize                 : 423110652
StreamSize/String          : 404 MiB (3%)
StreamSize/String1         : 404 MiB
StreamSize/String2         : 404 MiB
StreamSize/String3         : 404 MiB
StreamSize/String4         : 403.5 MiB
StreamSize/String5         : 404 MiB (3%)
StreamSize_Proportion      : 0.03147
Title                      : AAC 8ch
Language                   : en
Language/String            : English
Language/String1           : English
Language/String2           : en
Language/String3           : eng
Language/String4           : en
Default                    : Yes
Default/String             : Yes
Forced                     : No
Forced/String              : No

[Audio]
Count                      : 280
StreamCount                : 3
StreamKind                 : Audio
StreamKind/String          : Audio
StreamKindID               : 1
StreamKindPos              : 2
StreamOrder                : 2
ID                         : 3
ID/String                  : 3
UniqueID                   : 15682389536924796531
Format                     : DTS
Format/String              : DTS
Format/Info                : Digital Theater Systems
Format/Url                 : https://en.wikipedia.org/wiki/DTS_(sound_system)
Format_Commercial          : DTS
Format_Settings_Mode       : 16
Format_Settings_Endianness : Big
CodecID                    : A_DTS
Duration                   : 10949462.000000
Duration/String            : 3 h 2 min
Duration/String1           : 3 h 2 min 29 s 462 ms
Duration/String2           : 3 h 2 min
Duration/String3           : 03:02:29.462
Duration/String4           : 03:02:00:32
Duration/String5           : 03:02:29.462 (03:02:00:32)
BitRate_Mode               : CBR
BitRate_Mode/String        : Constant
BitRate                    : 1509000
BitRate/String             : 1 509 kb/s
Channel(s)                 : 6
Channel(s)/String          : 6 channels
ChannelPositions           : Front: L C R, Side: L R, LFE
ChannelPositions/String2   : 3/2/0.1
ChannelLayout              : C L R Ls Rs LFE
SamplesPerFrame            : 512
SamplingRate               : 48000
SamplingRate/String        : 48.0 kHz
SamplingCount              : 525574176
FrameRate                  : 93.750
FrameRate/String           : 93.750 FPS (512 SPF)
FrameCount                 : 1026512
BitDepth                   : 24
BitDepth/String            : 24 bits
Compression_Mode           : Lossy
Compression_Mode/String    : Lossy
Delay                      : 0
Delay/String3              : 00:00:00.000
Delay_Source               : Container
Delay_Source/String        : Container
Video_Delay                : 0
Video_Delay/String3        : 00:00:00.000
StreamSize                 : 2065342144
StreamSize/String          : 1.92 GiB (15%)
StreamSize/String1         : 2 GiB
StreamSize/String2         : 1.9 GiB
StreamSize/String3         : 1.92 GiB
StreamSize/String4         : 1.923 GiB
StreamSize/String5         : 1.92 GiB (15%)
StreamSize_Proportion      : 0.15360
Title                      : DTS 6ch
Language                   : en
Language/String            : English
Language/String1           : English
Language/String2           : en
Language/String3           : eng
Language/String4           : en
Default                    : No
Default/String             : No
Forced                     : No
Forced/String              : No

[Audio]
Count                      : 284
StreamCount                : 3
StreamKind                 : Audio
StreamKind/String          : Audio
StreamKindID               : 2
StreamKindPos              : 3
StreamOrder                : 3
ID                         : 4
ID/String                  : 4
UniqueID                   : 16605674554314757963
Format                     : MLP FBA
Format/String              : MLP FBA 16-ch
Format/Info                : Meridian Lossless Packing FBA with 16-channel presentation
Format_Commercial          : Dolby TrueHD with Dolby Atmos
Format_Commercial_IfAny    : Dolby TrueHD with Dolby Atmos
Format_AdditionalFeatures  : 16-ch
CodecID                    : A_TRUEHD
CodecID/Url                : http://www.dolby.com/consumer/technology/trueHD.html
Duration                   : 10949439.000000
Duration/String            : 3 h 2 min
Duration/String1           : 3 h 2 min 29 s 439 ms
Duration/String2           : 3 h 2 min
Duration/String3           : 03:02:29.439
Duration/String5           : 03:02:29.439
BitRate_Mode               : VBR
BitRate_Mode/String        : Variable
BitRate                    : 3402708
BitRate/String             : 3 403 kb/s
BitRate_Maximum            : 5616000
BitRate_Maximum/String     : 5 616 kb/s
Channel(s)                 : 8
Channel(s)/String          : 8 channels
ChannelPositions           : Front: L C R, Side: L R, Back: L R, LFE
ChannelPositions/String2   : 3/2/2.1
ChannelLayout              : L R C LFE Ls Rs Lb Rb
SamplesPerFrame            : 40
SamplingRate               : 48000
SamplingRate/String        : 48.0 kHz
SamplingCount              : 525573072
FrameRate                  : 1200.000
FrameRate/String           : 1 200.000 FPS (40 SPF)
FrameCount                 : 13139327
Compression_Mode           : Lossless
Compression_Mode/String    : Lossless
Delay                      : 0
Delay/String3              : 00:00:00.000
Delay_Source               : Container
Delay_Source/String        : Container
Video_Delay                : 0
Video_Delay/String3        : 00:00:00.000
StreamSize                 : 4657218004
StreamSize/String          : 4.34 GiB (35%)
StreamSize/String1         : 4 GiB
StreamSize/String2         : 4.3 GiB
StreamSize/String3         : 4.34 GiB
StreamSize/String4         : 4.337 GiB
StreamSize/String5         : 4.34 GiB (35%)
StreamSize_Proportion      : 0.34635
Title                      : TrueHD Atmos 8ch
Language                   : en
Language/String            : English
Language/String1           : English
Language/String2           : en
Language/String3           : eng
Language/String4           : en
Default                    : No
Default/String             : No
Forced                     : No
Forced/String              : No
NumberOfDynamicObjects     : 11
BedChannelCount            : 1
BedChannelCount/String     : 1 channel
BedChannelConfiguration    : LFE
User avatar
rednoah
The Source
Posts: 20170
Joined: 16 Nov 2011, 08:59

Re: Identify if file has DTS or TureHD audio stream

Post by rednoah »

e.g. access all CodecID values for all audio streams and strip the leading A_ part if any:

Code: Select all

{
	audio.CodecID*.after(/_/)
}

Code: Select all

[AAC-2, DTS, TRUEHD]

e.g. check if any CodecID matches TRUEHD and add a corresponding tag to the file name if so:

Code: Select all

{
	audio.CodecID =~ /TRUEHD/ ? ' [TrueHD]' : null
}

Code: Select all

 [TrueHD]


EDIT:

Do you want to add Channel(s)/String information (e.g. 8 channels) to the file name for each TRUEHD audio stream?

e.g. check if any CodecID matches TRUEHD and add a corresponding tag to the file name if so:

Code: Select all

{
	audio.findAll{ it.CodecID =~ /TRUEHD/ }.'Channel(s)/String'
}

Code: Select all

[8 channels]

:idea: The built-in af and channels bindings will give you the single maximum value from all the audio streams, which may or may not be the TRUEHD stream.
:idea: Please read the FAQ and How to Request Help.
ca81
Posts: 27
Joined: 14 Dec 2019, 20:08

Re: Identify if file has DTS or TureHD audio stream

Post by ca81 »

Many Thanks @ rednoah.
I was able to get the format that I wanted with some modifications to your code snippets above.

My code:

Code: Select all

({
	any{ audio.take(3).collect	/* to get info for 1st, 2nd & 3rd audio streams only */
		{ a ->allOf
			{ any{ a.LanguageString3 }{ 'XAX' }.upper() }	    /* to get the language of the audio stream in a 3 character format i.e. ENG/JPN/HIN and display correctly but 'XAX' means no audio language is mentioned for the audio stream */
			{ a.CodecID.removeAll('A_').removeAll('-2')}					/* to get the CodecID i.e. AAC, DTS, TRUEHD, etc. from the audio stream */
			{ a.ChannelsString.removeAll(' ').removeAll('annels')}			/* to get the audio channels in the audio stream */
			.join('-')	/* to join different parts of the info for each audio stream with a hyphen */
		}.join(', ')		/* to separate each audio stream with a comma & space */
	   }{ 'No Audio' }		/* to display 'No Audio' if there are no audio streams */
}),
Output:

Code: Select all

(ENG-AAC-8ch, ENG-DTS-6ch, ENG-TRUEHD-8ch),
Something for later but I think I will need to learn a bit of Groovy to understand the proper working of various code snippets :)
kim
Power User
Posts: 1157
Joined: 15 May 2014, 16:17

Re: Identify if file has DTS or TureHD audio stream

Post by kim »

I made some changes to your format:

Code: Select all

{
	any{ audio.findAll{it.LanguageString3 == 'eng' && (it.CodecID =~ ('DTS') || it.CodecID =~ 'TRUEHD') }.collect
		{ a -> allOf
			{ a.LanguageString3.upper() }
			{ a.CodecID.removeAll('A_')}
			{ a.Channels + 'ch'}
			.join('-')
		}.unique().joining(', ', ' (', ')')
	   }{}
}
or use a custom version of viewtopic.php?f=5&t=5285&start=75 for you I made:

Code: Select all

{
	def preferredLang = 'ENG'
	def useChFilter = false
	def filter = { [it.lang, it.codec.space('-'), it.ch].findAll() }

	def codecList =
	[
	'MPEG Audio' : 'MP2',
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'FLAC' : 'FLAC',
	'AAC LC' : 'AAC',
	'AAC LC SBR' : 'AAC',
	'AAC LC SBR PS' : 'AAC',
	'AC 3' : 'AC3',
	'AC 3 Dep' : 'EAC3',
	'E AC 3' : 'EAC3',
	'E AC 3 JOC' : 'EAC3 Atmos',
	'AC 3 Dep JOC' : 'EAC3 Atmos',
	'DTS' : 'DTS',
	'DTS 96 24' : 'DTS 96-24',
	'DTS ES' : 'DTS-ES',
	'DTS ES XXCH' : 'DTS-ES',
	'DTS XBR' : 'DTS-HD HRA',
	'DTS ES XBR' : 'DTS-HD HRA',
	'DTS ES XXCH XBR' : 'DTS-HD HRA',
	'DTS XLL' : 'DTS-HD MA',
	'DTS ES XLL' : 'DTS-HD MA',
	'DTS ES XXCH XLL' : 'DTS-HD MA',
	'DTS XLL X' : 'DTS X',
	'MLP FBA' : 'TrueHD',
	'MLP FBA 16 ch' : 'TrueHD Atmos'
	]

	def audioStreams = []
	def audioClean = { it.replaceAll(/[\p{Pd}\p{Space}]/, ' ').replaceAll(/\p{Space}{2,}/, ' ').slash(' ') }
	def channelClean = { it.replaceAll(/Debug.+|Object\sBased\s?\/?|(\d+)?\sobjects\s\/\s|0.(?=\d.\d)|20/).replaceAll(/6.0/,'5.1').replaceAll(/8.0/,'7.1') }
	def listStream = { it.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }.unique()*.join('-') }
	def oneStream = { listStream(it)[0] }
	def dString = { it.toDouble().toString() }
	def toInt = { it.toInteger() }

	any{audio.collect{ au ->
		def codec = audioClean(any{ au['CodecID/Hint'] }{ au['Format'] })
		def format_profile = any{ audioClean(au['Format_AdditionalFeatures'])}{}
		def String ch = any { au.Channels + 'ch'}{  }

		def chFilter =	( ( ( (ac == 'AAC'||ac == 'MP3') && ch != '2.0') || ( (ac == 'AC3'||ac == 'EAC3'||ac == 'DTS'||ac == 'TrueHD'||ac == 'MLPFBA') && ch != '5.1' ) ) ? ch : null )

		def combined = allOf{codec}{format_profile}.join(' ')

		audioStreams << ['index' : codecList.findIndexOf { it.key == combined }, 'default' : any {au['default'][0].toBoolean() }{ audio.size == 1 ? true : '' },
		'codec' : codecList.get(combined, 'Add to "' + combined + '" codecList'), 'combined' : combined, 'ch' : useChFilter ? chFilter : ch,
		'bitrate' : any{ toInt(au.BitRate) }{ toInt(au.BitRate_Maximum) }{ dString(au.FrameRate) }{null},
		'objects' : any{def objects = au['NumberOfDynamicObjects']; objects ? "[$objects Objs]" : ''}{null}, 'lang' : any{ au.'LanguageString3'.upper() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()

	any{addToList}{ listStream(audioStreams.findAll{ it.lang == preferredLang && (it.codec =~ ('DTS') || it.codec =~ 'TrueHD') }.unique{it.codec}).joining(', ', ' (', ')') }{}
	}{''}
}
Post Reply