pdeljanov / Symphonia

Pure Rust multimedia format demuxing, tag reading, and audio decoding library
Mozilla Public License 2.0
2.32k stars 136 forks source link

Mapping metadata to struct #184

Open 112RG opened 1 year ago

112RG commented 1 year ago

I am currently using metaflac in my project Deaftone. I am wanting to try out Symphonia to map tags from files into a struct I have but I am unsure how todo that with the examples and docs given.

In metaflac I simply

    let metadata: AudioMetadata = AudioMetadata {
        name: vorbis
            .title()
            .map(|v| v[0].clone())
            .unwrap_or_else(|| "FAILED TO READ TITLE DEAFTONE".to_string()),
        album: vorbis
            .album()
            .map(|v| v[0].clone())
            .unwrap_or_else(|| "FAILED TO READ ALBUM DEAFTONE".to_string()),
        album_artist: match vorbis.album_artist().map(|v| v[0].clone()) {
            Some(e) => e,
            None => vorbis
                .artist()
                .map(|v| v[0].clone())
                .unwrap_or_else(|| "FAILED TO READ ARTIST DEAFTONE".to_string()),
        },
        year: get_year(vorbis),
        track: vorbis.track().unwrap_or(0),
        path,
        lossless: true,
        duration: duration.unwrap_or_default(),
    };

But I am unsure how todo that with the library currently. Here is my struct defined below

pub struct AudioMetadata {
    pub name: String,
    pub artist: String,
    pub artist_sort: Option<String>,
    pub album_name: String,
    pub album_artist: String,
    pub album_sort: Option<String>,
    pub genre: Option<Vec<String>>,
    pub style: Option<Vec<String>>,
    pub discogs_albumid: Option<String>,
    pub discogs_artistid: Option<String>,
    pub discogs_labelid: Option<String>,
    pub lyricist: Option<String>,
    pub composer: Option<String>,
    pub composer_sort: Option<String>,
    pub work: Option<String>,
    pub mb_workid: Option<String>,
    pub arranger: Option<String>,
    pub grouping: Option<String>,
    pub year: i32,
    pub lyrics: Option<String>,
    pub comments: Option<String>,
    pub bpm: Option<String>,
    pub compilation: Option<String>,
    pub mb_track_id: Option<String>,
    pub mb_album_id: Option<String>,
    pub mb_artist_id: Option<String>,
    pub mb_albumartist_id: Option<String>,
    pub mb_releasetrack_id: Option<String>,
    pub mb_releasegroup_id: Option<String>,
    pub trackdisambig: Option<String>,
    pub album_type: Option<String>,
    pub acoustid_fingerprint: Option<String>,
    pub acoustid_id: Option<String>,
    pub asin: Option<String>,
    pub isrc: Option<String>,
    pub catalog_num: Option<String>,
    pub script: Option<String>,
    pub country: Option<String>,
    pub albumstatus: Option<String>,
    pub media: Option<String>,
    pub album_disambig: Option<String>,
    pub release_group_disambig: Option<String>,
    pub encodedby: Option<String>,
    pub original_year: Option<String>,
    pub initial_key: Option<String>,
    pub bit_rate: Option<i64>,
    pub encoder_settings: Option<String>,
    pub channels: Option<u8>,
    pub bit_depth: Option<u8>,
    pub sample_rate: Option<u32>,
    pub track: u32,
    pub disc: u32,
    pub length: u32,
    pub label: Option<String>,
    pub path: String,
    pub parent_path: String,
}
pdeljanov commented 1 year ago

If you don't need playback, then I'd recommend using the lofty crate instead of Symphonia since it's more comprehensive and simpler. Symphonia's metadata system is more complex because it has to deal with mid-stream changes to metadata.


Once you have a FormatReader, call the FormatReader::metadata function to get access to the metadata log. This is basically of a queue of MetadataRevisions with functions to iterate over and consume the revisions. Each MetadataRevision provides access to Tags, and Visuals (pictures). Looping through those slices will get you what you are looking for. My recommendation is to use the standard tag and visual key fields to match tags to your data structure.

One thing to note is that metadata can also be found while probing the file. This famously happens with ID3v2 tags since those are just binary blobs at the start of the file. The ProbeResult returned after the probe operation also returns a metadata log that should be consumed in the same way.

It's up to the application to decide how to interpret these revisions (i.e., whether one replaces another completely, or simply updates an older revision).

112RG commented 1 year ago

I will be using playback my project https://github.com/Ortygia/Deaftone is a music server. But I am still looking for a fast tag scanner solution metaflac is currently the fastest and from this discussion here https://github.com/Deaftone/Deaftone/issues/8#issuecomment-1376746887 metaflac is beating out lofty-rs on my testing. So I wanted to test out Symphonia as I am looking to squeeze the most performance possible out of it

sealter commented 1 year ago

If you don't need playback, then I'd recommend using the lofty crate instead of Symphonia since it's more comprehensive and simpler. Symphonia's metadata system is more complex because it has to deal with mid-stream changes to metadata.

Once you have a FormatReader, call the FormatReader::metadata function to get access to the metadata log. This is basically of a queue of MetadataRevisions with functions to iterate over and consume the revisions. Each MetadataRevision provides access to Tags, and Visuals (pictures). Looping through those slices will get you what you are looking for. My recommendation is to use the standard tag and visual key fields to match tags to your data structure.

One thing to note is that metadata can also be found while probing the file. This famously happens with ID3v2 tags since those are just binary blobs at the start of the file. The ProbeResult returned after the probe operation also returns a metadata log that should be consumed in the same way.

It's up to the application to decide how to interpret these revisions (i.e., whether one replaces another completely, or simply updates an older revision).

What about video metadata, is there a comprehensive and simpler crate? I just want to get video metadata