Serial-ATA / lofty-rs

Audio metadata library
Apache License 2.0
187 stars 35 forks source link

Can not write multiple artists with mp3 and generic `Tag` #349

Open vnghia opened 8 months ago

vnghia commented 8 months ago

Reproducer

I tried this code:

let mut tag = Id3v2Tag::default();
tag.set_artist(artists.join("\0")); // ["Artist1", "Artist2"]
let mut tag: Tag = tag.into();
tag.save_to_path(&path).unwrap();

// re-read
let tagged_file = read_from_path(&path).unwrap();
let artists = tagged_file.primary_tag().unwrap().
            .get_strings(&ItemKey::TrackArtist)
            .map(std::string::ToString::to_string)
            .collect_vec(); // ["Artists2"]

while this code works:

let mut tag = Id3v2Tag::default();
tag.set_artist(artists.join("\0")); // ["Artist1", "Artist2"]
tag.save_to_path(&path).unwrap();

// re-read
let tagged_file = read_from_path(&path).unwrap();
let artists = tagged_file.primary_tag().unwrap().
            .get_strings(&ItemKey::TrackArtist)
            .map(std::string::ToString::to_string)
            .collect_vec(); // ["Artist1", "Artist2"]

And it seems that this only happens with mp3. I can write multiple artists with vorbis comment on a flac file.

Summary

When converting to generic Tag from Id3v2Tag, multiple artitsts are not preserved.

Expected behavior

When converting to generic Tag from Id3v2Tag, multiple artitsts are preserved.

Assets

No response

Serial-ATA commented 8 months ago

That's an interesting one. Id3v2Tag::merge_tag() handles joining items, but Tag::save_to_path() skips the merging step. The artists are both written, the problem is they end up in different frames, which is not correct. For now, the solution would be to just convert the Tag back to an Id3v2Tag when you are done with it.