PR #25118 opened by Naomi Rennie-Waldock (nrenniewaldock) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25118 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25118.patch
# Summary of changes This adds generic tag mappings for some more tags, particularly the ones added by [MusicBrainz Picard](https://picard-docs.musicbrainz.org/en/latest/_static/MusicBrainz_Picard_Tag_Map.html). # Why? My primary music library is mostly FLAC, with a few digital copies that only come as MP3 or M4A. I'm using ffmpeg to maintain an Opus copy of it for portable devices, and found that some media players showed duplicate artists where the sources included both lossy and lossless files as they merge by tags (artist + artist sort, some also use musicbrainz artist id). Without this, transcode combinations like M4A to Opus or FLAC to MP3 would have incorrectly named tags that are ignored by media players. I'll mark this as WIP for now to get feedback. I also plan to update movenc to write the tags as well. >From 13cacdd78b1881eb84221e46a962d60a249a2432 Mon Sep 17 00:00:00 2001 From: Naomi Rennie-Waldock <[email protected]> Date: Fri, 16 Oct 2026 13:44:01 +0100 Subject: [PATCH 1/5] avformat/mov: rename the generic mappings for sort tags to be consistent with other formats ID3v2 uses -sort, and avformat.h says: > a modified version of a tag that should be used for > sorting will have '-sort' appended. E.g. artist="The Beatles", > artist-sort="Beatles, The". --- libavformat/mov.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index f7c12922d9..ceee120366 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -404,12 +404,12 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) case MKTAG( 'p','u','r','d'): key = "purchase_date"; break; case MKTAG( 'r','t','n','g'): key = "rating"; parse = mov_metadata_int8_no_padding; break; - case MKTAG( 's','o','a','a'): key = "sort_album_artist"; break; - case MKTAG( 's','o','a','l'): key = "sort_album"; break; - case MKTAG( 's','o','a','r'): key = "sort_artist"; break; - case MKTAG( 's','o','c','o'): key = "sort_composer"; break; - case MKTAG( 's','o','n','m'): key = "sort_name"; break; - case MKTAG( 's','o','s','n'): key = "sort_show"; break; + case MKTAG( 's','o','a','a'): key = "album_artist-sort"; break; + case MKTAG( 's','o','a','l'): key = "album-sort"; break; + case MKTAG( 's','o','a','r'): key = "artist-sort"; break; + case MKTAG( 's','o','c','o'): key = "composer-sort"; break; + case MKTAG( 's','o','n','m'): key = "name-sort"; break; + case MKTAG( 's','o','s','n'): key = "show-show"; break; case MKTAG( 's','t','i','k'): key = "media_type"; parse = mov_metadata_int8_no_padding; break; case MKTAG( 't','r','k','n'): key = "track"; -- 2.54.0 >From 1dd651cc442f61c14f268fd095e21ddc31ef0fb1 Mon Sep 17 00:00:00 2001 From: Naomi Rennie-Waldock <[email protected]> Date: Fri, 16 Oct 2026 13:44:05 +0100 Subject: [PATCH 2/5] avformat/vorbiscomment: add generic mappings for additional tags Taken from Picard's [1] and taglib's [2] documentation. [1]: https://picard-docs.musicbrainz.org/en/latest/_static/MusicBrainz_Picard_Tag_Map.html [2]: https://taglib.org/api/p_propertymapping.html --- libavformat/vorbiscomment.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c index 09973a576d..7dabf31290 100644 --- a/libavformat/vorbiscomment.c +++ b/libavformat/vorbiscomment.c @@ -38,6 +38,13 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = { /* Adapted from <https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#disc-subtitle> */ { "DISCSUBTITLE", "disc_subtitle" }, { "DESCRIPTION", "comment" }, + { "ALBUMARTISTSORT", "album_artist-sort" }, + { "ALBUMSORT", "album-sort" }, + { "ARTISTSORT", "artist-sort" }, + { "COMPOSERSORT", "composer-sort" }, + { "RELEASECOUNTRY", "release_country" }, + { "RELEASESTATUS", "release_status" }, + { "RELEASETYPE", "release_type" }, { 0 } }; -- 2.54.0 >From 684999174abc387d88315857f008a4191d07515a Mon Sep 17 00:00:00 2001 From: Naomi Rennie-Waldock <[email protected]> Date: Fri, 16 Oct 2026 13:44:05 +0100 Subject: [PATCH 3/5] avformat/id3v2: add generic `album_artist-sort`, `composer-sort`, and `media` tag mappings Taken from Picard's [1] and taglib's [2] documentation. [1]: https://picard-docs.musicbrainz.org/en/latest/_static/MusicBrainz_Picard_Tag_Map.html [2]: https://taglib.org/api/p_propertymapping.html --- libavformat/id3v2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 5ae931da9b..e28365b480 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -55,12 +55,15 @@ const AVMetadataConv ff_id3v2_34_metadata_conv[] = { { "TENC", "encoded_by" }, { "TIT2", "title" }, { "TLAN", "language" }, + { "TMED", "media", }, { "TPE1", "artist" }, { "TPE2", "album_artist" }, { "TPE3", "performer" }, { "TPOS", "disc" }, { "TPUB", "publisher" }, { "TRCK", "track" }, + { "TSO2", "album_artist-sort"}, + { "TSOC", "composer-sort"}, { "TSSE", "encoder" }, { "USLT", "lyrics" }, { 0 } @@ -96,7 +99,8 @@ attribute_nonstring const char ff_id3v2_tags[][4] = { "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT", "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED", "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3", - "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE", + "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSO2", "TSOC", + "TSRC", "TSSE", { 0 }, }; -- 2.54.0 >From a51606d757c639989bd1e5934663be33fe1cf50b Mon Sep 17 00:00:00 2001 From: Naomi Rennie-Waldock <[email protected]> Date: Fri, 16 Oct 2026 13:44:05 +0100 Subject: [PATCH 4/5] avformat/id3v2: add generic mappings for MusicBrainz tags Taken from Picard's [1] and taglib's [2] documentation. [1]: https://picard-docs.musicbrainz.org/en/latest/_static/MusicBrainz_Picard_Tag_Map.html [2]: https://taglib.org/api/p_propertymapping.html --- libavformat/id3v2.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index e28365b480..88e6d8e70c 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -66,6 +66,22 @@ const AVMetadataConv ff_id3v2_34_metadata_conv[] = { { "TSOC", "composer-sort"}, { "TSSE", "encoder" }, { "USLT", "lyrics" }, + { "Acoustid Fingerprint", "acoustid_fingerprint" }, + { "MusicBrainz Artist Id", "musicbrainz_artistid" }, + { "MusicBrainz Composer Id", "musicbrainz_composerid" }, + { "MusicBrainz Disc Id", "musicbrainz_discid" }, + { "MusicBrainz Original Artist Id", "musicbrainz_originalartistid" }, + { "MusicBrainz Original Album Id", "musicbrainz_originalalbumid" }, + { "MusicBrainz Recording Id", "musicbrainz_recordingid" }, + { "MusicBrainz Album Artist Id", "musicbrainz_albumartistid" }, + { "MusicBrainz Release Group Id", "musicbrainz_releasegroupid" }, + { "MusicBrainz Album Id", "musicbrainz_albumid" }, + { "MusicBrainz Track Id", "musicbrainz_trackid" }, + { "MusicBrainz Work Id", "musicbrainz_workid" }, + { "MusicBrainz Album Release Country", "release_country" }, + { "MusicBrainz Album Status", "release_status" }, + { "MusicBrainz Album Type", "release_type" }, + { "MusicBrainz Release Track Id", "musicbrainz_releasetrackid" }, { 0 } }; -- 2.54.0 >From 5a433f271a88cce05cf9054610e1ef17165139af Mon Sep 17 00:00:00 2001 From: Naomi Rennie-Waldock <[email protected]> Date: Fri, 16 Oct 2026 13:44:06 +0100 Subject: [PATCH 5/5] avformat/mov: add generic mappings for MusicBrainz tags Taken from Picard's [1] and taglib's [2] documentation. [1]: https://picard-docs.musicbrainz.org/en/latest/_static/MusicBrainz_Picard_Tag_Map.html [2]: https://taglib.org/api/p_propertymapping.html --- libavformat/mov.c | 75 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index ceee120366..2cf4854725 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5870,11 +5870,76 @@ static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom) priming, remainder, samples); } } - if (strcmp(mean, "com.apple.iTunes") == 0 && - strcmp(key, "DISCSUBTITLE") == 0) { - av_dict_set(&c->fc->metadata, "disc_subtitle", val, - AV_DICT_DONT_STRDUP_VAL); - val = NULL; + if (strcmp(mean, "com.apple.iTunes") == 0) { + if (strcmp(key, "DISCSUBTITLE") == 0) { + av_dict_set(&c->fc->metadata, "disc_subtitle", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "Acoustid Fingerprint") == 0) { + av_dict_set(&c->fc->metadata, "acoustid_fingerprint", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Artist Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_artistid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Composer Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_composerid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Disc Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_discid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Original Artist Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_originalartistid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Original Album Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_originalalbumid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Recording Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_recordingid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Album Artist Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_albumartistid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Release Group Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_releasegroupid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Album Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_albumid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Track Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_trackid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Work Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_workid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Album Release Country") == 0) { + av_dict_set(&c->fc->metadata, "release_country", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Album Status") == 0) { + av_dict_set(&c->fc->metadata, "release_status", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Album Type") == 0) { + av_dict_set(&c->fc->metadata, "release_type", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } else if (strcmp(key, "MusicBrainz Release Track Id") == 0) { + av_dict_set(&c->fc->metadata, "musicbrainz_releasetrackid", val, + AV_DICT_DONT_STRDUP_VAL); + val = NULL; + } } if (strcmp(key, "cdec") != 0) { av_dict_set(&c->fc->metadata, key, val, -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
