Script Help with Adding Bitrate to Folder

I’ve been trying to come up with a way to have Picard add the bitrate to the folder that contains the album. On VBR, this is challenging because on 15 different tracks, you’ll have 15 different bitrates. What I’m trying to do instead, is first check for a constant bitrate and set a new variable with that number, and then check to see if the bitrate falls within a range. I think the issue may be the nested ifs, or bitrate may simply not be responding to functions as I would expect.

    $if2(%albumartistsort%,%artistsort%)/
    $if($ne(%albumartistsort%,),
    %artist% - 
    %date% - 
    %album% {%label% %catalognumber%}  
    [
    $upper(%_extension%) 
    $if($eq(%_bitrate%,320.0),$set(_folderbr,320))
    $if($eq(%_bitrate%,256.0),$set(_folderbr,256))
    $if($eq(%_bitrate%,192.0),$set(_folderbr,192))
    $if($eq(%_bitrate%,160.0),$set(_folderbr,160))
    $if($eq(%_bitrate%,128.0),$set(_folderbr,128))
    $if(
        $gt(%_bitrate%,220.000),$if(
            $lt(%_bitrate%,310.000),$if(
                $gt(%_folderbr%,0),$set(_folderbr,V0)
    )))
    $if(
        $gt(%_bitrate%,170.000),$if(
            $lt(%_bitrate%,210.000),$if(
                $gt(%_folderbr%,0),$set(_folderbr,V2)
    )))
    %_folderbr%
    ]/)$if($gt(%totaldiscs%,1),%discnumber%,)$if($ne(%albumartist%,),$num(%tracknumber%,2). ,)$if(%_multiartist%,%artist% - ,)%title%

In reality all it does is use the last instance that %_folderbr% checked. So right now it would rename everything as V2, and if I moved the V0 code block below it, it would rename everything to V0.

Any thoughts?

Cleaned this up some and simplified for debugging. Relevant snippet:

[
$upper(%_extension%)
$if($eq(%_bitrate%,320.0),$set(_folderbr,320),
$if($eq(%_bitrate%,256.0),$set(_folderbr,256),
$if($eq(%_bitrate%,192.0),$set(_folderbr,192),
$if($eq(%_bitrate%,160.0),$set(_folderbr,160),
$if($eq(%_bitrate%,128.0),$set(_folderbr,128))))))

$if($gt(%_folderbr%,0),$noop(),
$if($gt(%_bitrate%,220),$set(_folderbr,V0),
$if($lt(%_bitrate%,219),$set(_folderbr,V2),
$set(_folderbr,Err)
)))
$if($eq($upper(%_extension%),MP3), %_folderbr%)
]

Any CBR album works fine, any VBR album gets renamed to [MP3 Err]. So I believe what’s going on is %_bitrate% is a string, and $eq works because the strings match, but $gt, for instance, will not because it’s doing a math comparison on a string type.

The problem here is that $if does not work here as you probably expect. $if itself is a function call, and it gets called with the result of $set. It is not a control structure of the language. So $result gets executed even before $if gets called.

The solution is quite simple, use $if inside the $set:

$set(_folderbr,$if($eq(%_bitrate%,160.0),160,))

Please excuse the short answer and lack of code formatting, answering from my mobile.

Edit: For anybody reading this, please ignore the above. Actually $if is handled as one would expect and any code inside of it is only executed if the condition matches.

So in the following example the first call to $set is only run if the condition $startswith(%artist%,The) is true, the second $set will be ignored then. If the condition is false only the second $set will run.

$if($startswith(%artist%,The),$set(comment,True),$set(comment,False))
1 Like

I actually just figured it out. For whatever reason, %_bitrate% will not work with $gt(), probably because it’s declared as a float and float comparisons are always funky. But, if you cast it as an int, by way of taking the first 3 characters, $gt() works again.

[
$set(_numbr,$left(%_bitrate%,3))
$upper(%_extension%)
$if($eq(%_bitrate%,320.0),$set(_folderbr,320),
$if($eq(%_bitrate%,256.0),$set(_folderbr,256),
$if($eq(%_bitrate%,192.0),$set(_folderbr,192),
$if($eq(%_bitrate%,160.0),$set(_folderbr,160),
$if($eq(%_bitrate%,128.0),$set(_folderbr,128))))))

$if($gt(%_folderbr%,0),$noop(),
$if($gt(%_numbr%,220),$set(_folderbr,V0),
$if($lt(%_numbr%,219),$set(_folderbr,V2),
$set(_folderbr,Err)
)))
$if($eq($upper(%_extension%),MP3), %_folderbr%)
]

This will obviously break on stuff <100 kbps. Not applicable to me, and easily fixed with some $replace().

I was just compelled to point out the logical fallacy here:
$gt(%_numbr%,220) checks for anything greater than 220, so 220 is not included.
$lt(%_numbr%,219) checks for anything less than 219, so 219 is not included.

This means than anything where %_numbr% equates to 219–220 (both numbers included) will not get matched by this. You probably want something more like:

$if($gte(%_numbr%,220),$set(_folderbr,V0),
$if($lt(%_numbr%,220),$set(_folderbr,V2),

This will $set(_folderbr,V0) for anything where %_numbr% is 220 or greather than and $set(_folderbr,V2) when it’s less. Thus, all (numeric) values are included in the comparison and you won’t suddenly end up with weird edge cases. :wink:

You should be able to just use $if(%_folderbr%,,…). Unless there’s more to your script than what you’ve shown, %_folderbr% will not contain a value at if it didn’t get set in the previous block, so numeric comparison makes less sense (IMHO) than just checking whether it exists at all. (Also, $noop() literally does nothing, so it should be possible to remove it—but on the other hand, keeping it might be nice for readability.)

You can use $set(_numbr,$div(%_bitrate%,1000)) (ie., divide the bitrate by 1000) to circumvent this instead of removing the 3 right most characters. :slight_smile:

2 Likes

Thanks for the clarification. Some of the code was left overly simple just to work through the immediate issue, and I’ll be working on cleaning it up. However, one of your suggestions does not work.

$if($gte(%_numbr%,220),$set(_folderbr,V0),
$if($lt(%_numbr%,220),$set(_folderbr,V2),

Fine.

$if(%_folderbr%,,

Fine as well, thank you. Couldn’t figure out the expected syntax for just checking whether a variable was empty.

$set(_numbr,$div(%_bitrate%,1000))

This won’t work in the current build. Here’s the complete script, if you’d like to review that.

$if2(%albumartistsort%,%artistsort%)/
$if($ne(%albumartistsort%,),
%artist% - 
%date% - 
%album% {%label% %catalognumber%}  
[
$noop($set(_numbr,$left(%_bitrate%,3)))
$set(_numbr,$div(%_bitrate%,1000))
$upper(%_extension%)
$if($eq(%_bitrate%,320.0),$set(_folderbr,320),
$if($eq(%_bitrate%,256.0),$set(_folderbr,256),
$if($eq(%_bitrate%,192.0),$set(_folderbr,192),
$if($eq(%_bitrate%,160.0),$set(_folderbr,160),
$if($eq(%_bitrate%,128.0),$set(_folderbr,128))))))

$if(%_folderbr%,,
$if($gte(%_numbr%,220),$set(_folderbr,V0),
$if($lt(%_numbr%,220),$set(_folderbr,V2),
$set(_folderbr,Err)
)))
$if($eq($upper(%_extension%),MP3), %_folderbr%)
]/)$if($gt(%totaldiscs%,1),%discnumber%,)$if($ne(%albumartist%,),$num(%tracknumber%,2). ,)$if(%_multiartist%,%artist% - ,)%title%

If you try it as is, a VBR MP3 will get tagged as [MP3 Err]. If you noop the line with $div and un-noop the line with $left it’ll work.

4 Likes

Greetings! Let me make one remark. It seems to me that in the “set ()” block it is better to use “if2 ()” and “unset ()”. In this way, “if ()” attachments can be avoided, and the code will take a more understandable look, without many brackets at the end, this will help to avoid confusion in some cases. EX:

$set(_folderbr,$if2(
$if($eq(%_bitrate%,320.0),320,$unset(_folderbr)),
$if($eq(%_bitrate%,256.0),256,$unset(_folderbr)),
$if($eq(%_bitrate%,192.0),192,$unset(_folderbr)),
$if($eq(%_bitrate%,160.0),160,$unset(_folderbr)),
$if($eq(%_bitrate%,128.0),128,$unset(_folderbr))
))

Hope this helps someone. Have a nice day!

1 Like

I’ve made a plugin that should help if you have an album with different mp3 files with different bitrates. It adds %_albumBitrate% variable that aggregates bitrates from all album files and looks like “V2+V0+320” in such cases. Feel free to use and modify it how you like - https://github.com/yuzvir/picard-scripting/blob/master/album_bitrates.py

3 Likes

After a bunch of playing around I got this to work for my ideal structure, and it saves me the hassle of all the split folders created when VBR fluctuates between v2 and v0. In short, THANK YOU!!

2 Likes

FWIW, I’ve got similar functionality in my massive script from heck and back, too. (Excerpt below, from script that is in the Script Repository thread, last posted 6-May 2020)

$noop(########### Audio Metrics Setup  ###########################)
$noop(########### DevMode Values Only ############################)

$set(_devMode,0) $noop(Use Standin Data.)

$set(_biitrate,71.426)
$set(_saample_rate,44100)
$set(_biits_per_sample,16)
$set(_chaannels,2)
$set(_tiitle,My Great Score)
$noop(########### CONFIRM DevMode is Disabled for Live Use ########)

$noop(############## Determine Bit Rate Integer Value #############)

$if($eq(%_devMode%,1),FileBit %_biitrate% ---)

$if($eq(%_devMode%,1),$set(_intBitRate,$rreplace(%_biitrate%,\\.\\d*\$,)),$set(_intBitRate,$rreplace(%_bitrate%,\\.\\d*\$,)))

$if($eq(%_devMode%,1),IntBit %_intBitRate% ---)

$if($eq(%_devMode%,1),$set(_bitRateSpeed,%_saample_rate%KHz),$set(_bitRateSpeed,%_sample_rate%KHz))
$if($eq(%_devMode%,1),$set(_bitsPerSample,[%_biits_per_sample%]bit),$set(_bitsPerSample,[%_bits_per_sample%]bit))
$if($eq(%_devMode%,1),$set(_audioChannels,%_chaannels%ch),$set(_audioChannels,%_channels%ch))
$if($eq(%_devMode%,1),$set(_titleForFilename,%_tiitle%),$set(_titleForFilename,%title%))

$set(_bitRateType,$if($eq_any(%_intBitRate%,320,256,224,192,160,128,112,96,80,64,48,40,32,24,16,8),CBR$set(_cbrRateValue,%_intBitRate%)$set(_fileCBRRate,%_intBitRate%),VBR$set(_vbrRateValue,%_intBitRate%)))

$noop(Bitrate factors of 8.0 are most likely CBR with the remainder being VBR)

$if($eq(%_bitRateType%,VBR),
$if($gt(%_vbrRateValue%,339),$set(_fileVBRRate,320+),
$if($gt(%_vbrRateValue%,319),$set(_fileVBRRate,320),
$if($gt(%_vbrRateValue%,260),$set(_fileVBRRate,V0+),
$if($gt(%_vbrRateValue%,220),$set(_fileVBRRate,V0),
$if($gt(%_vbrRateValue%,191),$set(_fileVBRRate,V1),
$if($gt(%_vbrRateValue%,170),$set(_fileVBRRate,V2),
$if($gt(%_vbrRateValue%,150),$set(_fileVBRRate,V3),
$if($gt(%_vbrRateValue%,140),$set(_fileVBRRate,V4),
$if($gt(%_vbrRateValue%,130),$set(_fileVBRRate,V5),
$if($gt(%_vbrRateValue%,120),$set(_fileVBRRate,V6),
$if($gt(%_vbrRateValue%,95),$set(_fileVBRRate,V7),
$if($gt(%_vbrRateValue%,69),$set(_fileVBRRate,V8),
$if($gt(%_vbrRateValue%,44),$set(_fileVBRRate,V9),
$set(_fileVBRRate,%_intBitRate%)
))))))))))))))

$noop(######### File Naming Structure Variables Complete #########)

I cant seem to make it work??
I installed the plugin https://github.com/yuzvir/picard-scripting/blob/master/album_bitrates.py

then created a new custom script with your code but it doesn’t do anything when i try to run script?

any idea what i’m doing wrong?

I can’t get it work, too.
I installed the plugin https://github.com/yuzvir/picard-scripting/blob/master/album_bitrates.py, but nothing happens.

What to do next? I’d like to get the new variable %_folderbr% to each file for using it later in mp3tag.