Keep folder name and add suffix

Howdy community,

My goal is to add a suffix at the end of my folder name so that if there are FLACs, it should add the extension, bit per sample and sampling rate like so: [FLAC - 16Bit - 44.1kHz]

If there are MP3s, only the extension and bitrate like so: [MP3 - 320]

Most of my folders are already properly named so I want to reuse the name, and just add a suffix. No need to read other tags like artist or album.

From what I understand, I need to create an action group, select the _DIRECTORY field, but then I'm a bit puzzled how to reuse the folder name.

I managed to create a column for the bit per sample: %_bitspersample%Bit
I managed to create a column for the sample rate: $div(%_samplerate%,1000)$ifgreater($mod(%_samplerate%,1000),0,.$left($mod(%_samplerate%,1000),1),)kHz

(Thanks to someone on this forum for that last bit)

But now how do I put this all together? Can I process both FLACs and MP3s using the same action or will I need separate actions?

On rare occasions, there may be both FLAC and MP3 in the same folder (shouldn't happen, but it could happen), how would those cases be handled? Would the last file in a folder be used for renaming the parent folder?

Thanks for the help!

See e.g. this thread:

After some reading/testing I came up with something that works, although I'm sure there will be some kinks to work around (haven't tested with a folder containing both FLAC and MP3 yet).

  1. Create a new action group, I called it 'Folder - Add Format, Bit depth, Sample Rate'
  2. Add a new action 'Format Value'
  3. Select '_DIRECTORY' for the field
  4. Then in Format String:, I have the following:

%_directory% '['$upper(%_extension%) - $if($eql($lower(%_extension%),'flac'),%_bitspersample%Bit - $div(%_samplerate%,1000)$ifgreater($mod(%_samplerate%,1000),0,.$left($mod(%_samplerate%,1000),1),)kHz,%_bitrate%)']'

This will keep the folder name intact and add at the end...

  • For folders containing FLAC, a suffix like [FLAC - 16Bit - 44.1kHz]
  • For folders containing MP3, a suffix like [MP3 - 320]

Hope this helps!

You should be aware that this will name the folder based on the properties of the first song in it. It won't account for mixed folders where for example the first track is 24/48 and the rest is 16/44.1. Or for an album with mp3s of different bitrates.
I tried and was unable to get a proper folder naming that accounts for all files in the folder in the past within mp3tag.
My solution was to write an external python script to be executed as a tool from within mp3tag that scans the audio files in the folder and adds a suffix based on all the songs, however I never got around to polish it or work out the kinks.

[Reply]

Thank you for this information! I had a feeling this wouldn't be a perfect solution and it would either use the first or last file in the folder.

Would you be willing to share that python script? I'd be happy to take a look. Maybe Claude/Sonnet AI can help us figure it out. Would be great to come up with a solution that can handle all scenarios (FLAC, WAV, MP3, mixed extensions or bitrates, etc.)

Best,
B

I don't mind. But as I said, it's rudimentary, not tested and far from complete. I haven't touched it since september last year and I'd do quite a few things differently now.

import os
import subprocess
import math
import sys
import re

def get_bitrates(directory, extension):
    files = [f for f in os.listdir(directory) if f.endswith(extension)]
    bitrates = []
    for file in files:
        file_path = os.path.join(directory, file)
        if extension == 'mp3':
            result = subprocess.run(['exiftool', '-AudioBitrate', '-b', '-m', file_path], stdout=subprocess.PIPE, text=True, check=True)
        elif extension == 'm4a':
            result = subprocess.run(['exiftool', '-AvgBitrate', '-b', '-m', file_path], stdout=subprocess.PIPE, text=True, check=True)
        bitrate = float(result.stdout) / 1000
        bitrates.append(bitrate)
    return bitrates

def check_for_flac_files(directory):
    # Initialize a flag to indicate if .flac files were found
    flac_found = False

    # List all files in the directory
    for filename in os.listdir(directory):
        if filename.endswith(".flac"):
            flac_found = True
    return flac_found

def main(directory):
    mp3_bitrates = get_bitrates(directory, 'mp3')
    m4a_bitrates = get_bitrates(directory, 'm4a')
    flac_exists = check_for_flac_files(directory)

    # Regular expression pattern
    pattern = r'^(.*?)(?: \[MP3 \d{2,3}\]| \[M4A \d{2,3}\]| \[MP3 \d{2,3}-\d{2,3}\]| \[M4A \d{2,3}-\d{2,3}\]| \[FLAC\+MP3 \d{2,3}\]| \[FLAC\+M4A \d{2,3}\])'

    # Match the pattern against the directory
    match = re.match(pattern, directory)

    # Initialize new_directory with the original directory
    new_directory = directory

    # If there's a match, update new_directory with the captured text
    if match:
        captured_text = match.group(1)
        new_directory = captured_text

    if not mp3_bitrates and not m4a_bitrates and not flac_exists:
        print("Directory does not contain .mp3 .m4a or .flac files.")
        sys.exit(1)

    if not mp3_bitrates and not m4a_bitrates and flac_exists:
        print("Directory only contains .flac files.")
        sys.exit(1)

    if mp3_bitrates and m4a_bitrates:
        print("Mp3 and m4a mix.")
        sys.exit(1)

    if mp3_bitrates and not m4a_bitrates and not flac_exists:
        avg_bitrate = round(sum(mp3_bitrates) / len(mp3_bitrates))
        min_bitrate = round(min(mp3_bitrates))
        max_bitrate = round(max(mp3_bitrates))

        if min_bitrate == avg_bitrate or max_bitrate == avg_bitrate:
            new_name = f"{os.path.basename(new_directory)} [MP3 {avg_bitrate}]"
        else:
            new_name = f"{os.path.basename(new_directory)} [MP3 {min_bitrate}-{max_bitrate}]"

    if not mp3_bitrates and m4a_bitrates and not flac_exists:
        avg_bitrate = round(sum(m4a_bitrates) / len(m4a_bitrates))
        min_bitrate = round(min(m4a_bitrates))
        max_bitrate = round(max(m4a_bitrates))

        if min_bitrate == avg_bitrate or max_bitrate == avg_bitrate:
            new_name = f"{os.path.basename(new_directory)} [M4A {avg_bitrate}]"
        else:
            new_name = f"{os.path.basename(new_directory)} [M4A {min_bitrate}-{max_bitrate}]"

    if mp3_bitrates and not m4a_bitrates and flac_exists:
        mp3_avg_bitrate = round(sum(mp3_bitrates) / len(mp3_bitrates))
        new_name = f"{os.path.basename(new_directory)} [FLAC+MP3 {mp3_avg_bitrate}]"

    if not mp3_bitrates and m4a_bitrates and flac_exists:
        m4a_avg_bitrate = round(sum(m4a_bitrates) / len(m4a_bitrates))
        new_name = f"{os.path.basename(new_directory)} [FLAC+M4A {m4a_avg_bitrate}]"

    
    os.rename(directory, os.path.join(os.path.dirname(directory), new_name))
    subprocess.run(['mp3tag', '/add', f"/fn:{os.path.join(os.path.dirname(directory), new_name)}"])

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python script.py <directory>")
        sys.exit(1)

    directory = sys.argv[1]

    if not os.path.isdir(directory):
        print("Invalid directory path.")
        sys.exit(1)

    main(directory)

These days I'd probably make it recursive as well instead of only relying on it being called with the folderpath.
I'd also use mediainfo instead of exiftool to extract the relevant audio information.
Also the flac bit depth and sampling rate aren't in it because back then I used an mp3tag action group to calculate these. As I said, it's highly incomplete.
I might take a stab at it when I'm done with my current project.
But feel free to let me know if it helps or if you manage to improve it.