Determining whether condition applies to multiple files

Hello, I’m trying to figure out whether it is possible to do the following with scripting:

  1. Determine whether a release consists of the same media type or not. For example, whether all of its discs are CDs, or if one is something else, such as a live DVD, bonus 7" or something. I would like to file them into a directory tagged, for example, “Album 2CD”, and if mixed “Album something else”.

  2. Whether all the files in a digital release are of the same bitrate and samplerate. I have releases where an album might contain a few bonus tracks at a better quality. I’d like to file albums with a consistent bitrate away like “album 16-44.1” with mixed releases filed away like “album mixed”. I wouldn’t want a single release to be sorted into multiple directories based on differing qualities.

Thanks!

Just a bump to see if anyone knows.

Is comparison between files in a complete release possible?

What I want to do: if a release’s files are all of the same bit depth + samplerate, i.e all files match 24bit/96kHz, include this detail its directory name.

I totally had missed your initial thread :frowning:

But for the question: Out of the box Picard does not offer a way to check all files for specific data. A plugin could do this, maybe by providing a scripting function to get the common value for a tag.

Overall having a way to get a common value for a tag for all files of a release sounds very useful. Actually I could imagine to have scripting functions to aggregate the values of a tag across files on a single release in various ways:

  • get a value if it is the same across all files
  • get the value that most files have
  • get an average (for numerical tags)
  • get a list of all values

Would also be useful for e.g. genre. Currently I don’t 5hink such a plugin exists.

3 Likes

I started something that might enable this sort of functionality at:

https://github.com/rdswift/picard-plugins/tree/2.0_RDS_Plugins/plugins/album_level_tags

I haven’t done much testing on it yet, and it definitely doesn’t aggregate the values for you, but it’s there if someone wants to use it as a starting point to develop something with a bit more functionality.

3 Likes

I gave this a go with a slightly different approach:

https://raw.githubusercontent.com/phw/picard-plugins/releasetag_aggregations/plugins/releasetag_aggregations/releasetag_aggregations.py

Note: The functions names starting with $album_ were previously called $releasetag_. I changed this with an update to version 0.4 and have updated this post accordingly.

This plugin provides a couple of functions that can be used to get aggregated values from all files on the release. Note: Due to technical limitations these functions work only when used in a naming script.

E.g. one can use the following to get a common media (note: variable names must be passed by name, e.g. media, not with value, e.g. %media%):

$album_all(media)

If all files have the same value for media (e.g. “CD”) that value will be returned, otherwise it will be empty. You can use this to just check whether all files have the same type or not:

$if($album_all(media),all same media type,different media type)

For handling numeric values e.g. for including the bitrate in a folder name there are $album_min(), $album_max() and $album_avg(). E.g. you could do a bitrate range:

$album_min(_bitrate)-$album_max(_bitrate)

Or to have it use only a single value if all files are identical combine it with $album_all:

$if2($album_all(_bitrate),$album_min(_bitrate)-$album_max(_bitrate))

Another option is to use an average bitrate:

$album_avg(_bitrate)

For something like genres you might want to use the most common value. There is $album_mode() for this:

$album_mode(genre)

If you have 4 files tagged with a genre of “rock” and 3 with genre “metal” this will use “rock”. Now often there are multiple genres in a file (that means a genre tag is a multi-value tag). Let’s assume we have a release with individual tags tagged with the following genres:

  1. rock; metal
  2. rock; blues
  3. blues
  4. rock; metal
  5. blues; alternative
  6. blues; jazz

Using $album_mode(genre) would pick “rock; metal” as the genre, because this is the most common combination. But maybe you want the most common single value? There is $album_multi_mode() for this:

$album_multi_mode(genre)

This looks at all the values individually and hence will give “blues” (which is used 4 times, followed by rock 3 times).

There are also multi tag variations of min, max and average ($album_multi_min(), $album_multi_max(), $album_multi_avg()).

To install the script the easiest is to download the file releasetag_aggregations.py from https://raw.githubusercontent.com/phw/picard-plugins/releasetag_aggregations/plugins/releasetag_aggregations/releasetag_aggregations.py and install it from inside Picard via Options > Plugins > Install plugin…

3 Likes

Excellent, I always wanted to write such a plugin myself, but did not find the time do it.
Thank you very much!

I guess it would require major code changes in Picard itself to make this also work for tagging scripts?
One specific use case for this I have in mind is replacing the album artist for classical and audiobook releases using the most common writer or performer credits which are only available at the recording level (in most cases).

It would require code changes, but actually I don’t think it would be much. The script parser supports providing a file when evaluating a script. Originally a file only ever was available when saving / renaming. But as Picard supports using the file tags since Picard 2.5 we could also provide this to the parser. In addition I think it would kind of make sense to provide more context in general, e.g. we could always provide access to the album, track or cluster, independent of whether a file is available or not. This can be a bit tricky for developers of scripting functions to consider all cases, but would provide great flexibility. E.g. in the functions here I already handle both the case that a file is matched to a proper release on the right or only added to a cluster on the left.

3 Likes

Thanks for this. I don’t seem to be able to get it working right now, though.

I’ve installed the plugin, and it’s activated, but I see an error telling me that $releasetag_all is an unknown function. I’ll give it a closer look this weekend. I think my filenaming script could do with an overhaul.

Ideally what I’d like to end up with, with a little psuedocode:

if _bits_per_sample >= 24:
  write "24-bit" to dir name
  if all tracks have the same _sample_rate:
    write eg. "44.1kHz" to dir name
  else:
    write "mixed" to dir name
else:
  forget about it

Thanks again for looking into this. The mix, max stuff looks very handy.

Sorry for the confusion. After some discussion on the review of my plugin I changed the naming to $album_*, e.g. $album_all(_bits_per_sample ). I’ll update my post above accordingly to avoid future confusion.

For your use case something like this should do:

$if($album_all(_bits_per_sample ),
$album_all(_bits_per_sample)-$if($album_all(_sample_rate),$album_all(_sample_rate) Hz,mixed)
)

If you want to use kHz maybe instead of $album_all(_sample_rate) Hz use $div($album_all(_sample_rate),1000) kHz. Not sure right now how this ends up with rounding, but just try it.

UPDATE: Thinking about it the double calls to $album_all can be avoided. If this worked once we know for sure the value of the current file matches, so we could do:

$if($album_all(_bits_per_sample ),
%_bits_per_sample%-$if($album_all(_sample_rate),$div(%_sample_rate%,1000) kHz,mixed)
)
1 Like

Ah, thanks!

Perhaps this is inefficient or something, but it does the trick

$if($gte(%_bits_per_sample%,24),%_bits_per_sample%-bit $if($album_all(_sample_rate),$div(%_sample_rate%,1000)$if($ne($mod(%_sample_rate%,1000),0),.$left($mod(%_sample_rate%,1000),1))kHz,$div($album_max(_sample_rate),1000)$if($ne($mod($album_max(_sample_rate),1000),0),.$left($mod($album_max(_sample_rate),1000),1))kHz),)

My main issue was Picard splitting files between two directories, should some property differ. The above mess should dump the files into a directory with the album’s max samlplerate.

1 Like

I guess we should have some number formatting function :smiley: Or at least extend $num for a precision parameter to specify the number of digits after the comma.

2 Likes