Multiple audio tracks with different codecs and languages

All about user-defined episode / movie / file name format expressions
User avatar
rednoah
The Source
Posts: 22898
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Multiple audio tracks with different codecs and languages

Post by rednoah »

I've never seen a Title field for an audio stream:

Code: Select all

Title                            : Dolby Digital Plus Audio / 7.1 / 48 kHz / 1280 kbps
I guess this Title tag is supposed to show up when you select a given audio stream in your media player. Someone thought this is a good display value for this audio stream.

Might be useful, but probably won't be defined for the vast majority of files.
:idea: Please read the FAQ and How to Request Help.
devster
Posts: 417
Joined: 06 Jun 2017, 22:56

Re: Multiple audio tracks with different codecs and languages

Post by devster »

My assumption was that the "title" field is an optional metadata tag and I wouldn't want to rely on it.

For naming purposes I found out that the AdditionalFeatures bascically means a hybrid stream.
In this case there seem to be:
  • "base" 5.1 AC-3 stream, decodable by an AC-3 decoder. (The Format field which represents the "minimal" decoder required)
  • Dependant E-AC-3 stream with 2 additional channels, optional and apparently interleaved with the first one (The Format/String apparently)
It seems to be part of E-AC-3 which allows embedding a core AC-3 stream.

The ChannelPositions/String2 seems a bug, a workaround in this specific case would be to tokenize by comma ChannelPositions (Front: L C R, Side: L R, Back: L R, LFE), strip whatever's before the colon, count number of words in the string (3,2,2,1) with the last one being the Low Frequency Effects.
I only work in black and sometimes very, very dark grey. (Batman)
antisgae
Posts: 13
Joined: 29 Aug 2018, 22:48

Re: Multiple audio tracks with different codecs and languages

Post by antisgae »

Just in case it helps to somebody i modified the code and added also flac audio.
Looks like this: "ESP ac3 2.0 ENG flac 1.0"
./1961 - Homicidal - Homicidio - William Castle/1961 - Homicidal - Homicidio - William Castle BDR 1080p 35.0Mbps ESP ac3 2.0 ENG flac 1.0 SUB ENG ESP.mkv

Code: Select all

{
	def codecList =
	[
	'MP3' : 'mp3',
	'FLAC' : 'flac',
	'PCM' : 'pcm',
	'AAC LC' : 'aac',
	'AAC LC SBR' : 'aac',
	'AC 3' : 'ac3',
	'AC 3 Dep' : 'eac3',
	'E AC 3' : 'eac3',
	'E AC 3 JOC' : 'eac3 Atmos',
	'DTS' : 'dts',
	'DTS 96 24' : 'dts',
	'DTS ES' : 'dtses',
	'DTS ES XXCH' : 'dtses',
	'DTS XBR' : 'dts',
	'DTS ES XBR' : 'dtses',
	'DTS ES XXCH XBR' : 'dtses',
	'DTS XLL' : 'dts',
	'DTS ES XLL' : 'dtses',
	'DTS ES XXCH XLL' : 'dtses',
	'DTS XLL X' : 'dtsx',
	'MLP FBA' : 'truehd',
	'MLP FBA 16 ch' : 'truehd Atmos'
	]
	def filter = { [it.lang, it.codec, it.ch, it.objects] }

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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	def dString = { it.toDouble().toString() }
	def toInt = { it.toInteger() }

	audio.collect{ au ->
		def codec = audioClean(any{ au['CodecID/Hint'] }{ au['Format'] })
		def format_profile = any{ audioClean(au['Format_AdditionalFeatures'])}{}
		def String ch = any{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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' : au['default'][0].toBoolean(),
		'codec' : codecList.get(combined, 'UNKNOWN_FORMAT'), 'combined' : combined, 'ch' : ch, 
		'bitrate' : any{toInt(au.BitRate)}{toInt(au.BitRate_Maximum)}{au.FrameRate.toDouble()}{null},
		'objects' : any{'[' + au['NumberOfDynamicObjects'] + ' Objs]'}{null}, 'lang' : any{au.'LanguageString3'.upper().replaceAll("SPA","ESP")}{null} ]
		return audioStreams
	}

	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{it.default == true})

	allStreams.join(' ').space(' ')
	preferredStream.space(' ')
	defaultStream.space(' ')
	bestBitRate.space(' ')
	[bestBitRate, preferredStream].unique().join(' ')
	[defaultStream, bestBitRate].unique().join(' ')
}
kim
Power User
Posts: 1251
Joined: 15 May 2014, 16:17

Re: Multiple audio tracks with different codecs and languages

Post by kim »

added bestPreferredLang = to find best stream in your preferred language (preferredLang) or default as backup
e.g. German

Code: Select all

{
	def preferredLang = 'Deu'
	
	def codecList =
	[
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'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',
	'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 filter = { [it.codec, it.ch, it.objects, it.lang] }

	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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	def dString = { it.toDouble().toString() }
	def toInt = { it.toInteger() }

	audio.collect{ au ->
		def codec = audioClean(any{ au['CodecID/Hint'] }{ au['Format'] })
		def format_profile = any{ audioClean(au['Format_AdditionalFeatures'])}{}
		def String ch = any{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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' : au['default'][0].toBoolean(),
		'codec' : codecList.get(combined, 'UNKNOWN_FORMAT'), 'combined' : combined, 'ch' : ch, 
		'bitrate' : any{toInt(au.BitRate)}{toInt(au.BitRate_Maximum)}{au.FrameRate.toDouble()}{null},
		'objects' : any{'[' + au['NumberOfDynamicObjects'] + ' Objs]'}{null}, 'lang' : any{au.'LanguageString3'.upperInitial()}{null} ]
		return audioStreams
	}

	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{it.default == true})
	def bestPreferredLang = any{audioStreams.findAll{it.lang == preferredLang }.sort{a, b -> b.bitrate <=> a.bitrate}.collect{ filter(it) }*.minus(null).unique().get(0).join(' ')}{defaultStream}

	bestPreferredLang.space('.')
}
kim
Power User
Posts: 1251
Joined: 15 May 2014, 16:17

Re: Multiple audio tracks with different codecs and languages

Post by kim »

Added addToList = to make it more user friendly ( output e.g. [Add to "DTS XBR" codecList] )
Added useChFilter = to make it more user friendly ( true or false, makes it more "scene" like )

Code: Select all

{
	def preferredLang = 'Eng'
	def useChFilter = false
	def filter = { [it.codec, it.ch, it.objects, it.lang] }

	def codecList =
	[
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()
	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
	def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
	}{'NO_AUDIO'}
}
Only use one of these lines:

Code: Select all

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
useChFilter = this line:

Code: Select all

def chFilter =	( ( ( (ac == 'AAC'||ac == 'MP3') && ch != '2.0') || ( (ac == 'AC3'||ac == 'EAC3'||ac == 'DTS'||ac == 'TrueHD'||ac == 'MLPFBA') && ch != '5.1' ) ) ? ch : null )
= if AAC/MP3 2.0 OR AC3/EAC3/DTS/TrueHD/MLPFBA 5.1, then don't show the 2.0/5.1 part

allStreams = All Audio Streams
preferredStream = The last (best) match from codecList (order matters, from low to high quality / or what you prefer)
defaultStream = The Audio Stream tagged "default=Yes" or if only one Stream
bestBitRate = The Audio Stream with the highest BitRate (with BitRate_Maximum/FrameRate as backup)
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Multiple audio tracks with different codecs and languages

Post by nartana »

I couldn't find an answer (bc it's probably obvious): Kim and others helped evolve the def codecList expression, in this thread, but I'm not sure where/how to use that long expression, that defines all the different possible codecs/formats. I want to make sure any movie with Atmos indicates as much, but that doesn't always happen.

I use CLI via SSH to rename media on my Synology (where I have FileBot installed.) It works great. I have a basic understanding of the expressions I've compiled. But is "codecList" a file in my FileBot package that's installed on my Syno? Do I edit that to add the many awesome codecs in the code Kim has evolved, here? Or is that long expression something I add to a CLI command each time I want to process files in my 'unsorted' folder?
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Multiple audio tracks with different codecs and languages

Post by nartana »

Renaming output, CLI via Synology FB install (all packages updated):

Code: Select all

MovieTitle (2019) 118mins [18.0 Mbps] (1920x800) Dolby Digital 5.1 [6ch]
Renaming output, new Windows 10 installation of standalone FB app:

Code: Select all

SameMovieTitle 118mins (18.0 Mbps) (1920x800) TrueHD 7.1 Atmos [8ch]
According to MediaInfo, the second (Windows) output is correct: (8ch Atmos)

I would like to continue using CLI via Synology package - I’ve tried at least ten different expressions I’ve found on the forums, re. audio codec, but it always outputs 5.1 Dolby.

I know I'm not providing all the info you need, but if we know that all the modules are updated to latest, on the Syno server... is there a default reason why outputs differ?
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Multiple audio tracks with different codecs and languages

Post by nartana »

This is the expression I use via CLI (which produces the incorrect codec/channel output, on rename):

Code: Select all

filebot -rename -r /volume1/Media/UNSORTED/Movies/ --db TheMovieDB -non-strict --conflict auto --output /volume1/Media/SORTED/ --format "Movies/{certification}/{n} ({y})/{n} ({y}) {minutes}mins [{mbps}] ({resolution}) {aco} {channels} [{af}]/{ny} @{mbps} {tags.upper[]} {' CD'+pi}" --action copy
User avatar
rednoah
The Source
Posts: 22898
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Multiple audio tracks with different codecs and languages

Post by rednoah »

Compare filebot -script fn:sysinfo output. Different versions of MediaInfo may yield different values.
:idea: Please read the FAQ and How to Request Help.
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Multiple audio tracks with different codecs and languages

Post by nartana »

Thank you @rednoah (also for indulging sloppy question format.)

The output is below — I assume the next step is for me to check the version I'm using vs. the newest version available.

Code: Select all

FileBot 4.8.5 (r6224)
JNA Native: 5.2.2
MediaInfo: 19.09
7-Zip-JBinding: 9.20
Chromaprint: fpcalc version 1.4.3
Extended Attributes: OK
Unicode Filesystem: OK
Script Bundle: 2019-05-15 (r565)
Groovy: 2.5.6
JRE: Java(TM) SE Runtime Environment 1.8.0_201
JVM: 64-bit Java HotSpot(TM) 64-Bit Server VM
CPU/MEM: 4 Core / 1 GB Max Memory / 40 MB Used Memory
OS: Linux (amd64)
HW: Linux ******** 3.10.105 #24922 SMP Wed Jul 3 16:37:24 CST 2019 x86_64 GNU/Linux synology_avoton_1815+
DATA: /volume1/@appstore/filebot/data/admin
Package: SPK
License: FileBot License P75********
User avatar
rednoah
The Source
Posts: 22898
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Multiple audio tracks with different codecs and languages

Post by rednoah »

Well, it's not about being newer or older, but about being different. FileBot will bundle the latest version on platform-dependent builds, e.g. MSI package. But on platforms where there is more than one CPU architecture, the FileBot package will only bundle platform-independent components, i.e. SPK package, and rely on 3rd party dependencies for platform-dependent components, i.e. MediaInfo, Chromaprint, etc. These tend to be somewhat outdated on Synology because they're maintained by 3rd party volunteers.

MediaInfo: 19.09 is the latest one though, so that should work exactly the same as the latest beta, which bundles this version of MediaInfo as well:
viewtopic.php?t=1609
:idea: Please read the FAQ and How to Request Help.
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Multiple audio tracks with different codecs and languages

Post by nartana »

Thank you, I didn't know that about Syno packages. Now it makes more sense.

I'll test results running FB on a MacMini that's connected to the Syno (to see if my results differ vs. running the Syno FB build.)

Since I'll be trying FB on a diff. platform, it's a good time to ask:
Is the GUI (app) version of FB the only way to use these long { def codecList... } definitions of audio codecs? Like in the "Filter" field of the GUI version?

Or, if there's a thread, or keywords that'll help me search how to use these w/ the CLI-based FB operations...?

I know it's a real huckleberry question. I'm brain-blocked on the next step with this.

Thanks for helping me better understand these diff results (Syno FB vs. Windows FB.)
User avatar
rednoah
The Source
Posts: 22898
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Multiple audio tracks with different codecs and languages

Post by rednoah »

What makes you think that format expressions work different in the GUI and the CLI? They're the same of course. Format expressions work the same in both GUI and CLI, it's literally the same code.


:idea: Except passing complex multi-line argument values on the command-line might be a little bit troublesome, doable, but annoying. Use the @file syntax for reading command-line arguments from external text files.


:idea: You can use filebot -script fn:mediainfo /files to dump raw media info tables, so you can see and compare the raw data that FileBot is getting back from libmediainfo.
:idea: Please read the FAQ and How to Request Help.
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Multiple audio tracks with different codecs and languages

Post by nartana »

Thanks again — that makes so much sense, that the interface is the interface (and expressions work the same, underneath.)

And thank you for the tools. Time to learn about syntax and to compare the data FileBot is getting back from libmediainfo.

Even in the short year I've been using FileBot, it has been really cool to see how you continuously evolve it, based on input.

Cheers @rednoah.

-Erin
User avatar
rednoah
The Source
Posts: 22898
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Multiple audio tracks with different codecs and languages

Post by rednoah »

nartana wrote: 15 Mar 2020, 00:19 Even in the short year I've been using FileBot, it has been really cool to see how you continuously evolve it, based on input.
Keep the good ideas coming. I might not always implement exactly what you want, but it might inspire me to implement something even more interesting. :lol:
:idea: Please read the FAQ and How to Request Help.
Keven07
Posts: 22
Joined: 13 Apr 2020, 08:39

Re: Multiple audio tracks with different codecs and languages

Post by Keven07 »

kim wrote: 05 Mar 2020, 22:11 Added addToList = to make it more user friendly ( output e.g. [Add to "DTS XBR" codecList] )
Added useChFilter = to make it more user friendly ( true or false, makes it more "scene" like )

Code: Select all

{
	def preferredLang = 'Eng'
	def useChFilter = false
	def filter = { [it.codec, it.ch, it.objects, it.lang] }

	def codecList =
	[
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()
	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
	def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
	}{'NO_AUDIO'}
}
Only use one of these lines:

Code: Select all

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
useChFilter = this line:

Code: Select all

def chFilter =	( ( ( (ac == 'AAC'||ac == 'MP3') && ch != '2.0') || ( (ac == 'AC3'||ac == 'EAC3'||ac == 'DTS'||ac == 'TrueHD'||ac == 'MLPFBA') && ch != '5.1' ) ) ? ch : null )
= if AAC/MP3 2.0 OR AC3/EAC3/DTS/TrueHD/MLPFBA 5.1, then don't show the 2.0/5.1 part

allStreams = All Audio Streams
preferredStream = The last (best) match from codecList (order matters, from low to high quality / or what you prefer)
defaultStream = The Audio Stream tagged "default=Yes" or if only one Stream
bestBitRate = The Audio Stream with the highest BitRate (with BitRate_Maximum/FrameRate as backup)
this what i ' m looking for many days, now my search is over. <3
Thanks for this format, Really appreciate your work
AbedlaPaille
Posts: 107
Joined: 12 Apr 2020, 04:02

Re: Multiple audio tracks with different codecs and languages

Post by AbedlaPaille »

kim wrote: 05 Mar 2020, 22:11 Added addToList = to make it more user friendly ( output e.g. [Add to "DTS XBR" codecList] )
Added useChFilter = to make it more user friendly ( true or false, makes it more "scene" like )

Code: Select all

{
	def preferredLang = 'Eng'
	def useChFilter = false
	def filter = { [it.codec, it.ch, it.objects, it.lang] }

	def codecList =
	[
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()
	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
	def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
	}{'NO_AUDIO'}
}
Only use one of these lines:

Code: Select all

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
useChFilter = this line:

Code: Select all

def chFilter =	( ( ( (ac == 'AAC'||ac == 'MP3') && ch != '2.0') || ( (ac == 'AC3'||ac == 'EAC3'||ac == 'DTS'||ac == 'TrueHD'||ac == 'MLPFBA') && ch != '5.1' ) ) ? ch : null )
= if AAC/MP3 2.0 OR AC3/EAC3/DTS/TrueHD/MLPFBA 5.1, then don't show the 2.0/5.1 part

allStreams = All Audio Streams
preferredStream = The last (best) match from codecList (order matters, from low to high quality / or what you prefer)
defaultStream = The Audio Stream tagged "default=Yes" or if only one Stream
bestBitRate = The Audio Stream with the highest BitRate (with BitRate_Maximum/FrameRate as backup)
Can this awesome bit of wizardry be tweaked to prefer the stream in the language matching the one from info.OriginalLanguage? Cheers for this snippet kim it's quite amazing.
kim
Power User
Posts: 1251
Joined: 15 May 2014, 16:17

Re: Multiple audio tracks with different codecs and languages

Post by kim »

try replacing the top part with:

Code: Select all

{
	import net.filebot.Language;	
	def preferredLang = Language.findLanguage(info.OriginalLanguage).ISO3.upperInitial()
but because of e.g.
iso_639_1=nl iso_639_3=nld iso_639_2B=dut tag=nl-NL names=[Dutch]

Code: Select all

{
	import net.filebot.Language;	
	def preferredLang = Language.findLanguage(info.OriginalLanguage).iso_639_2B.upperInitial()
or

Code: Select all

{
	import net.filebot.Language;	
	def preferredLang = Language.findLanguage(info.OriginalLanguage).ISO3B.upperInitial()
haveabreak
Posts: 6
Joined: 05 Jul 2020, 21:35

Re: Multiple audio tracks with different codecs and languages

Post by haveabreak »

kim wrote: 05 Mar 2020, 22:11 Added addToList = to make it more user friendly ( output e.g. [Add to "DTS XBR" codecList] )
Added useChFilter = to make it more user friendly ( true or false, makes it more "scene" like )

Code: Select all

{
	def preferredLang = 'Eng'
	def useChFilter = false
	def filter = { [it.codec, it.ch, it.objects, it.lang] }

	def codecList =
	[
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()
	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
	def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
	}{'NO_AUDIO'}
}
Only use one of these lines:

Code: Select all

	allStreams.join(' & ').space('.')
	preferredStream.space('.')
	defaultStream.space('.')
	bestBitRate.space('.')
	[defaultStream, bestBitRate].unique().join(' & ').space('.')
	[bestBitRate, preferredStream].unique().join(' & ').space('.')
	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
useChFilter = this line:

Code: Select all

def chFilter =	( ( ( (ac == 'AAC'||ac == 'MP3') && ch != '2.0') || ( (ac == 'AC3'||ac == 'EAC3'||ac == 'DTS'||ac == 'TrueHD'||ac == 'MLPFBA') && ch != '5.1' ) ) ? ch : null )
= if AAC/MP3 2.0 OR AC3/EAC3/DTS/TrueHD/MLPFBA 5.1, then don't show the 2.0/5.1 part

allStreams = All Audio Streams
preferredStream = The last (best) match from codecList (order matters, from low to high quality / or what you prefer)
defaultStream = The Audio Stream tagged "default=Yes" or if only one Stream
bestBitRate = The Audio Stream with the highest BitRate (with BitRate_Maximum/FrameRate as backup)
How could I add this to my existing naming convention?

Code: Select all

movieFormat={plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{ac}{channels}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}.join(' ') + ']' + {'-' + group}}.tail}
seriesFormat={plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{ac}{channels}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}.join(' ') + ']' + {'-' + group}}.tail}
animeFormat={plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{ac}{channels}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}.join(' ') + ']' + {'-' + group}}.tail}
Would gladly send some money for help because I'm a total noob. Either here or on Discord jezal#5787
kim
Power User
Posts: 1251
Joined: 15 May 2014, 16:17

Re: Multiple audio tracks with different codecs and languages

Post by kim »

very easy just replace the

Code: Select all

{ac}{channels}
like so:

Code: Select all

{plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{
	def preferredLang = 'Eng'
	def useChFilter = false
	def filter = { [it.codec, it.ch, it.objects, it.lang] }

	def codecList =
	[
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()
	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
	def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}

	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
	}{'NO_AUDIO'}
}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}.join(' ') + ']' + {'-' + group}}.tail}
if you really want is on one line just add a ; after all the "def blocks"e.g.

Code: Select all

{ def preferredLang = 'Eng'; def useChFilter = false; def filter = { [it.codec, it.ch, it.objects, it.lang] };

Code: Select all

{plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{def preferredLang = 'Eng'; def useChFilter = false; def filter = { [it.codec, it.ch, it.objects, it.lang] }; def codecList = ['MP3' : 'MP3','PCM' : 'PCM','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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }; 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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }; 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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]; return audioStreams}; def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort(); def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' '); def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() }); def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() }); def defaultStream = oneStream(audioStreams.findAll{ it.default == true }); def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}; any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}}{'NO_AUDIO'}}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}.join(' ') + ']' + {'-' + group}}.tail}
btw: the normal way is video before audio

Code: Select all

{vc}{ac}
haveabreak
Posts: 6
Joined: 05 Jul 2020, 21:35

Re: Multiple audio tracks with different codecs and languages

Post by haveabreak »

kim wrote: 30 Jul 2020, 17:45 very easy just replace the

Code: Select all

{ac}{channels}
like so:

Code: Select all

{plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{
	def preferredLang = 'Eng'
	def useChFilter = false
	def filter = { [it.codec, it.ch, it.objects, it.lang] }

	def codecList =
	[
	'MP3' : 'MP3',
	'PCM' : 'PCM',
	'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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }
	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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()
	def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' ')
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
	def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}

	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
	}{'NO_AUDIO'}
}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}.join(' ') + ']' + {'-' + group}}.tail}
if you really want is on one line just add a ; after all the "def blocks"e.g.

Code: Select all

{ def preferredLang = 'Eng'; def useChFilter = false; def filter = { [it.codec, it.ch, it.objects, it.lang] };

Code: Select all

{plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{def preferredLang = 'Eng'; def useChFilter = false; def filter = { [it.codec, it.ch, it.objects, it.lang] }; def codecList = ['MP3' : 'MP3','PCM' : 'PCM','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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }; 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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }; 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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]; return audioStreams}; def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort(); def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' '); def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() }); def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() }); def defaultStream = oneStream(audioStreams.findAll{ it.default == true }); def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}; any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}}{'NO_AUDIO'}}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}.join(' ') + ']' + {'-' + group}}.tail}
btw: the normal way is video before audio

Code: Select all

{vc}{ac}
Wow, thank you so much for the help! This helps a lot!
btw: the normal way is video before audio

Code: Select all

{vc}{ac}
Tried to edit it as you said. How does that look and how would you do it?

Code: Select all

{plex.derive{' ' + tags.join(' ')}{' [' + allOf{vs}{vf}{hdr}{vc.replace('AVC','x264').replace('ATEME', 'H.265').replace('Microsoft', 'VC-1').replace('HEVC','x265')}{fn.match(/REMUX/).upper()}{def preferredLang = 'Eng'; def useChFilter = false; def filter = { [it.codec, it.ch, it.objects, it.lang] }; def codecList = ['MP3' : 'MP3','PCM' : 'PCM','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 oneStream = { it.collect{ filter(it) }*.minus(null).unique().flatten().join(' ') }; 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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().toString().sum() }{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }; 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{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]; return audioStreams}; def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort(); def allStreams = audioStreams.collect{ filter(it) }*.minus(null).unique()*.join(' '); def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() }); def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() }); def defaultStream = oneStream(audioStreams.findAll{ it.default == true }); def bestPreferredLang = any{ audioStreams.findAll{ it.lang == preferredLang }.sort{ a, b -> b.bitrate <=> a.bitrate }.collect{ filter(it) }*.minus(null).unique().get(0).join(' ') }{}; any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}}{'NO_AUDIO'}}.join(' ') + ']' + {'-' + group}}.tail}
Thanks again, I really appreciate your help!
kim
Power User
Posts: 1251
Joined: 15 May 2014, 16:17

Re: Multiple audio tracks with different codecs and languages

Post by kim »

looks ok

the only thing is choice one and maybe one more as backup

Code: Select all

{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
RudyBzh
Posts: 23
Joined: 31 Mar 2013, 14:05

Re: Multiple audio tracks with different codecs and languages

Post by RudyBzh »

Hi,
I'm trying to include this complex piece of code but have some movies not matching (NO_AUDIO).
How can I troubleshoot this ?

Here are some exemples with "mediainfo -f" results of audio parts.

Exemple 1

Code: Select all

Audio #1
Count                                    : 294
Count of stream of this kind             : 3
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 0
Stream identifier                        : 1
StreamOrder                              : 1
ID                                       : 2
ID                                       : 2
Unique ID                                : 2
Format                                   : AC-3
Format                                   : AC-3
Format/Info                              : Audio Coding 3
Format/Url                               : https://en.wikipedia.org/wiki/AC3
Commercial name                          : Dolby Digital
Commercial name                          : Dolby Digital
Format settings, Endianness              : Big
Codec ID                                 : A_AC3
Duration                                 : 6054117
Duration                                 : 1 h 40 min
Duration                                 : 1 h 40 min 54 s 117 ms
Duration                                 : 1 h 40 min
Duration                                 : 01:40:54.117
Duration                                 : 01:40:54.117
Bit rate mode                            : CBR
Bit rate mode                            : Constant
Bit rate                                 : 384000
Bit rate                                 : 384 kb/s
Channel(s)                               : 6
Channel(s)                               : 6 channels
Channel positions                        : Front: L C R, Side: L R, LFE
Channel positions                        : 3/2/0.1
Channel layout                           : L R C LFE Ls Rs
Samples per frame                        : 1536
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 290597616
Frame rate                               : 31.250
Frame rate                               : 31.250 FPS (1536 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 78
Delay                                    : 78 ms
Delay                                    : 78 ms
Delay                                    : 78 ms
Delay                                    : 00:00:00.078
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : -5
Delay relative to video                  : -5 ms
Delay relative to video                  : -5 ms
Delay relative to video                  : -5 ms
Delay relative to video                  : -00:00:00.005
Stream size                              : 290597616
Stream size                              : 277 MiB (12%)
Stream size                              : 277 MiB
Stream size                              : 277 MiB
Stream size                              : 277 MiB
Stream size                              : 277.1 MiB
Stream size                              : 277 MiB (12%)
Proportion of this stream                : 0.12196
Title                                    : VFF AC3 5.1
Language                                 : fr
Language                                 : French
Language                                 : French
Language                                 : fr
Language                                 : fra
Language                                 : fr
Service kind                             : CM
Service kind                             : Complete Main
Default                                  : Yes
Default                                  : Yes
Forced                                   : No
Forced                                   : No
bsid                                     : 8
Dialog Normalization                     : -31
Dialog Normalization                     : -31 dB
acmod                                    : 7
lfeon                                    : 1
dialnorm_Average                         : -31
dialnorm_Average                         : -31 dB
dialnorm_Minimum                         : -31
dialnorm_Minimum                         : -31 dB
dialnorm_Maximum                         : -31
dialnorm_Maximum                         : -31 dB
dialnorm_Count                           : 1002
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #2
Count                                    : 294
Count of stream of this kind             : 3
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 1
Stream identifier                        : 2
StreamOrder                              : 2
ID                                       : 3
ID                                       : 3
Unique ID                                : 3
Format                                   : AC-3
Format                                   : AC-3
Format/Info                              : Audio Coding 3
Format/Url                               : https://en.wikipedia.org/wiki/AC3
Commercial name                          : Dolby Digital
Commercial name                          : Dolby Digital
Format settings, Endianness              : Big
Codec ID                                 : A_AC3
Duration                                 : 6054117
Duration                                 : 1 h 40 min
Duration                                 : 1 h 40 min 54 s 117 ms
Duration                                 : 1 h 40 min
Duration                                 : 01:40:54.117
Duration                                 : 01:40:54.117
Bit rate mode                            : CBR
Bit rate mode                            : Constant
Bit rate                                 : 384000
Bit rate                                 : 384 kb/s
Channel(s)                               : 6
Channel(s)                               : 6 channels
Channel positions                        : Front: L C R, Side: L R, LFE
Channel positions                        : 3/2/0.1
Channel layout                           : L R C LFE Ls Rs
Samples per frame                        : 1536
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 290597616
Frame rate                               : 31.250
Frame rate                               : 31.250 FPS (1536 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 78
Delay                                    : 78 ms
Delay                                    : 78 ms
Delay                                    : 78 ms
Delay                                    : 00:00:00.078
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : -5
Delay relative to video                  : -5 ms
Delay relative to video                  : -5 ms
Delay relative to video                  : -5 ms
Delay relative to video                  : -00:00:00.005
Stream size                              : 290597616
Stream size                              : 277 MiB (12%)
Stream size                              : 277 MiB
Stream size                              : 277 MiB
Stream size                              : 277 MiB
Stream size                              : 277.1 MiB
Stream size                              : 277 MiB (12%)
Proportion of this stream                : 0.12196
Title                                    : Anglais AC3 5.1
Language                                 : en
Language                                 : English
Language                                 : English
Language                                 : en
Language                                 : eng
Language                                 : en
Service kind                             : CM
Service kind                             : Complete Main
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
bsid                                     : 8
Dialog Normalization                     : -31
Dialog Normalization                     : -31 dB
acmod                                    : 7
lfeon                                    : 1
dialnorm_Average                         : -31
dialnorm_Average                         : -31 dB
dialnorm_Minimum                         : -31
dialnorm_Minimum                         : -31 dB
dialnorm_Maximum                         : -31
dialnorm_Maximum                         : -31 dB
dialnorm_Count                           : 1002
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #3
Count                                    : 282
Count of stream of this kind             : 3
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 2
Stream identifier                        : 3
StreamOrder                              : 3
ID                                       : 4
ID                                       : 4
Unique ID                                : 4
Format                                   : AAC
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Commercial name                          : AAC
Format_AdditionalFeatures                : LC
Codec ID                                 : A_AAC-2
Duration                                 : 6054117
Duration                                 : 1 h 40 min
Duration                                 : 1 h 40 min 54 s 117 ms
Duration                                 : 1 h 40 min
Duration                                 : 01:40:54.117
Duration                                 : 01:40:54.117
Channel(s)                               : 2
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Channel positions                        : 2/0/0
Channel layout                           : L R
Samples per frame                        : 1024
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 290597616
Frame rate                               : 46.875
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 41
Delay                                    : 41 ms
Delay                                    : 41 ms
Delay                                    : 41 ms
Delay                                    : 00:00:00.041
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : -42
Delay relative to video                  : -42 ms
Delay relative to video                  : -42 ms
Delay relative to video                  : -42 ms
Delay relative to video                  : -00:00:00.042
Title                                    : VFF AAC 2.0
Language                                 : fr
Language                                 : French
Language                                 : French
Language                                 : fr
Language                                 : fra
Language                                 : fr
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration
Exemple 2

Code: Select all

Audio #1
Count                                    : 282
Count of stream of this kind             : 2
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 0
Stream identifier                        : 1
StreamOrder                              : 1
ID                                       : 2
ID                                       : 2
Unique ID                                : 17475167537096227729
Format                                   : AAC
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Commercial name                          : AAC
Format_AdditionalFeatures                : LC
Codec ID                                 : A_AAC-2
Duration                                 : 5115584
Duration                                 : 1 h 25 min
Duration                                 : 1 h 25 min 15 s 584 ms
Duration                                 : 1 h 25 min
Duration                                 : 01:25:15.584
Duration                                 : 01:25:15.584
Channel(s)                               : 2
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Channel positions                        : 2/0/0
Channel layout                           : L R
Samples per frame                        : 1024
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 245548032
Frame rate                               : 46.875
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 0
Delay                                    : 00:00:00.000
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : -83
Delay relative to video                  : -83 ms
Delay relative to video                  : -83 ms
Delay relative to video                  : -83 ms
Delay relative to video                  : -00:00:00.083
Title                                    : VFF AAC 2.0
Language                                 : fr
Language                                 : French
Language                                 : French
Language                                 : fr
Language                                 : fra
Language                                 : fr
Default                                  : Yes
Default                                  : Yes
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #2
Count                                    : 294
Count of stream of this kind             : 2
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 1
Stream identifier                        : 2
StreamOrder                              : 2
ID                                       : 3
ID                                       : 3
Unique ID                                : 3
Format                                   : AC-3
Format                                   : AC-3
Format/Info                              : Audio Coding 3
Format/Url                               : https://en.wikipedia.org/wiki/AC3
Commercial name                          : Dolby Digital
Commercial name                          : Dolby Digital
Format settings, Endianness              : Big
Codec ID                                 : A_AC3
Duration                                 : 5115584
Duration                                 : 1 h 25 min
Duration                                 : 1 h 25 min 15 s 584 ms
Duration                                 : 1 h 25 min
Duration                                 : 01:25:15.584
Duration                                 : 01:25:15.584
Bit rate mode                            : CBR
Bit rate mode                            : Constant
Bit rate                                 : 384000
Bit rate                                 : 384 kb/s
Channel(s)                               : 6
Channel(s)                               : 6 channels
Channel positions                        : Front: L C R, Side: L R, LFE
Channel positions                        : 3/2/0.1
Channel layout                           : L R C LFE Ls Rs
Samples per frame                        : 1536
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 245548032
Frame rate                               : 31.250
Frame rate                               : 31.250 FPS (1536 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 78
Delay                                    : 78 ms
Delay                                    : 78 ms
Delay                                    : 78 ms
Delay                                    : 00:00:00.078
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : -5
Delay relative to video                  : -5 ms
Delay relative to video                  : -5 ms
Delay relative to video                  : -5 ms
Delay relative to video                  : -00:00:00.005
Stream size                              : 245548032
Stream size                              : 234 MiB (14%)
Stream size                              : 234 MiB
Stream size                              : 234 MiB
Stream size                              : 234 MiB
Stream size                              : 234.2 MiB
Stream size                              : 234 MiB (14%)
Proportion of this stream                : 0.13658
Title                                    : Anglais AC3 5.1
Language                                 : en
Language                                 : English
Language                                 : English
Language                                 : en
Language                                 : eng
Language                                 : en
Service kind                             : CM
Service kind                             : Complete Main
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
bsid                                     : 8
Dialog Normalization                     : -31
Dialog Normalization                     : -31 dB
acmod                                    : 7
lfeon                                    : 1
dialnorm_Average                         : -31
dialnorm_Average                         : -31 dB
dialnorm_Minimum                         : -31
dialnorm_Minimum                         : -31 dB
dialnorm_Maximum                         : -31
dialnorm_Maximum                         : -31 dB
dialnorm_Count                           : 1504
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration
Example 3 :

Code: Select all

Audio #1
Count                                    : 282
Count of stream of this kind             : 6
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 0
Stream identifier                        : 1
StreamOrder                              : 1
ID                                       : 2
ID                                       : 2
Unique ID                                : 1810417575
Format                                   : DTS
Format                                   : DTS
Format/Info                              : Digital Theater Systems
Format/Url                               : https://en.wikipedia.org/wiki/DTS_(sound_system)
Commercial name                          : DTS
Mode                                     : 16
Format settings, Endianness              : Big
Codec ID                                 : A_DTS
Duration                                 : 7501909
Duration                                 : 2 h 5 min
Duration                                 : 2 h 5 min 1 s 909 ms
Duration                                 : 2 h 5 min
Duration                                 : 02:05:01.909
Duration                                 : 02:05:01.909
Bit rate mode                            : CBR
Bit rate mode                            : Constant
Bit rate                                 : 754500
Bit rate                                 : 754 kb/s
Channel(s)                               : 6
Channel(s)                               : 6 channels
Channel positions                        : Front: L C R, Side: L R, LFE
Channel positions                        : 3/2/0.1
Channel layout                           : C L R Ls Rs LFE
Samples per frame                        : 512
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 360091632
Frame rate                               : 93.750
Frame rate                               : 93.750 FPS (512 SPF)
Bit depth                                : 24
Bit depth                                : 24 bits
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 0
Delay                                    : 00:00:00.000
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : 0
Delay relative to video                  : 00:00:00.000
Stream size                              : 707523792
Stream size                              : 675 MiB (9%)
Stream size                              : 675 MiB
Stream size                              : 675 MiB
Stream size                              : 675 MiB
Stream size                              : 674.7 MiB
Stream size                              : 675 MiB (9%)
Proportion of this stream                : 0.09197
Language                                 : en
Language                                 : English
Language                                 : English
Language                                 : en
Language                                 : eng
Language                                 : en
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #2
Count                                    : 282
Count of stream of this kind             : 6
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 1
Stream identifier                        : 2
StreamOrder                              : 2
ID                                       : 3
ID                                       : 3
Unique ID                                : 4936
Format                                   : AAC
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Commercial name                          : AAC
Format_AdditionalFeatures                : LC
Codec ID                                 : A_AAC-2
Duration                                 : 7501909
Duration                                 : 2 h 5 min
Duration                                 : 2 h 5 min 1 s 909 ms
Duration                                 : 2 h 5 min
Duration                                 : 02:05:01.909
Duration                                 : 02:05:01.909
Channel(s)                               : 2
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Channel positions                        : 2/0/0
Channel layout                           : L R
Samples per frame                        : 1024
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 360091632
Frame rate                               : 46.875
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 0
Delay                                    : 00:00:00.000
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : 0
Delay relative to video                  : 00:00:00.000
Language                                 : fr
Language                                 : French
Language                                 : French
Language                                 : fr
Language                                 : fra
Language                                 : fr
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #3
Count                                    : 282
Count of stream of this kind             : 6
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 2
Stream identifier                        : 3
StreamOrder                              : 3
ID                                       : 4
ID                                       : 4
Unique ID                                : 15050
Format                                   : AAC
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Commercial name                          : AAC
Format_AdditionalFeatures                : LC
Codec ID                                 : A_AAC-2
Duration                                 : 7501909
Duration                                 : 2 h 5 min
Duration                                 : 2 h 5 min 1 s 909 ms
Duration                                 : 2 h 5 min
Duration                                 : 02:05:01.909
Duration                                 : 02:05:01.909
Channel(s)                               : 2
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Channel positions                        : 2/0/0
Channel layout                           : L R
Samples per frame                        : 1024
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 360091632
Frame rate                               : 46.875
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 0
Delay                                    : 00:00:00.000
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : 0
Delay relative to video                  : 00:00:00.000
Language                                 : pt
Language                                 : Portuguese
Language                                 : Portuguese
Language                                 : pt
Language                                 : por
Language                                 : pt
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #4
Count                                    : 282
Count of stream of this kind             : 6
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 3
Stream identifier                        : 4
StreamOrder                              : 4
ID                                       : 5
ID                                       : 5
Unique ID                                : 25636
Format                                   : AAC
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Commercial name                          : AAC
Format_AdditionalFeatures                : LC
Codec ID                                 : A_AAC-2
Duration                                 : 7501909
Duration                                 : 2 h 5 min
Duration                                 : 2 h 5 min 1 s 909 ms
Duration                                 : 2 h 5 min
Duration                                 : 02:05:01.909
Duration                                 : 02:05:01.909
Channel(s)                               : 2
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Channel positions                        : 2/0/0
Channel layout                           : L R
Samples per frame                        : 1024
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 360091632
Frame rate                               : 46.875
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 0
Delay                                    : 00:00:00.000
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : 0
Delay relative to video                  : 00:00:00.000
Language                                 : ru
Language                                 : Russian
Language                                 : Russian
Language                                 : ru
Language                                 : rus
Language                                 : ru
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #5
Count                                    : 282
Count of stream of this kind             : 6
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 4
Stream identifier                        : 5
StreamOrder                              : 5
ID                                       : 6
ID                                       : 6
Unique ID                                : 384
Format                                   : AAC
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Commercial name                          : AAC
Format_AdditionalFeatures                : LC
Codec ID                                 : A_AAC-2
Duration                                 : 7501909
Duration                                 : 2 h 5 min
Duration                                 : 2 h 5 min 1 s 909 ms
Duration                                 : 2 h 5 min
Duration                                 : 02:05:01.909
Duration                                 : 02:05:01.909
Channel(s)                               : 2
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Channel positions                        : 2/0/0
Channel layout                           : L R
Samples per frame                        : 1024
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 360091632
Frame rate                               : 46.875
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 0
Delay                                    : 00:00:00.000
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : 0
Delay relative to video                  : 00:00:00.000
Language                                 : es
Language                                 : Spanish
Language                                 : Spanish
Language                                 : es
Language                                 : spa
Language                                 : es
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration

Audio #6
Count                                    : 282
Count of stream of this kind             : 6
Kind of stream                           : Audio
Kind of stream                           : Audio
Stream identifier                        : 5
Stream identifier                        : 6
StreamOrder                              : 6
ID                                       : 7
ID                                       : 7
Unique ID                                : 9511
Format                                   : AAC
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Commercial name                          : AAC
Format_AdditionalFeatures                : LC
Codec ID                                 : A_AAC-2
Duration                                 : 7501909
Duration                                 : 2 h 5 min
Duration                                 : 2 h 5 min 1 s 909 ms
Duration                                 : 2 h 5 min
Duration                                 : 02:05:01.909
Duration                                 : 02:05:01.909
Channel(s)                               : 2
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Channel positions                        : 2/0/0
Channel layout                           : L R
Samples per frame                        : 1024
Sampling rate                            : 48000
Sampling rate                            : 48.0 kHz
Samples count                            : 360091632
Frame rate                               : 46.875
Frame rate                               : 46.875 FPS (1024 SPF)
Compression mode                         : Lossy
Compression mode                         : Lossy
Delay                                    : 0
Delay                                    : 00:00:00.000
Delay, origin                            : Container
Delay, origin                            : Container
Delay relative to video                  : 0
Delay relative to video                  : 00:00:00.000
Language                                 : uk
Language                                 : Ukrainian
Language                                 : Ukrainian
Language                                 : uk
Language                                 : ukr
Language                                 : uk
Default                                  : No
Default                                  : No
Forced                                   : No
Forced                                   : No
SamplingCount_Source                     : General_Duration
Duration_Source                          : General_Duration
Also, this part never throws "null" if there is no "NumberOfDynamicObjets"

Code: Select all

'objects' : any{ '[' + au['NumberOfDynamicObjects'] + ' Objs]' }{null}
So I have a lot of movies with "[null.Objs]"


I don't understand the "AddToList" option ? What is it made for and how to use it.


Lastly, idealy, I would like to rename my file with this result :
Best French language available & Best quality if different ; So 2 results max but could be 1 if all the same (unique). Something like :
[AC3 5.1 Fra] // with hidden [AAC 2.0 Fra & AC3 5.1 Eng] (not better qualities)
[AC3 5.1 Fra & DTS-ES 7.0 Eng] ; Because Eng version is better

I tried this without success : [bestPreferredLang, bestBitRate].unique().join(' & ')
It shows more than 2 results for a lot of movies.

Thanks
kim
Power User
Posts: 1251
Joined: 15 May 2014, 16:17

Re: Multiple audio tracks with different codecs and languages

Post by kim »

Version 5

Code: Select all

{
	def preferredLang = 'Fra'
	def useChFilter = false
	def filter = { [it.codec, it.ch, it.objects, it.lang].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{Punct}/, ' ') }
	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{ channelClean(au.ChannelPositionsString2).tokenize('\\/')*.toDouble().sum() }
			{ channelClean(au.ChannelLayout_Original).split().collect{ it == 'LFE' ? 0.1 : 1 }.sum() }
			{ channelClean(dString(au.ChannelsOriginal)) } { channelClean(dString(au.Channels)) }

		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) }{ au.FrameRate.toDouble() }{null},
		'objects' : any{def objects = au['NumberOfDynamicObjects']; objects ? "[$objects Objs]" : ''}{null}, 'lang' : any{ au.'LanguageString3'.upperInitial() }{null} ]
		return audioStreams
	}

	def addToList = audioStreams.codec.findAll{ it.contains('Add to') }.unique().sort()
	def allStreams = listStream(audioStreams)
	def preferredStream = oneStream(audioStreams.findAll{ it.index == audioStreams.index.max() })
	def bestBitRate = oneStream(audioStreams.findAll{ it.bitrate == audioStreams.bitrate.max() })
	def defaultStream = any{ oneStream(audioStreams.findAll{ it.default == true }) }{ oneStream(audioStreams.findAll{ !it.default }) }
	def bestPreferredLang = any{ oneStream(audioStreams.findAll{ it.lang == preferredLang }) }{}

	any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
	}{'NO_AUDIO'}
}

e.g. replace

Code: Select all

{bestPreferredLang}
with

Code: Select all

{[bestPreferredLang, bestBitRate].findAll().unique().join(' & ')}
sample "AC3 5.1 Fra & DTS-HD MA 7.1 Eng"
RudyBzh
Posts: 23
Joined: 31 Mar 2013, 14:05

Re: Multiple audio tracks with different codecs and languages

Post by RudyBzh »

Thanks a lot kim. Seems to perfectly makes the job.
I tried to change the last line :

Code: Select all

any{addToList}{bestPreferredLang}{defaultStream}{bestBitRate}{preferredStream}
with this :

Code: Select all

{[bestPreferredLang, bestBitRate].findAll().unique().join(' & ')}
But it's not working (I only get 1 result even if there should be 2 independent results for some movies...).
But doing like this, as you told, is working :

Code: Select all

any{addToList}{[bestPreferredLang, bestBitRate].findAll().unique().join(' & ')}{defaultStream}{bestBitRate}{preferredStream}
I'm just confused & really don't understand why ?!

If I take attributes "one by one", like only "{bestBitRate}", I can't get it to work (it gives me a result but not the "best bitrate").
I'm surely missing something like dealing with lists & findAll...
Also, if I remove the last line, as if I don't want to get anything, except "NO_AUDIO", I still get a result... I don't know from where : The "return audiostream" ?! The "any{audio.collect..." ?!

Well, the good thing is that it seems to be working. The bad thing is that I don't understand... but the problem is... me ;)
Post Reply