Tagging ALAC files - double values

Hello everyone,

I am currently editing my iTunes/Apple Music library. My main format is ALAC.

I have noticed that Picard edits and saves the ALAC files correctly,

but as soon as I open the files again in Picard (delete release and drag the files into Picard one more time), certain values are saved twice, e.g., release country, release type, MB IDs. and I get the red star*

My script currently looks like this:
$unset(artistsort)
$unset(albumartistsort)
$replace(%artist%,ft.,feat.)
$replace(%album%,<<,«)
$replace(%album%,>>,»)
$set(grouping,%catalognumber%)

When I tag the same release in FLAC format, the values are saved correctly and are retained when I reload them.

Does anyone have any idea what is different with ALAC?

When more details are needed please let me know


But here you can see in the second image that Picard fixed your tags. They were double (original value), now they’re single (new value). So save and you’ll be fine.

When you have a gold disc without a star in the first image, click on the first track to make the tags visible, as in the second image.

Does the script work on the first image and the second? Or only on the first image where the error occurs?

2 Likes

Then try this:

$unset(artistsort)
$unset(albumartistsort)
$set(artist,$replace(%artist%,ft.,feat.))
$set(album,$replace($replace(%album%,<<,«),>>,»))
$set(grouping,%catalognumber%)

What’s changed:
$set(artist,
): Instead of just $replace, the result of the operation is hard-coded into the artist tag. This replaces the old value with the new one.

Nested $replace for album: I’ve combined both replacements into one line to make the script cleaner and faster.

$set(grouping,
): Ensures that the catalog number isn’t appended to the previous value in the grouping field.

1 Like

@slipmaxim

In MusicBrainz Picard, tag duplication in ALAC files (MP4/M4A format) occurs because Picard maps standard fields (e.g., artistsort) to specific technical atoms, while your script might be creating additional “free” tags with the same name.

To definitively eliminate this issue, apply the following solutions:

1. Enable Tag Clearing in Options (Recommended)

This is the most effective method for ALAC files. Picard will remove all existing metadata before saving new data, preventing old and new atoms from “stacking.”

  • Go to Options > Tags.

  • Check the option “Clear existing tags”.

  • Note: If you have custom tags you want to keep, add their names to the “Preserve these tags from being cleared” list in the same menu.

2. Modify the Script (Logic Fix)

In ALAC/MP4, using $unset alone isn’t always enough if the field is reset within the same write cycle. Try this version of the script:

$unset(artistsort)
$unset(albumartistsort)
$unset(grouping)

$set(artist,$replace(%artist%,ft.,feat.))
$set(album,$replace($replace(%album%,<<,«),>>,»))
$set(grouping,%catalognumber%)

Why does ALAC cause problems while FLAC doesn’t?

  • FLAC: Uses simple Vorbis comments where the tag name is plain text (e.g., ARTIST). Overwriting values is straightforward.

  • ALAC (MP4): Uses specific codes (atoms), such as ©ART for artist or soar for sorting. If a text-based tag named “artistsort” already exists in the file (e.g., created by another program), Picard will write the new value to the soar atom but won’t remove the old text tag, resulting in visible duplicates.

Tip: If you still see duplicates in your player after these changes, use a tool like MP3Tag to view “Extended Tags.” This will allow you to see if there are hidden atoms with non-standard names that Picard does not map automatically.

1 Like

You likely have additional freeform tags that map to the same internal tag name. E.g. in your case with the MP4 format Picard would expect the Artist MBID to be stored in a tag called ----:com.apple.iTunes:MusicBrainz Artist Id. But it also reads other tags stored inside ----:com.apple.iTunes: and just maps them literally to the same internal name it would in addition read ----:com.apple.iTunes:musicbrainz_artistid.

Have a look at Appendix B: Tag Mapping — MusicBrainz Picard v2.13.3 documentation . This issue can generally happen if there is a mapping between the internal tag name and a format specific name. If the file contains the tag again matching the internal tag name you get it loaded twice.

We have a ticket for this somewhere, but no good solution yet.

2 Likes

Thank you so much for you time and effort! It helped a lot.

It’s more clear now to me.

Yes, I’ve used several “free” tags back in the day, manual tagging in foobar, switched to Yate for some time. It was a long way.

MP3Tag extended tags reveals the mess:

a lot of double values.

This did the trick right away: 1. Enable Tag Clearing in Options (Recommended)

But it will also wipe a lot of data I’ve added over the years. I need to check what I want to keep


THANK YOU for the script update. Finally, it works like it should.

Maybe one additional script question: I want to get rid of different kind of “feat.” variations like “f/”, “ft.” etc. how do I keep it in one script line?

$set(artist,$rreplace(%artist%,\\s+[Ff](?:eat\\.?|t\\.?|/)\\s+.*,))
$set(albumartist,$rreplace(%albumartist%,\\s+[Ff](?:eat\\.?|t\\.?|/)\\s+.*,))

What this script does:

  • \\s+ – looks for a space before the tag.

  • [Ff](?:eat\\.?|t\\.?|/) – catches variants: feat, feat., ft, ft., and f/ (both lowercase and uppercase).

  • \\s+.* – removes everything after the tag until the end of the field.

1 Like

Thanks WindwosLover,

unfortunately I get a warning when I try your script: $set(artist,$rreplace(%artist%,\s+Ff\s+.,))
$set(albumartist,$rreplace(%albumartist%,\s+Ff\s+.
,))

Bildschirmfoto 2026-03-13 um 21.25.34

Adding these lines to your MusicBrainz Picard script often triggers an “unexpected character ‘(’” error. This happens because the Picard script parser is highly sensitive to how commas and parentheses are handled within functions, especially inside regular expressions.

The Cause of the Error

In Picard scripting, the comma (,) is used to separate function arguments. If a comma appears inside your $rreplace expression without being quoted, Picard treats it as the end of an argument. This breaks the function’s structure and leads to syntax errors, such as unmatched parentheses.

How to Fix It

To make the script work correctly, you must “hide” special characters (commas, parentheses) from the parser by enclosing the entire regular expression in single quotes (').

Here is the corrected version of your script:

$set(artist,$rreplace(%artist%,'\\s+[Ff](?:eat\\.?|t\\.?|/)\\s+.*',))
$set(albumartist,$rreplace(%albumartist%,'\\s+[Ff](?:eat\\.?|t\\.?|/)\\s+.*',))

Key Rules for a Correct Script:

  • Use Single Quotes: Always wrap the second argument of the $rreplace function (the regex pattern) in '...' if it contains characters like ,, (, or ).

  • Watch for Double Backslashes: In Picard scripts, you often need to use a double backslash (e.g., \\s instead of \s) so the regex engine interprets it correctly.

  • $rreplace vs. $replace: Remember that $rreplace supports regular expressions (regex), while the standard $replace is only for simple text replacement.

1 Like