1 Start Simple

The following example shows how you can read an audio file, parse, set, and save its metadata:

fn main() {
    // using `default()` or `new()` alone so that the metadata format is
    // guessed (from the file extension) (in this case, Id3v2 tag is read)
    let mut tag = Tag::new().read_from_path(MP3_FILE).unwrap();
    // You can also specify the metadata format (tag type):
    let _tag = Tag::new()
        .with_tag_type(TagType::Id3v2)
        .read_from_path(MP3_FILE)
        .expect("Fail to read!");

    tag.set_title("foo title");
    assert_eq!(tag.title(), Some("foo title"));
    tag.remove_title();
    assert!(tag.title().is_none());
    tag.remove_title();
    // trying to remove a field that's already empty won't hurt

    let cover = Picture {
        mime_type: MimeType::Jpeg,
        data: &vec![0u8; 10],
    };

    tag.set_album_cover(cover.clone());
    assert_eq!(tag.album_cover(), Some(cover));
    tag.remove_album_cover();
    assert!(tag.album_cover().is_none());
    tag.remove_album_cover();

    tag.write_to_path(MP3_FILE).expect("Fail to save");
    // TASK: reload the file and prove the data have been saved
}

Note that Tag always reads into a Box<dyn AudioTag>. If you do not want a trait object, you can use the underlying concrete types. However, you’ll also need to manually bring the traits into scope if you prefer not to write audiotags::*.

use audiotags::{traits::*, FlacTag, Id3v2Tag, Mp4Tag};
// or alternatively `use audiotags::*`

fn main() {
    let mut tag = FlacTag::read_from_path("assets/a.flac").unwrap();
    tag.set_title("foo");
    assert_eq!(tag.title(), Some("foo"));
    let mut tag = Mp4Tag::read_from_path("assets/a.m4a").unwrap();
    tag.set_title("foo");
    assert_eq!(tag.title(), Some("foo"));
    let mut tag = Id3v2Tag::read_from_path("assets/a.mp3").unwrap();
    tag.set_title("foo");
    assert_eq!(tag.title(), Some("foo"));
    // all other methods in trait `AudioTagEdit` are available, not just title
}