Capabilities, frame access, and save policies
Formats and native tags
The common property interface is useful when the same operation should work across formats. Use the native tag classes when you need a feature that has no common representation, or when the exact tag family and output version matter. This is the same division used in the upstream TagLib introduction.
Format support
All formats below support metadata reads. Text keys and picture roles describe the high-level editing API; valid values remain subject to the native format’s restrictions.
| Format / container | Writable text keys | Artwork roles |
|---|---|---|
| MPEG / MP3, ADTS AAC | Common and custom | All named roles |
| FLAC | Common and custom | All named roles |
| Ogg Vorbis, Opus, Speex, FLAC | Common and custom | All named roles |
| MP4 / M4A | Common and custom | Other |
| ASF / WMA | Mapped keys | All named roles |
| WAV, AIFF | Common and custom | All named roles |
| APE, Musepack, WavPack | Common and custom | Front and back cover |
| TrueAudio, DSF, DSDIFF | Common and custom | All named roles |
| Matroska / WebM | Common and custom | Other |
| MOD, S3M, IT | Title, comment | None |
| XM | Title, comment, tracker name | None |
| Shorten | Read only | None |
Query capabilities
var format = TagLib.read(Path.of("song.flac"), ReadOptions.TAGS_ONLY).format();
boolean albumArtist = format.supportsProperty(PropertyKey.ALBUM_ARTIST);
boolean customFields = format.supportsCustomProperties();
boolean frontCover = format.supportsPictureType(PictureType.FRONT_COVER);
The same queries can be called on an enum constant without a file, for example Format.MP4. supportedPropertyKeys()
lists known writable names, and supportedPictureTypes() lists named roles. For containers with custom
fields, the known-key list is not exhaustive. A supported key may be stored as custom text rather than a dedicated
native field.
Read native ID3v2 frames
try (var file = new cz.skyba.taglib.mpeg.MpegFile(Path.of("song.mp3"))) {
var tag = file.id3v2Tag();
if (tag != null) {
for (var frame : tag.frameList("TIT2")) {
System.out.println(frame);
}
}
}
id3v2Tag() returns the live tag or null when no object exists. getOrCreateId3v2Tag()
creates an empty tag in memory if needed. It does not write the file. Textual frame IDs use three or four
uppercase ASCII letters/digits. frameList is a read-only live view, not a detached copy of frames. To
delete a family of frames, use removeFrames("TIT2") and save the file explicitly.
Live native objects belong to their file session. Keep the file open while using them, and use explicit copying
APIs when you need an independent mutable object. Do not assume the snapshot ownership rules of AudioMetadata
apply to native tags.
Look up an MP4 item
try (var file = new cz.skyba.taglib.mp4.Mp4File(Path.of("song.m4a"))) {
var title = file.tag().findItem("©nam");
title.ifPresent(item -> System.out.println(item.toStringList()));
}
findItem returns an Optional containing the live stored item, including a stored void
item. Empty means the key is absent. The older item accessor is deprecated because its detached void
result cannot distinguish absence from a stored void item. Use the property map for ordinary title/artist edits;
native item access is useful for atom-specific metadata.
Tag families and save options
A file can contain more than one tag family. An MP3 can have ID3v2, ID3v1, and APE tags; WAV can have ID3v2 and RIFF INFO. The common interface hides that distinction when reading. A format-specific save makes you choose what to write and what to do with unselected tags.
| Option | Effect |
|---|---|
| Tag set | Selects the in-memory tag families to write. Selecting a family does not make an empty tag contain data. |
StripTags.STRIP_NONE |
Preserves unselected tag families in storage. |
StripTags.STRIP_OTHERS |
Removes unselected tag families from storage. This is a deletion policy. |
Tag.Version.V3 / V4 |
Selects the ID3v2 output version. Version conversion can change how fields are represented. |
DuplicateTags.DUPLICATE |
Allows MPEG saving to fill missing common fields between participating ID3 tags. |
DuplicateTags.DO_NOT_DUPLICATE |
Disables that common-field copying; it does not delete a tag. |
Default MPEG saves select all supported families, use ID3v2.4, and enable common-field duplication. Default WAV
saves select ID3v2 and INFO and use ID3v2.4. In both, unselected tags use STRIP_OTHERS; selected
empty tags are removed. WAV’s BEXT and iXML edits are saved independently of its ID3v2/INFO selection.
Save an ID3v2.3 tag while retaining other families
try (var file = new cz.skyba.taglib.mpeg.MpegFile(Path.of("song.mp3"))) {
file.getOrCreateId3v2Tag().setTitle("New title");
var options = new cz.skyba.taglib.mpeg.MpegSaveOptions(
java.util.Set.of(cz.skyba.taglib.mpeg.MpegFile.TagType.ID3V2),
FileBase.StripTags.STRIP_NONE,
cz.skyba.taglib.id3.v2.Tag.Version.V3,
FileBase.DuplicateTags.DO_NOT_DUPLICATE);
file.save(options);
}
This writes the ID3v2 tag and leaves other tag families in storage. It does not synchronize their titles. A player reading ID3v1 instead of ID3v2 may therefore show the old title. Decide whether your application wants to preserve, synchronize, or remove those other tags before choosing a policy.
See the upstream MPEG file documentation for the corresponding C++ concepts. Java uses typed option records and enums rather than the C++ bit mask.