Fine-tuning bestBitRate output for audio codec

Running FileBot from the console, Groovy scripting, shell scripts, etc
Post Reply
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Fine-tuning bestBitRate output for audio codec

Post by nartana »

I've been very happy with the 'display best audio stream codec info' script Kim helped me create.

I'd like to discover how to fine-tune the best-audio-codec output re. periods (see Output example, below snippet).

Code: Select all

Movies/{vf}/{any{"$collection/($y) ${n.replace(':',' -')}"}{"${n.replace(':',' -')} ($y)"}}{'/' + {n.replace(':',' -')} + ' (' + y + ') '}{'(' + fn.matchAll(/Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Final|Extended|Rogue|Special|Diamond|Despecialized|R.Rated|(\\d+th.)?Anniversary).(Cut|Edition|Version)|Extended|Remastered|Recut|Uncut|Uncensored|Unrated|special.edition/)*.upperInitial()*.lowerTrail().sort().join(', ').replaceAll(/[._]/, " ") + ') '}
{tags.matchAll(/extended|uncensored|remastered|unrated|uncut|Theatrical|Theatrical.Cut|Theatrical.edition|3d|directors.cut|special.edition/)*.normalizePunctuation()*.upperInitial()*.lowerTrail().sort().unique().join(' - ')}{ minutes + 'mins [' }{vf =~ /2160p/ ? '4k' : HD}
{ ' [' + vf + ' @' + mbps.space('').lower() + '] '}

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

	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',
	'AC 3 MLP FBA 16 ch' : 'TrueHD Dolby 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',
	'FLAC' : 'FLAC',
	'VORBIS' : 'Ogg Vorbis WHAT',
	'Vorbis' : 'Ogg Vorbis WHAT WHAT'
	]

	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) }{null}, 'frameRate' : any{ au.FrameRate.toDouble() * ch.toDouble() }{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 bestFrameRate = oneStream(audioStreams.findAll{ it.frameRate == audioStreams.frameRate.max() })
	def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
	def bestPreferredGer = any{audioStreams.findAll{it.lang == preferredGer }.sort{it.bitrate}.reverse().collect{ filter(it) }*.minus(null).unique().get(0).join(' ')}{''}
	def bestPreferredEng = any{audioStreams.findAll{it.lang == preferredEng }.sort{it.bitrate}.reverse().collect{ filter(it) }*.minus(null).unique().get(0).join(' ')}{''}

bestBitRate.space('.') }
		{'NO_AUDIO'}
}

{'/' + {n.replace(':',' -')} + ' (' + y + ') '}{ vf }{' ★' + hdr + '★'}{ minutes + 'mins [' }{vf =~ /2160p/ ? '4k' : HD}{ ' [' + vf + ' @' + mbps.space('').lower() + '] '}{' [' + af + ']'}
Folder Name Output:
Olympus Has Fallen (2013) 119mins [4K @71mbps] DTS-HD.MA.5.1

Desired Folder Name Output:
Olympus Has Fallen (2013) 119mins [4K @71mbps] DTS-HD MA 5.1

Attempted Script Changes:
I tried using a space instead of a period, i.e. bestBitRate.space(' '). This removes the period from "5.1" and makes it "5 1" which is undesired.

P.S. I never get edition tags (i.e. 'Final Cut') to show up. Do you see anything wrong with the tags string in my script?

P.P.S. I realize it’s not necessarily good form to have "@" in my filenames, but I like it.

Thank-you for considering these questions.
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Fine-tuning bestBitRate output for audio codec

Post by nartana »

As I was. (Specifically, I was an idiot).

I solved the main question myself, by accident.

I edited this snippet:

Code: Select all

bestBitRate.space('.')
I made it like this:

Code: Select all

bestBitRate
And then it did what I wanted... err, what it's supposed to do.

However!

I still can't get tags to work. For example, no "Directors Cut," or "Extended Edition," et al.

Can you see any issues in the snippets (example, original post) relating to tags?
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Fine-tuning bestBitRate output for audio codec

Post by rednoah »

{tags} doesn't just work? (if not, please paste an example file path)
:idea: Please read the FAQ and How to Request Help.
nartana
Posts: 35
Joined: 02 May 2019, 22:28

Re: Fine-tuning bestBitRate output for audio codec

Post by nartana »

Thanks for the wknd reply rednoah.

Yes, I got {tags} to work yesterday. I had begun trying various {tags} variables you suggested in other threads. Suddenly, success. I've no idea why - obviously, a PICNIC type situation. ha.

And, by using {tags.first() } I got rid of the brackets and replaced them with stars (desired).

Below is the script that works for me, now:

Code: Select all

…Media/Movies/{vf}/{any{"$collection/($y) ${n.replace(':',' -')}"}{"${n.replace(':',' -')} ($y)"}}{'/' + {n.replace(':',' -')} + ' (' + y + ') '}{' ★' + tags.first() + '★ '}{ minutes + 'mins '}{'['}{vf =~ /2160p/ ? '4K' : hd}{' ' + mbps.lower() + '] ' + '[' + bitdepth + 'bit] '}

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

   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',
   'AC 3 MLP FBA 16 ch' : 'TrueHD Dolby 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',
   'FLAC' : 'FLAC',
   'VORBIS' : 'Ogg Vorbis WHAT',
   'Vorbis' : 'Ogg Vorbis WHAT WHAT'
   ]

   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) }{null}, 'frameRate' : any{ au.FrameRate.toDouble() * ch.toDouble() }{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 bestFrameRate = oneStream(audioStreams.findAll{ it.frameRate == audioStreams.frameRate.max() })
   def defaultStream = oneStream(audioStreams.findAll{ it.default == true })
   def bestPreferredGer = any{audioStreams.findAll{it.lang == preferredGer }.sort{it.bitrate}.reverse().collect{ filter(it) }*.minus(null).unique().get(0).join(' ')}{''}
   def bestPreferredEng = any{audioStreams.findAll{it.lang == preferredEng }.sort{it.bitrate}.reverse().collect{ filter(it) }*.minus(null).unique().get(0).join(' ')}{''}

bestBitRate }
       {'NO_AUDIO'}
}

{'/' + {n.replace(':',' -')} + ' (' + y + ') '}{ minutes + 'mins '}{'[' + hd + ' ' + mbps.lower() + '] '}{'[' + hdr + '] '}{af}
Successful output (subdirectory name):
Independence Day (1996) ★Extended★ 153mins [4K 40 mbps] [10bit] DTS-HD MA 7.1

Successful Output (file name):
Independence Day (1996) 153mins [UHD 40 mbps] [HDR10] 8ch.mkv

Any 'clean-up' suggestions always welcome. For my feral scripting.

Sorry for posting questions when I should've dug in more, first.

Thanks for continuing to evolve this software.
Post Reply