All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- ID3v2:
ChapterFrameandChapterTableOfContentsFrameFrameList, a sharedFramestorage used inId3v2Tag,ChapterFrameandChapterTableOfContentsFrameId3v2ErrorKind::UnsupportedVersion
- ID3v2: Moved
error::{Id3v2Error, Id3v2ErrorKind}toid3::v2::error::{Id3v2Error, Id3v2ErrorKind}
0.23.3 - 2026-03-14
- ItemKey:
ItemKey::MusicBrainzReleaseType(PR)
- ID3v2:
ItemKey::Lyricsis no longer supported (issue) (PR)ItemKey::Lyricsis often overloaded with synchronized lyrics in LRC format. In other formats, the distinction betweenItemKey::LyricsandItemKey::UnsyncLyricsdoesn't matter much as they're both text fields. In ID3v2, however, synchronized lyrics are a separate binary frame. To write synchronized lyrics, you'll have to useId3v2TagandSynchronizedTextFramedirectly.
- ID3v2:
- Timestamp: Only enforce valid year in strict mode (issue) (PR)
- OGG Vorbis: Fixed potential infinite loop while property reading (issue) (PR)
- IFF: Support chunks with invalid padding (issue) (PR)
- When RIFF/AIFF chunks have an odd length, they should be padded, and the padding is not counted in the chunk size. However, some encoders incorrectly include the padding in the size, which can cause the parser to go out of sync. We no longer assume padding is valid and have additional checks to stay in sync when possible.
0.23.2 - 2026-02-14
- FLAC:
- Fix duplicate
Last-metadata-blockflags in the presence of PADDING blocks (issue) (PR) - Ignore ID3v2 tags when not stripped during write (issue) (PR)
- Previously, the Vorbis Comments writer assumed that the ID3v2 tag had already been stripped. If that wasn't the case, it would error that it couldn't find the FLAC stream marker.
- Fix duplicate
0.23.1 - 2026-02-08
- Docs: Replaced
doc_auto_cfgwithdoc_cfg(PR)
0.23.0 - 2026-02-08
- ItemKey:
ItemKey::AlbumArtists, available for ID3v2, Vorbis Comments, APE, and MP4 Ilst (PR)- This is a multi-value item that stores each artist for a track. It should be retrieved with
Tag::get_stringsorTag::take_strings. - For example, a track has
ItemKey::TrackArtist= "Foo & Bar", thenItemKey::AlbumArtists= ["Foo", "Bar"].
- This is a multi-value item that stores each artist for a track. It should be retrieved with
ItemKey::UnsyncLyrics(issue) (PR)- In formats like Vorbis Comments,
ItemKey::Lyricsmay actually contain synchronized lyrics in LRC format. To help with the ambiguity, some apps may write a separate field containing normal, unsynchronized lyrics. - In other formats where the difference doesn't matter (like ID3v2), this will act exactly the same as
ItemKey::Lyrics.
- In formats like Vorbis Comments,
ItemKey::ReleaseCountry(PR)- Currently, this maps to the fields used by MusicBrainz Picard, which expect an ISO 3166-1 code.
ItemKey::AcoustIdandItemKey::AcoustIdFingerprint(issue) (PR)- These two fields come from AcoustID, and can appear multiple times in a single tag.
ItemKey::Descriptionmapping for Vorbis Comments (issue) (PR)
- Serde: Serde support for
*Typeenums (FileType,TagType,PictureType) (issue) (PR)- Support can be enabled with the new
serdefeature (not enabled by default)
- Support can be enabled with the new
- Probe:
Probe::read_bound()(PR)- Same as
Probe::read(), but returns aBoundTaggedFile
- Same as
- ID3v2 (PR):
- Unified the two generic conversion paths
- The background conversion used in
Tag::save_to(), and the direct conversion done viaInto::<Id3v2Tag>::into(tag)used to take different paths, causing certain conversions and frame merging to not occur in the former case (issue). They now use the same logic, which has also been rewritten to reuse data whenever possible, instead of cloning like before.
- The background conversion used in
- The following frames now use
Cowinternally:CommentFrame,UnsynchronizedTextFrame,TextInformationFrame,ExtendedTextFrame,UrlLinkFrame,ExtendedUrlFrame,AttachedPictureFrame,PopularimeterFrame,KeyValueFrame,RelativeVolumeAdjustmentFrame,UniqueFileIdentifierFrame,OwnershipFrame,EventTimingCodesFrame,PrivateFrame,BinaryFrame FrameId::is_valid()andFrameId::is_outdated()
- Unified the two generic conversion paths
- WriteOptions:
WriteOptions::lossy_text_encoding()to replace invalid characters when encoding strings (PR)- When enabled, any non-representable character will be replaced with
?(e.g.lфftyinTextEncoding::Latin1will returnl?fty)
- When enabled, any non-representable character will be replaced with
- Popularimeter: Generic user-specified star rating support (discussion) (PR)
- These items require special handling. See the docs for more details.
- Other:
EXTENSIONSlist containing common file extensions for all supported audio file types (issue) (PR)- This is useful for filtering files when scanning directories. If your app uses extension filtering, please consider switching to this, as to not miss any supported files.
- ID3v2: Check
TXXX:ALBUMARTISTandTXXX:ALBUM ARTISTforItemKey::AlbumArtistconversions - ID3v1:
- Vorbis Comments: Check
ALBUM ARTISTforItemKey::AlbumArtistconversions - Vorbis Comments: Support
DISCNUMBERfields with thecurrent/totalformat. (issue) (PR)- These fields will now properly be split into
DISCNUMBERandDISCTOTAL, making it possible to use them with Accessor::disk() and Accessor::disk_total().
- These fields will now properly be split into
- ItemKey:
- FileType: Replaced
FileType::supports_tag_type()withFileType::tag_support()(PR)- Rather than a simple
bool, this now returns aTagSupport, which can describe three states: unsupported, read-only, and read/write
- Rather than a simple
- TaggedFileExt: Replaced
TaggedFileExt::supports_tag_type()withTaggedFileExt::tag_support()(PR) - FileResolver: Replaced
FileResolver::supported_tag_types()withFileResolver::tag_support()(PR)
- ID3v2:
- Support parsing UTF-16
COMM/USLTframes with a single BOM (issue) (PR)- Some encoders will only write a BOM to the frame's description, rather than to every string in the frame.
This was previously only supported in
SYLTframes, and has been extended toCOMMandUSLT.
- Some encoders will only write a BOM to the frame's description, rather than to every string in the frame.
This was previously only supported in
- Don't error on empty
SYLTstrings (issue) (PR)
- Support parsing UTF-16
- Vorbis Comments: Parse
TRACKNUMBERwith respect toParseOptions::implicit_conversions(issue) (PR) - APE: Fix disc number removal/writing (issue) (PR)
- AAC/ADTS: Fix frame header search (issue) (PR)
- When searching for the next frame, the parser was not fully skipping the previous one. If the AAC payload contained the frame sync bits and an otherwise invalid ADTS header, then the parser would error.
- FLAC: Fix corruption of files with no metadata blocks (issue) (PR)
- OGG: Improved performance of page searching (issue) (PR)
- MP4: Don't error on freeform atoms with no data (PR)
- ItemKey:
ItemKey::Unknown(PR)Tagis now intended for generic metadata editing only, with format-specific items only being available through concrete tag types. See #521 for the rationale.
- Picture:
Picture::new_unchecked(), replaced withPicture::unchecked()returning a builder (issue) (PR) - Accessor:
Accessor::*_year()methods, replaced withAccessor::*_date()(issue) (PR)- Since all formats (except ID3v1) have full date support, the generic API now accepts
Timestamps. For ID3v1, the date will be truncated down to the year for conversions/writing. - Year tags can still be set manually with
ItemKey::Year
- Since all formats (except ID3v1) have full date support, the generic API now accepts
- ID3v2:
AttachedPictureFrame::as_bytes()no longer supports encoding ID3v2.2PICframes
0.22.4 - 2025-04-29
- MP4:
- A missing
mdatatom is no longer a hard error when reading properties (PR)- This is now only an error in
Strictmode. Note that any properties read in a file with nomdatatom are essentially useless.
- This is now only an error in
- Incorrectly sized
freeatoms are no longer a hard error (PR)- If a
freeatom claims to be larger than the remainder of the stream, parsing will simply stop. This will now only be aSizeMismatcherror inStrictmode. Invalid padding is a common issue in all tag formats due to buggy software, so it's better to work around it by default rather than discard the entire stream as invalid.
- If a
- A missing
- WAV:
- When writing tags, the writer will be constrained to the stream size reported by the file, not by the file's actual length (PR)
- Previously, tags were simply written to the end of the file, but this would break files that have junk data appended.
- This allows for files with appended junk data that falls outside of the stream length. This can be caused by buggy software misusing padding.
- When writing tags, the writer will be constrained to the stream size reported by the file, not by the file's actual length (PR)
0.22.3 - 2025-04-04
- MimeType:
MimeType::ext()to get the standard file extension ofPictureMimeTypes (PR)
- 2024 Edition: Set the edition to 2024 and MSRV to 1.85 (issue) (PR)
- This is not a breaking change, as there was no MSRV prior.
0.22.2 - 2025-02-08
Thanks, @Lepidopteran for this release!
- Docs (PR) (PR): Updated old (invalid) links
- ID3v2 (issue) (PR): Preserve all values of
ItemKey::MusicBrainz{ArtistId, ReleaseArtistId, WorkId}- Previously, the fields would be written with only the last value in the list.
0.22.1 - 2025-01-11
- VorbisComments: Support
TRACKNUMBERfields with thecurrent/totalformat. (issue) (issue) (PR)- These fields will now properly be split into
TRACKNUMBERandTRACKTOTAL, making it possible to use them with Accessor::track() and Accessor::track_total().
- These fields will now properly be split into
0.22.0 - 2025-01-05
- ItemKey:
ItemKey::TrackArtists, available for ID3v2, Vorbis Comments, APE, and MP4 Ilst (PR)- This is a multi-value item that stores each artist for a track. It should be retrieved with
Tag::get_stringsorTag::take_strings. - For example, a track has
ItemKey::TrackArtist= "Foo & Bar", thenItemKey::TrackArtists= ["Foo", "Bar"]. - See https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#artists
- This is a multi-value item that stores each artist for a track. It should be retrieved with
- UnsynchronizedStream:
UnsynchronizedStream::get_ref()(PR) - Ilst (PR):
- Methods to quickly set/check boolean flags:
Ilst::set_flagIlst::is_podcastIlst::is_compilationIlst::is_gaplessIlst::is_show_workIlst::is_hd_video
DataTypeenum- Previously, atom data types were stored as a
u32, with their names being available inmp4::constants. Now, instead ofmp4::constants::BE_SIGNED_INTEGER, you can useDataType::BeSignedInteger, for example. - It can be converted to and from a
u32
- Previously, atom data types were stored as a
AtomData::data_type()to get the data type code of the atom content.
- Methods to quickly set/check boolean flags:
- Ilst:
- Add new rules for
gnreatom upgrades (issue) (PR)- In the case that a
©genandgnreatom are present in a file, there was no way to tell which©genatoms were upgraded. the new rules are:gnrepresent + no©genpresent,gnregets upgraded as normalgnrepresent +©genpresent,©gentakes precedence andgnreis discarded- With ParsingOptions::implicit_conversions
set to
false,gnrewill be retained as an atom of typeUnknown.
- With ParsingOptions::implicit_conversions
set to
- In the case that a
- Ignore invalid
covrdata types when not usingParsingMode::Strict(issue) (PR)
- Add new rules for
- RIFF INFO: Ignore text decoding errors when not using
ParsingMode::Strict(issue) (PR)- RIFF INFO tags may be encoded with a non UTF-8 system encoding, that we have no way of knowing. It's no longer an error to read these files, it's just unlikely that anything useful come out of the RIFF INFO tags.
- MusePack: Fix potential panic when the beginning silence makes up the entire sample count (PR)
- Timestamp:
- Support timestamps without separators (ex. "20240906" vs "2024-09-06") (issue) (PR)
Timestamp::parsewill now short-circuit when possible inParsingMode::{BestAttempt, Relaxed}(issue) (PR)- For example, the timestamp "2024-06-03 14:08:49" contains a space instead of the required "T" marker.
In
ParsingMode::Strict, this would be an error. Otherwise, the parser will just stop once it hits the space and return the timestamp up to that point.
- For example, the timestamp "2024-06-03 14:08:49" contains a space instead of the required "T" marker.
In
- ID3v2:
- MP4: Support for flag items (ex.
cpil) of any size (not just 1 byte) (issue) (PR) - Fuzzing (Thanks @qarmin!) (PR) (PR) (PR) (PR) (PR):
- MusePack: Fix panic when ID3v2 tag sizes exceed the stream length (issue)
- WAV: Fix panic when calculating bit depth with abnormally large
bytes_per_sample(issue) - WavPack*: Fix panic when encountering wrongly sized blocks (issue) (issue)
- WavPack*: Fix panic when encountering zero-sized blocks (issue)
- WavPack: Verify the size of non-standard sample rate blocks (issue)
- WavPack: Fix potential overflow in bit depth calculation (issue)
- MPEG: Fix panic when APE tags are incorrectly sized (issue)
- MPEG: Fix panic when calculating the stream length for files with improperly sized frames (issue)
- ID3v2: Fix panic when parsing non-ASCII
TDATandTIMEframes inTDRCconversion (issue) - APE: Fix panic when parsing incorrectly sized header APE tags (issue)
0.21.1 - 2024-08-28
- FLAC: Vendor strings are now retained when writing tags (PR)
- This behavior already exists for OGG formats.
- FLAC: Stop writing invalid
PADDINGblocks (issue) (PR)- If a
PADDINGblock existed in the original file, and it wasn't placed at the end of the header, it would be moved without setting theLast-metadata-blockflag. This would cause decoders to believe that the file was corrupted.
- If a
- Fuzzing (Thanks @qarmin!) (PR):
0.21.0 - 2024-07-29
- ParseOptions:
ParseOptions::read_tagsto skip the parsing of tags (issue) (PR)ParseOptions::read_cover_art(issue) (PR)- As cover art can be large, it is now possible to disable reading it when parsing a file.
ParseOptions::implicit_conversionsto prevent automatic data conversions (PR)- Be sure to read the warnings in the docs to understand what this means.
- ID3v2: Support writing ID3v2.3 tags (issue) (PR)
- This can be done by setting
WriteOptions::use_id3v23totrue.
- This can be done by setting
- Tag:
Tag::take_filter(PR)- This is like
Tag::take, but allows for per-TagItemfiltering. - This is useful for
TagType::Id3v2, as it allows specifying descriptions and languages for frames. See the docs and PR description for more details.
- This is like
- Timestamp:
Timestamp::parsewith empty inputs will returnNonewhen not usingParsingMode::Strict(PR) - MP4: Atoms with sizes greater than the remaining file size will be ignored with
ParsingMode::Relaxed(PR) - ID3v2 (PR):
PopularimeterFrame::as_bytes()is now falliblePrivateFrame::as_bytes()is now fallible
- Fuzzing (Thanks @qarmin!) (PR) (PR):
- MP4:
- Fix panic when reading properties of a file with no timescale specified (issue)
- Fix panics when reading improperly sized freeform atom identifiers (issue) (issue)
- Fix panic when
dataatom length is less than 16 bytes (issue) - Fix panic with improperly sized freeform identifiers (issue)
- Fix panic when
hdlratom is an unexpected length (issue) - Fix panic when
sttsatom has an unrealistically large entry count (issue) (PR)
- WAV:
- Vorbis:
- FLAC: Fix panic when reading properties of a file with incorrect block sizes (issue)
- AIFF: Fix panic when reading properties of a file with invalid f80 sample rate (issue)
- MP4:
0.20.1 - 2024-07-02
0.20.0 - 2024-06-06
- Tag:
- Support
ItemKey::ParentalAdvisoryforIlstandId3v2Tag(issue) (PR)- This will allow for generic edits to the iTunes-style parental advisory tag. Note that this will use the numeric representation. For more information, see: https://docs.mp3tag.de/mapping/#itunesadvisory.
- New
tag::itemsmodule for generic representations of complex tag items - New
Timestampitem for ISO 8601 timestamps (PR)
- Support
- ID3v2: Special handling for frames with timestamps with
Frame::Timestamp(PR) - GlobalOptions:
preserve_format_specific_items()(issue) (PR)- This will allow for the preservation of format-specific items when converting between tag types.
- Previously, these items would be discarded when converting to the generic
Tag. Now they are stored in an immutable container, and silently rejoined with the tag when converting back to the original format or when writing.
- TagItem:
set_langandset_descriptionto allow for generic conversions of additional ID3v2 frames (such as comments) (issue) (PR) - BoundTaggedFile:
BoundTaggedFile::into_innerto get the original file handle (PR)
- VorbisComments/ApeTag: Verify contents of
ItemKey::FlagCompilationduringTagmerge (PR) - ID3v2:
⚠️ Important⚠️ :Framehas been converted to anenum(PR):- This makes it easier to validate frame contents, as one can no longer make an
AttachedPictureFramewith the ID"TALB", for example. See the PR for a full description of the changes.
// Old: let frame = Frame::new( "TALB", FrameType::Text(TextInformationFrame { TextEncoding::UTF8, value: String::from("Foo album"), }), FrameFlags::default(), ).unwrap(); // New: let frame = Frame::Text(TextInformationFrame::new( FrameId::new("TALB").unwrap(), FrameFlags::default(), TextEncoding::UTF8, String::from("Foo album"), ));
- This makes it easier to validate frame contents, as one can no longer make an
- Renamed
Popularimeter->PopularimeterFrame - Renamed
SynchronizedText->SynchronizedTextFrame
- ID3v2: Disallow 4 character TXXX/WXXX frame descriptions from being converted to
ItemKey(issue) (PR) - MPEG: Durations estimated by bitrate are more accurate (PR)
- MP4:
- WAV: Bitrate calculation is now more accurate (PR)
- MusePack: Overall improved audio properties (PR)
0.19.2 - 2024-04-26
- Length:
impl<T: Length> Truncate for &mut T
0.19.1 - 2024-04-26 (YANKED)
- MP4: All surrounding
freeatoms will be used when writingilsttags (issue) (PR)- Previously, only the
freeatoms immediately surrounding theilstatom were used.
- Previously, only the
0.19.0 - 2024-04-21
- WriteOptions (issue) (PR):
⚠️ Important⚠️ : This update introducesWriteOptionsto allow for finer grained control over how Lofty writes tags. These are best used as global user-configurable options, as most options will not apply to all files. The defaults are set to be as safe as possible, see here.
- Generic Writes (PR):
⚠️ Important⚠️ : This update introducesFileLike, which is a combination of theTruncate+Lengthtraits that allows one to write to more than justFiles. In short,Cursor<Vec<u8>>can now be written to.
- ChannelMask
- Opus:
OpusPropertiesnow contains the channel mask - AAC:
AacPropertiesnow contains the channel mask - Prelude:
lofty::preludemodule to make trait imports easier (PR)
- ID3v2: Ignore empty duplicate frames (PR)
- Some software will apparently write an empty duplicate frame after the actual frame. As the latest frame is the only one that gets preserved, we now check if the frame is empty before replacing.
- Properties:
FilePropertiesandChannelMaskhave been moved from the root to the newlofty::propertiesmodule (PR) - ParseOptions/WriteOptions/GlobalOptions:
⚠️ Important⚠️ : Moved tolofty::config(PR)
- AudioFile/TaggedFileExt/TaggedFile/BoundTaggedFile/FileType:
⚠️ Important⚠️ : Moved tolofty::file(PR)
- Tag:
⚠️ Important⚠️ - The following items have been moved tolofty::tag(PR):TagAccessorTagTypeTagItemItemKeyItemValue
- Probe:
⚠️ Important⚠️ - Moved tolofty::probe(PR):
- Picture:
⚠️ Important⚠️ - The following items have been moved tolofty::picture(PR):PicturePictureTypePictureInformationMimeType
- IFF (PR):
- AIFF:
AIFFTextChunksrenamed toAiffTextChunks - RIFF:
RIFFInfoListrenamed toRiffInfoList
- AIFF:
- Vorbis: Fix panic when reading properties of zero-length files (issue) (PR)
- ID3v2:
- WAV: Length and bitrate values are properly rounded (PR)
- ParseOptions: No longer derives
{PartialOrd, Ord}(PR)
0.18.2 - 2024-01-23
- MP4: Padding for shrinking tags will no longer overwrite unrelated data (PR)
0.18.1 - 2024-01-20 (YANKED)
0.18.0 - 2024-01-12
- MP4: Check if audio streams are DRM protected, exposed as
Mp4Properties::is_drm_protected()(PR) - ID3v2:
- GlobalOptions: Options local to the thread that persist between reads and writes (PR)
- See the docs for more information
- ItemKey:
ItemKey::IntegerBpm(issue) (PR)
- ID3v1: Renamed
GENRES[14]to"R&B"(Previously"Rhythm & Blues") (PR) - MP4: Duration milliseconds are now rounded to the nearest whole number (PR)
- ID3v2:
- Stop erroring on empty frames when not using
ParsingMode::Strict(PR) - Verify contents of flag items (
ItemKey::FlagCompilation,ItemKey::FlagPodcast) (PR) Id3v2Tag::get_text()will now return the raw, unedited string (PR)- Previously, all null separators were replaced with
"/"to make the string easier to display. Now, null separators are only replaced inAccessormethods. It is up to the caller to decide how to handle all other strings.
- Previously, all null separators were replaced with
- Stop erroring on empty frames when not using
- resolve: Custom resolvers will now be checked before the default resolvers (PR)
- MPEG: Up to
max_junk_byteswill now be searched for tags between the start of the file and the first MPEG frame (PR)- This allows us to read and write ID3v2 tags that are preceeded by junk
- ItemKey:
- MP4:
- ID3v2: Support UTF-16 encoded TIPL frames with a single BOM (issue) (PR)
- Speex: Estimate bitrate when the nominal bitrate is not available (PR)
- When no nominal bitrate was provided, the bitrate was previously set to 0. Now we will give an estimate based on the stream length, which may or may not be entirely accurate.
- ItemKey:
ItemKey::InvolvedPeople - MimeType:
MimeType::None,Picturenow stores anOption<MimeType>. - ID3v2:
TextSizeRestrictions::NoneandImageSizeRestrictions::NoneTagRestrictionsnow stores anOption<TextSizeRestrictions>andOption<ImageSizeRestrictions>.
- MPEG:
Emphasis::None,MpegPropertiesnow stores anOption<Emphasis>.
0.17.1 - 2023-11-26
0.17.0 - 2023-11-14
- ParseOptions:
ParseOptions::allocation_limitto change the default allocation limit. (PR) - ID3v2:
Id3v2Tag::genresto handle all the ways genres can be stored inTCONframes. (PR)
- VorbisComments: When converting from
TagtoVorbisComments,ItemKey::Unknowns will be checked for spec compliance. (PR) - ID3v2: Any trailing null terminators will be trimmed when reading Comment, Text, UserText, UserUrl, and UnsynchronizedText frames. (PR)
- Alloc: The default allocation limit for any single tag item is now 16MB. (PR)
- Probe:
Probe::set_file_type()will return theProbeto allow for builder-style usage. (PR)
- MP4: Verify atom identifiers fall within a subset of characters (PR)
- For a multitude of reasons, garbage data can be left at the end of an atom, resulting in Lofty attempting to parse it as another atom definition. As the specification is broad, there is no way for us to say with certainty that an identifier is invalid. Now we unfortunately have to guess the validity based on the commonly known atoms. For this, we follow TagLib's checks.
- ID3v1: No longer error on inputs shorter than 128 bytes (the length of an ID3v1 tag). (PR)
- ID3v2: No longer error on multi-value UTF-16 encoded text frames (issue) (PR)
- MP4:
Ilst::{track_total, disc_number, disc_total}(PR)- These existed prior to the methods on
Accessor. There is no need to keep them around, as they behave the same.
- These existed prior to the methods on
0.16.1 - 2023-10-15
- MP4: Skip unexpected or empty data atoms in ilst (PR)
- It is possible for an
ilstitem to have both emptydataatoms and unexpected (likely vendor-specific) atoms other thandata. These are both cases we can safely ignore unless usingParsingMode::Strict.
- It is possible for an
0.16.0 - 2023-10-01
- ID3v2:
- MP4 (PR):
Atom::into_dataAtom::merge
- OGG: Support for reading "COVERART" fields, an old deprecated image storage format. (issue) (PR)
- ID3v2:
- Tag header parsing errors will be ignored unless using
ParsingMode::Strict(PR) - For spec compliance,
Id3v2Tag::insertwill now check for frames that are only meant to appear in a tag once and remove them. Those frames are: "MCDI", "ETCO", "MLLT", "SYTC", "RVRB", "PCNT", "RBUF", "POSS", "OWNE", "SEEK", and "ASPI". (PR) Id3v2Tag::removewill now take aFrameIdrather than&str(PR)FrameIdnow implementsInto<Cow<'_, str>>, making it possible to use it inFrame::new(PR)Id3v2Taggetters will now use&FrameIdinstead of&strfor IDs (PR)
- Tag header parsing errors will be ignored unless using
- MP4 (PR):
Ilst::removewill now return all of the removed atomsIlst::insert_picturewill now combine all pictures into a singlecovratomIlst::insertwill now merge atoms with the same identifier into a single atom
- FLAC:
- Allow multiple Vorbis Comment blocks when not using
ParsingMode::Strict(PR)- This is not allowed by spec, but is still possible to encounter in the wild. Now we will just take whichever tag happens to be latest in the stream and use it, they will not be merged.
- Allow picture types greater than 255 when not using
ParsingMode::Strict(issue) (PR)- This is not allowed by spec, but has been encountered in the wild. Now we will just cap the picture type at 255.
- Allow multiple Vorbis Comment blocks when not using
- WavPack: Custom sample rates will no longer be overwritten (PR)
- When a custom sample rate (or multiplier) was encountered, it would accidentally be overwritten with 0, causing incorrect duration and bitrate values.
- APE: Reading properties on older files will no longer error (PR)
- Older APE stream versions were not properly handled, leading to incorrect properties and errors.
- ID3v2: Don't expect text frames to be null terminated (issue) (PR)
0.15.0 - 2023-07-11
- ID3v2:
- ParseOptions:
ParseOptions::max_junk_bytes, allowing the parser to sift through junk bytes to find required information, rather than immediately declare a file invalid. (discussion) (PR) - WavPack:
WavPackPropertiesnow contains the channel mask, accessible throughWavPackProperties::channel_mask()(PR) - AIFF:
AiffPropertiesto hold additional AIFF-specific information- AIFC compression types are now exposed through
AiffCompressionType
- ID3v2:
- APE: The default track/disk number is now
0to line up with ID3v2. This is only used whenset_{track, disk}_totalis used without a correspondingset_{track, disk}. - VorbisComments: When writing, items larger than
u32::MAXwill throwErrorKind::TooMuchData, rather than be silently discarded. - AIFF:
AiffFilewill no longer useFileProperties. It now usesAiffProperties.
- APE: Track/Disk number pairs are properly converted when writing (issue) (PR)
- ID3v2: TIPL/TMCL frames will no longer be read as a single terminated string (issue) (PR)
- WavPack: Multichannel files will no longer be marked as mono, supporting up to 4095 channels (PR)
0.14.0 - 2023-06-08
- ParsingMode: A new variant,
BestAttemptwill attempt to fill holes in otherwise valid tag items (PR) - 🎉 Support for Musepack files (issue) (PR)
- Probe: The default
ParsingModeis nowParsingMode::BestAttempt(It was previouslyParsingMode::Strict) - Alloc:
- ID3v2: Removed
id3::util::synchsafe::unsynch_content. This has been replaced with UnsynchronizedStream.
0.13.0 - 2023-05-08
- Tag/ItemValue:
Tag::remove_empty/ItemValue::is_empty(PR) - ItemKey: Variants for MusicBrainz Release group/Artist/Release artist/Work IDs (PR)
- ID3v2:
- VorbisComments:
ItemKey::Barcodemapping (PR)
- ID3v1:
ID3v1Tag->Id3v1Tag - ID3v2:
- FileType/TagType/ItemKey: All variants have been changed to UpperCamelCase (PR)
- MPEG:
MPEGFile->MpegFileMPEGProperties->MpegProperties
- ID3v2: Compressed frames are now properly handled (PR)
- ID3v2:
- All uses of
ID3v2ErrorKind::Otherhave been replaced with concrete errors SyncTextInformationandGEOBInformationhave been flattened into their respective items (PR)
- All uses of
0.12.1 - 2023-04-10
- WAV: Fix division by zero when reading the properties of an empty stream (issue) (PR)
- ID3v2 (PR):
- Export
id3::v2::UniqueFileIdentifierFrame - Export
id3::v2::Popularimeter
- Export
0.12.0 - 2023-04-04
- Properties: Expose channel mask (only supported for WAV and MPEG for now) (PR)
- ItemKey:
InitialKeymapping for Vorbis Comments (PR) - VorbisComments:
VorbisComments::pushto allow for a non-replacing insertion (PR) - Tags:
<Tag>::new()as an alias for<Tag>::default()(PR) - Picture:
Picture::into_data()(PR)
- APE/ID3v1/ID3v2/Tag:
- VorbisComments (PR):
- Keys will now be verified according to spec before insertion
- Getters will now case-insensitively search for keys
TRACKNUMwill now be considered in theAccessor::*trackmethods
- Tags: Method names are more consistent (PR)
- ID3v2:
- MP4 (PR):
- Fix the incorrect size being written for newly created
moov.udta.metaatoms- Previously, the 8 bytes for the size and identifier were not accounted for
- The parser has been further restricted to avoid going out of bounds
- This was only an issue if there was garbage data after the
moovitem and the parser had not yet found themoov.udtaatom.
- This was only an issue if there was garbage data after the
- Fix the incorrect size being written for newly created
- WavPack (PR):
- Fewer errors are suppressed
- Metadata sub-blocks are now properly parsed
- Bitrate calculation will now properly round down
0.11.0 - 2023-01-29
- MP4:
- Vorbis Comments:
- Additional mappings for the
Label,Remixer, andEncodedByItemKeyvariants (PR)
- Additional mappings for the
- ID3v2: A new
id3v2_compression_supportfeature to optionally depend onflate2for decompressing frames - ItemKey:
- New Variants:
AppleXid,Director,Color
- New Variants:
- AudioFile:
AudioFile::save_to{_path}(PR) - Files:
<File>::set_{tag} - FLAC:
FlacProperties- Previously, FLAC files used
FileProperties.FlacPropertieswas added to support getting the MD5 signature of the audio data.
- Previously, FLAC files used
- OGG:
OggPictureStorage- This was added to cover the overlap in functionality between
VorbisCommentsandFlacFilein that they both store(Picture, PictureInformation).
- This was added to cover the overlap in functionality between
- TagExt:
TagExt::len
- MP4:
AtomIdentstores freeform identifiers asCow<str>opposed toString(PR)- This allows freeform identifiers to be constructed in a const context.
- ID3v2:
FrameIDnow usesCow<str>opposed toString(PR) - FLAC:
FlacFilenow stores pictures separately from itsVorbisCommentstag
- Metadata format features (PR):
- All of the format-specific features have been removed, as they served no purpose. They used to bring in optional dependencies, but they have long since been removed.
- Tag: Handling of the
Yeartag has been improved.- Previously, setting a year with
Tag::set_yearrequired aRecordingDate. Now it will check if the format supports theYeartag, and if not, then it will set aRecordingDate.
- Previously, setting a year with
- OGG: Writing of large packets would corrupt the stream (issue) (PR)
0.10.0 - 2022-12-27
- TagExt:
TagExt::contains - Ilst:
AtomData::Boolfor the various flag atoms such ascpil,pcst, etc. - BoundTaggedFile: A
TaggedFilevariant bound to aFilehandle. (issue) (PR)
- Files: Return the removed tag from
<File>::remove(TagType)(PR)- Previously, the only way to remove and take ownership of a tag was through
TaggedFile::take. This was not possible when using a concrete type, such asOpusFile.
- Previously, the only way to remove and take ownership of a tag was through
- TaggedFile: Renamed
TaggedFile::taketoTaggedFile::remove(PR) - lofty_attr: The
lofty_attr::LoftyFilederive proc macro is now exported aslofty::LoftyFile. - TaggedFile: All methods have been split out into a new trait,
TaggedFileExt. (PR) - Accessor: All methods returning string values now return
Cow<str>. (PR)- This is an unfortunate change that needed to be made in order to accommodate the handling of the different possible text separators between ID3v2 versions.
- ID3v2: Support reading of duplicate tags (issue) (PR)
- Previously, if we were reading a file and encountered an ID3v2 tag after having already read one, we would overwrite the last one, losing all of its information. Now we preserve all of the information, overwriting frames as necessary.
- ID3v2: The
'/'character is no longer used as a separator (issue) - MP4: Stopped expecting certain flags for the
gnreatom prior to upgrading it (issue) (PR)
0.9.0 - 2022-10-30
ParseOptions(issue) (PR):⚠️ Important⚠️ : This update introducesParseOptionsto allow for finer grained control over error eagerness and other settings. Previously, when reading a file the only option available wasread_properties, specified with aboolinread_from{_path}. This will now default totrue, and can be overridden when usingProbe.
- 🎉 Support for AAC (ADTS) files (issue) (PR)
- FileProperties:
FileProperties::new - Debug logging via the log crate for exposing recoverable errors.
- Error:
ErrorKind::SizeMismatch
- ID3v2:
- Frame/tag flags with optional additional data are now
Option<T>instead of(bool, T) id3::v2::TextEncodingis now exported aslofty::TextEncoding
- Frame/tag flags with optional additional data are now
read_from{_path}will no longer take aboolfor reading properties, and will do it by default. To change this behavior, you must now useProbe.- FileType:
primary_tag_typewill no longer change its return depending on the enabled features. - lofty_attr: Simplified the
file_typeattribute:- Before, you had to specify custom file types as
#[lofty(file_type = "Custom(\"MyFile\")")]. Now you can simply do#[lofty(file_type = "MyFile")]and it will infer the rest.
- Before, you had to specify custom file types as
- IFF:
WAVandAIFFitems are no longer combined in theiffmodule. They are now separated into their own modules atiff::wavandiff::aiffrespectively.
- lofty_attr: The
#[lofty(always_present)]attribute has been removed, and is now inferred.
0.8.1 - 2022-09-09
- VorbisComments:
VorbisComments::get_all, same asTag::get_strings(issue)
- ID3v2: Handle tag-wide unsynchronisation flag (amberol#235)
- MP3: Stop using partial frame headers (PR)
0.8.0 - 2022-08-10
- A new file resolver system:
- New module:
lofty::resolve - With this, you will be able to create your own
FileTypes, while continuing to use lofty's traditional API. Read the module docs for more info.
- New module:
- A proc macro for file creation:
- With the new
lofty_attrcrate, file creation has been simplified significantly. It is available for both internal and external usage.
- With the new
- ID3v2: Exposed internal functions
id3::v2::util::{synch_u32, unsynch_u32} - MP4:
Atom::push_data
- TaggedFile:
tag{_mut}no longer takes a reference toTagType - ID3v2:
LanguageFrame'slangfield has changed type -String->[u8; 3] - MP3:
- Renamed
lofty::mp3->lofty::mpeg - Renamed
MP3File->MPEGFile - Renamed
MP3Properties->MPEGProperties
- Renamed
- MP4:
Atom::datawill now return all values - Vorbis Comments: Recognize lowercase
METADATA_BLOCK_PICTUREas a picture (issue)
- ID3v2:
ItemKey::InitialKeynow maps toTKEY(PR)
0.7.3 - 2022-07-22
- FileType:
FileType::from_extdetects MP1/MP2 asFileType::MP3, allowing these files to be read withread_from_path/Probe::open. - ItemKey:
ItemKey::{REPLAYGAIN_ALBUM_GAIN, REPLAYGAIN_ALBUM_PEAK, REPLAYGAIN_TRACK_GAIN, REPLAYGAIN_TRACK_PEAK}
- ID3v2:
TXXX/WXXXframes will be stored by their descriptions inID3v2Tag->Tagconversions- Stopped allowing empty strings in
Accessor::set_*
- Tag: The
Accessor::set_*methods will stop falling through, and adding empty strings
0.7.2 - 2022-07-13
This release mostly addresses issues uncovered by fuzzing, thanks to @5225225!
- Tag: The
Accessor::set_*methods will now remove the item when given an empty string
- AIFF/WAV: Stop relying on the file-provided size when reading (Fixes OOM)
- MP3/APE: Stop trusting the lengths of APE tag items (Fixes OOM)
- PictureInformation: Fix potential integer overflow in
{from_jpeg, from_png} - MP4: The parser has received a major facelift, and shouldn't be so eager to allocate or trust user data (Fixes OOM)
- FLAC: Return early when encountering invalid zero-sized blocks
- FLAC/Opus/Vorbis/Speex: Add better length validity checks while reading Vorbis Comments (Fixes OOM)
0.7.1 - 2022-07-08
- Vorbis Comments:
VorbisComments::{pictures, set_picture, remove_picture} - Tag:
Tag::{set_picture, remove_picture} - MP4: Support property reading for files with FLAC audio
- ID3v2:
ID3v2Tagnow derivesEq
0.7.0 - 2022-06-27
- WavPack support
- Accessor:
- The following new accessor methods have been added:
tracktrack_totaldiskdisk_totalyearcomment
- The following new accessor methods have been added:
- Bitrates in properties will be rounded up, similar to FFmpeg and TagLib
- ID3v1: Renamed
Id3v1Tag->ID3v1Tag - ID3v2:
- Insert multi-value frames separately when converting to
Tag- E.g. An artist of "foo/bar/baz" will become 3 different
TagItems withItemKey::TrackArtist
- E.g. An artist of "foo/bar/baz" will become 3 different
- Join multiple artists with "/" during
Tag->Id3v2Tagconversion- Inverse of the previous entry
- Properly capitalized the following:
Id3v2Error->ID3v2ErrorId3v2ErrorKind->ID3v2ErrorKindErrorKind::Id3v2->ErrorKind::ID3v2Id3v2TagFlags->ID3v2TagFlagsId3v2Version->ID3v2VersionId3v2Tag->ID3v2Tag
- Insert multi-value frames separately when converting to
- Properly capitalized the variants of
TagTypeApe->APEId3v1->ID3v1Id3v2->ID3v2Mp4Ilst->MP4ilstRiffInfo->RIFFInfoAiffText->AIFFText
- All types implementing
PartialEqnow implementEq - MP4:
Ilst::track_numberhas been moved to theAccessor::trackimplementation - Tag: Renamed
Tag::get_textstoTag::get_strings - AIFF: Renamed
AiffTextChunks->AIFFTextChunks - WAV: Renamed
RiffInfoList->RIFFInfoList
- AIFF: Fixed division by zero panic during property reading (issue)
- ID3v2: Support decoding UTF-16 T/WXXX frames with missing content BOM (issue)
0.6.3 - 2022-05-18
- MP4:
- Support atoms with multiple values (issue)
Atom::from_collection
- ID3v2: Discard empty frames, rather than error
- APE: Allow empty tag items
- Rather than error on empty items, they will just be discarded
- Pictures: Treat "image/jpg" as
MimeType::Jpeg(PR) - MP3:
- Properly validate the contents of Xing/LAME/VBRI headers (issue)
- A header with any field zeroed out would result in a division by zero panic
- Fix duration estimation for files with Xing headers without the necessary flags
- Properly validate the contents of Xing/LAME/VBRI headers (issue)
- FLAC: Fix property reading of zero-length files (issue)
- Vorbis Comments: Fix reading of vendor strings with invalid mixed UTF-8 and UTF-16 encodings
- ID3v2:
- Fix reading of zero-size tags
- Attempt to read invalid v2 frame IDs in v3 tags
- For some reason, some apps write v2 frame IDs in otherwise valid v3 frames
- Attempt to decode invalid
COMMlanguages
- MP4:
- Fix hang when reading invalid padding (issue)
- If invalid padding was encountered at the end of the file, the reader would get stuck in an infinite loop attempting to read zero size atoms
- Fallback to bitrate calculation from
mdatwhen necessary (issue)- When reading a file that doesn't provide a valid bitrate or duration, a division by zero panic would occur.
Now, it attempts to calculate the bitrate from the
mdatatom.
- When reading a file that doesn't provide a valid bitrate or duration, a division by zero panic would occur.
Now, it attempts to calculate the bitrate from the
- Fix hang when reading invalid padding (issue)
0.6.2 - 2022-04-24
- MP3: Fix panic when reading files with no MPEG frames (issue)
- Attempting to read an MP3 file with
read_properties = truewould result in a panic if the file contained no MPEG frames
- Attempting to read an MP3 file with
0.6.1 - 2022-04-09
- MP3: Fix reading of ID3v2 tags with an extended header
- Restrictions were unnecessarily put on the reader, keeping it from continuing to read into the extended header if it was present
- ID3v2: Fix reading of tags with an extended header
- The size of the extended header was not being subtracted from the total tag size, causing the reading to continue outside the tag boundaries
0.6.0 - 2022-04-05
TagItem::{into_key, into_value, consume}- MP4:
Mp4Codec::MP3 - MP4:
mp4::AudioObjectType- This new type is used in
mp4::Mp4Properties, accessible withMp4Properties::audio_object_type. This provides additional information for the type of audio being dealt with.
- This new type is used in
TagExt::clear- This allows tags to be cleared of any items or pictures, while retaining any flags (if applicable)
- ID3v2: Respect
Id3v2TagFlags::crcwhen writing- Previously, this flag was ignored, but it will now calculate a CRC for the extended header
- ID3v2:
FrameValue::Popularimeter ItemValue::{into_string, into_binary}Tag::take_stringsTaggedFilenow implementsAudioFile
- MP4: Sample rates and channels are now retrieved from the audio specific config (if possible).
If the information is invalid or unavailable, the existing value from the
mp4abox will be used instead. - Vorbis Comments: Support non-PNG/JPEG images in
PictureInformation::from_picture- The method still only supports PNG and JPEG, but rather than error when it encounters an unknown image, it will return
PictureInformation::default
- The method still only supports PNG and JPEG, but rather than error when it encounters an unknown image, it will return
lofty::read_fromwill now wrap theFilein aBufReader- FLAC: FLAC now has its own module at
lofty::flac - ID3v2:
FrameValueis now#[non_exhaustive] TagType::remove_fromnow works for ID3v2 tags in APE and FLAC files- This previously verified that the
FileTypesupported the tag. It now has special exceptions for these formats to allow stripping out these unsupported tags
- This previously verified that the
- MP4: Renamed
AdvisoryRating::NonetoAdvisoryRating::Inoffensive - Renamed
TaggedFile::remove_tagtoTaggedFile::take - Vorbis Comments:
VorbisComments::insert_picturenow accepts a user providedPictureInformation - Vorbis Comments: Rename
VorbisComments::{get_item, insert_item, remove_key}toVorbisComments::{get, insert, remove} - Vorbis Comments:
VorbisComments::removenow returns an iterator over the removed items
- MP4: Non-full
metaatoms are now properly handled.-
It is possible for these to be a regular atom (no version or flags). This information was assumed to be present and would get skipped, which would affect the reading of subsequent atoms.
This behavior has been noticed by:
-
- MP4: Properly search for
sounatom- The search wasn't adding read bytes correctly, but tests passed due to the atom being immediately available. It would attempt to read until it reached an EOF if it managed to make it through multiple iterations.
- FLAC: Support files with an ID3v2 tag
- This will be read only just like APE, but will allow such files to be read
- ID3v2: Fix writing certain proprietary Apple frames
- When writing, frame IDs are verified with their content. The Apple specific frames "MVNM" and "MVIN" were missing,
causing an error if they were written with their proper type (
FrameValue::Text)
- When writing, frame IDs are verified with their content. The Apple specific frames "MVNM" and "MVIN" were missing,
causing an error if they were written with their proper type (
- ID3v2: Stop writing a BOM for
TextEncoding::UTF16BE
0.5.3 - 2022-03-03
0.5.2 - 2022-02-26
- MP4:
Ilst::{atoms, retain}
- ID3v2: The footer flag is written to the tag
- ID3v2: Pictures are written when using
Tag
0.5.1 - 2022-02-21
- MP4: Padding atoms (
free) are used when writing - Opus: Channel count is verified in accordance to the channel mapping family
- MP4:
metaatoms are written correctly
0.5.0 - 2022-02-20
- Support for Speex files
TagExttrait to unify tag behaviordoc_cfgfeature for docs.rs- Fallible allocation with
ErrorKind::Allocto help prevent OOM - New dependency:
cfg-if - MP3: Emphasis struct (
mp3::Emphasis) for use inMp3Properties - ID3v2: Respect the footer flag (
id3::v2::Id3v2TagFlags::footer) when writing - MP4: Constants for all well-known data types (
mp4::constants) - MP4: Support
rtng(Parental advisory) atom, with correspondingmp4::AdvisoryRatingenum
- Added
#[non_exhaustive]toMimeType - Added
#[non_exhaustive]toPictureType - Added
#[non_exhaustive]toMp4Codec - APE: Clarify why ID3v2 is read only
- MP3: No longer error on missing Xing/VBRI header when reading properties
- MP3: Read the entire MPEG frame header, which is exposed in
Mp3Properties AudioFilenow requiresInto<TaggedFile>- MP4: Empty atoms are discarded
- MP4: Variable-size integers are shrunk when writing
- MP4: Panic in
Mp4File::read_from(commit) - WAV/AIFF: Chunk reading now makes use of fallible allocation, preventing OOM
- ID3v2: Text is properly encoded when writing
- ID3v2:
MVNMandMVINframes are now treated as text frames - ID3v2: Text encodings are verified for V2 tags
- MP4:
plIDatom is properly treated as a 64-bit signed integer (issue) - MP4:
rateandrtngnow map to the correctItemKey - MP4: Integer pairs are now written correctly
TagTypeandFileTypeare no longer taken by reference in any method
ErrorKind::BadExtension