lofty-rs
lofty-rs copied to clipboard
Writing metadata to specific mp3 causes error BadFrame("MODE", Text)
Reproducer
Code
#!/usr/bin/env -S cargo +nightly -Zscript
```cargo
[dependencies]
lofty = "0.17.1"
```
use lofty::{ItemKey, LoftyError, Probe, Tag, TagExt, TaggedFileExt};
use std::path::Path;
#[derive(Default, Debug, Clone)]
pub struct Metadata {
pub artist: String,
pub title: String,
pub bpm: f32,
pub key: String,
pub comment: String,
pub mood: String,
}
pub fn write_metadata(
path: impl AsRef<Path> + Copy,
metadata: &Metadata,
) -> Result<(), LoftyError> {
let mut tagged_file = Probe::open(path)?.read()?;
let tag = match tagged_file.primary_tag_mut() {
Some(primary_tag) => primary_tag,
None => {
if let Some(first_tag) = tagged_file.first_tag_mut() {
first_tag
} else {
let tag_type = tagged_file.primary_tag_type();
eprintln!("WARN: No tags found, creating a new tag of type `{tag_type:?}`");
tagged_file.insert_tag(Tag::new(tag_type));
tagged_file.primary_tag_mut().unwrap()
}
}
};
tag.insert_text(ItemKey::TrackArtist, metadata.artist.clone());
tag.insert_text(ItemKey::TrackTitle, metadata.title.clone());
tag.insert_text(ItemKey::Bpm, metadata.bpm.to_string());
tag.insert_text(ItemKey::InitialKey, metadata.key.clone());
tag.insert_text(ItemKey::Comment, metadata.comment.clone());
tag.insert_text(ItemKey::Mood, metadata.mood.clone());
tag.save_to_path(path)?;
Ok(())
}
fn main() {
write_metadata("./07-tehotu-encoder-6c2b060a.mp3", &Metadata {
artist: "tehotu".to_string(),
title: "encoder".to_string(),
bpm: 42.0,
key: "12A".to_string(),
comment: "testcomment".to_string(),
mood: "testmood".to_string()
}).expect("Failed writing metadata");
Summary
Writing metadata fails because of error
Expected behavior
Writing metadata doesn't fail
Assets
https://we.tl/t-zYjiGOjteR 07-tehotu-encoder-6c2b060a.mp3 e2
So what's happening:
- The file has a
TXXX:MODEframe - The
Id3v2Tag->Tagconversion tries to convert allTXXXdescriptions toItemKeys -
TXXX:MODEis stored asItemKey::Unknown("MODE") - The
Tag->Id3v2Tagcreates aMODEtext frame (not aTXXXframe!), as the description is 4 characters long, it is believed to be a normal frame ID - The
Id3v2Tagnow fails verification, as text frames are expected to start with 'T'
That's a pretty major oversight on my part. I hadn't accounted for 4 character descriptions. :smile:
When I get to implementing #302, I can further restrict the TXXX -> TagItem conversion.