C++ library for reading and writing MP4/M4A/AAC (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags

Martchus 965ee4ab4b Adapt tests to recent changes 3 months ago
aac 4ad9ceb68c Fix warning in AacSbrInfo 1 year ago
adts c9e1dde70b Adapt to changes in c++utilities 1 year ago
av1 c9e1dde70b Adapt to changes in c++utilities 1 year ago
avc c9e1dde70b Adapt to changes in c++utilities 1 year ago
avi 5ad00a083c Adapt to changes in c++utilities 1 year ago
doc 602f4f7c8f Improve refs in "Adding new fields" doc 1 year ago
flac c9e1dde70b Adapt to changes in c++utilities 1 year ago
id3 d26e594777 Deprecate 'Year' in favor of 'RecordDate' and 'ReleaseDate', fix handling in ID3v2 3 months ago
ivf c9e1dde70b Adapt to changes in c++utilities 1 year ago
matroska d26e594777 Deprecate 'Year' in favor of 'RecordDate' and 'ReleaseDate', fix handling in ID3v2 3 months ago
mp4 d26e594777 Deprecate 'Year' in favor of 'RecordDate' and 'ReleaseDate', fix handling in ID3v2 3 months ago
mpegaudio 5ad00a083c Adapt to changes in c++utilities 1 year ago
ogg 7043c3d2a9 Don't suppress IO errors when writing files 7 months ago
opus 5ad00a083c Adapt to changes in c++utilities 1 year ago
scripts 0d4d3da41e Add script to update enum comments 3 months ago
testfiles 2772a0c1ad Add MP4 testfile with chapters 1 year ago
tests 965ee4ab4b Adapt tests to recent changes 3 months ago
vorbis d26e594777 Deprecate 'Year' in favor of 'RecordDate' and 'ReleaseDate', fix handling in ID3v2 3 months ago
wav 0c2056c2f9 Refactor WaveFormatHeader::parse() 1 year ago
.gitignore bc306af88e Apply clang-format later 3 years ago
CMakeLists.txt 8f3eae59f1 Add more time-related ID3v2 IDs 3 months ago
LICENSE 2eb5e3172f Initial commit 5 years ago
README.md 736b4caeeb Document handling different types and encodings 1 year ago
abstractattachment.cpp 5ad00a083c Adapt to changes in c++utilities 1 year ago
abstractattachment.h 7efa7a0d5a Adapt to c++utilities v5 1 year ago
abstractchapter.cpp 5ad00a083c Adapt to changes in c++utilities 1 year ago
abstractchapter.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
abstractcontainer.cpp c9e1dde70b Adapt to changes in c++utilities 1 year ago
abstractcontainer.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
abstracttrack.cpp 6e9b39726d Add conversion from ISO-639-2/B codes to language names 11 months ago
abstracttrack.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
aspectratio.cpp 7efa7a0d5a Adapt to c++utilities v5 1 year ago
aspectratio.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
backuphelper.cpp 7043c3d2a9 Don't suppress IO errors when writing files 7 months ago
backuphelper.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
basicfileinfo.cpp 5ad00a083c Adapt to changes in c++utilities 1 year ago
basicfileinfo.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
caseinsensitivecomparer.h c0336ed4bb Apply clang-format 2 years ago
diagnostics.cpp d64084ec78 Refactor formatting list of values 2 years ago
diagnostics.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
exceptions.cpp bd7d5b00d7 Use noexcept directly 1 year ago
exceptions.h bd7d5b00d7 Use noexcept directly 1 year ago
fieldbasedtag.h e75a8d25c5 Adjust values()/setValues() to handle multiple values per text frame 2 years ago
genericcontainer.h 7efa7a0d5a Adapt to c++utilities v5 1 year ago
genericfileelement.h 40a96c1fd4 Use 64 KiB buffer to copy file elements 7 months ago
generictagfield.h af4b43ff79 Replace typedef with using 2 years ago
global.h c9e1dde70b Adapt to changes in c++utilities 1 year ago
language.cpp 6e9b39726d Add conversion from ISO-639-2/B codes to language names 11 months ago
language.h 6e9b39726d Add conversion from ISO-639-2/B codes to language names 11 months ago
languages.csv 6e9b39726d Add conversion from ISO-639-2/B codes to language names 11 months ago
localeawarestring.cpp c0336ed4bb Apply clang-format 2 years ago
localeawarestring.h c0336ed4bb Apply clang-format 2 years ago
margin.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
mediafileinfo.cpp 7043c3d2a9 Don't suppress IO errors when writing files 7 months ago
mediafileinfo.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
mediaformat.cpp 66895e8e2c Distinguish text and "meta" tracks in MP4 1 year ago
mediaformat.h 66895e8e2c Distinguish text and "meta" tracks in MP4 1 year ago
positioninset.h c9e1dde70b Adapt to changes in c++utilities 1 year ago
progressfeedback.cpp 27d3acad9a Document progress feedback 2 years ago
progressfeedback.h 7efa7a0d5a Adapt to c++utilities v5 1 year ago
settings.h 85eb71cd20 Use helper for flag enum from c++utilities 11 months ago
signature.cpp 5ad00a083c Adapt to changes in c++utilities 1 year ago
signature.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
size.cpp c0336ed4bb Apply clang-format 2 years ago
size.h 5ad00a083c Adapt to changes in c++utilities 1 year ago
tag.cpp 7d709ce9af Add Tag::supportsMultipleValues() 2 years ago
tag.h d26e594777 Deprecate 'Year' in favor of 'RecordDate' and 'ReleaseDate', fix handling in ID3v2 3 months ago
tagtarget.cpp 5ad00a083c Adapt to changes in c++utilities 1 year ago
tagtarget.h 7efa7a0d5a Adapt to c++utilities v5 1 year ago
tagvalue.cpp 44fea6c8c2 Omit default components when formatting date time 3 months ago
tagvalue.h 13a87b473d Improve documentation 3 months ago

README.md

Tag Parser

C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags.

Supported formats

The tag library can read and write the following tag formats:

  • iTunes-style MP4/M4A tags (MP4-DASH is supported)
  • ID3v1 and ID3v2 tags
    • conversion between ID3v1 and different versions of ID3v2 is possible
  • Vorbis, Opus and FLAC comments in Ogg streams
    • cover art via "METADATA_BLOCK_PICTURE" is supported
  • Vorbis comments and "METADATA_BLOCK_PICTURE" in raw FLAC streams
  • Matroska/WebM tags and attachments

File layout options

Tag position

The library allows you to choose whether tags should be placed at the beginning or at the end of an MP4/Matroska file.

Padding

Padding allows adding additional tag information without rewriting the entire file or appending the tag. Usage of padding can be configured:

  • minimum/maximum padding: The file is rewritten if the padding would fall below/exceed the specifed limits.
  • preferred padding: If the file needs to be rewritten the preferred padding is used.

Default value for minimum and maximum padding is zero. Hence the library will almost always have to rewrite the entire file to apply changes. To prevent this, set at least the maximum padding to a higher value.

It is also possible to force rewriting the entire file always.

Taking advantage of padding is currently not supported when dealing with Ogg streams (it is supported when dealing with raw FLAC streams).

Additional features

The library can also display technical information such as the ID, format, language, bitrate, duration, size, timestamps, sampling frequency, FPS and other information of the tracks.

It also allows to inspect and validate the element structure of MP4 and Matroska files.

Text encoding, Unicode support

The library is aware of different text encodings and can convert between different encodings using iconv.

Windows specific

A workaround to support filenames containing non-ASCII characters (despite the lack of an UTF-8 supporting std::fstream under Windows) can be enabled by adding -DUSE_NATIVE_FILE_BUFFER=ON to the CMake arguments when building c++utilities. It is not sufficient to specify this option only when building tagparser.

Usage

This example shows how to read and write tag fields in a format-independent way:

#include <tagparser/mediafileinfo.h>
#include <tagparser/diagnostics.h>

// create a MediaFileInfo for high-level access to overall functionality of the library
TagParser::MediaFileInfo fileInfo;
// create container for errors, warnings, etc.
Diagnostics diag;

// open file (might throw ios_base::failure)
fileInfo.setPath("/path/to/some/file");
fileInfo.open();
// parse tags
// (might throw exception derived from TagParser::Failure for fatal parsing error or ios_base::failure for IO errors)
fileInfo.parseTags(diag);

// get first tag as an object derived from the Tag class
auto tag = fileInfo.tags().at(0);
// extract title and convert it to UTF-8 std::string
// (toString() might throw ConversionException)
auto title = tag->value(TagParser::KnownField::Title).toString(TagParser::TagTextEncoding::Utf8);

// change album using an encoding suitable for the tag format
tag->setValue(TagParser::KnownField::Album, TagParser::TagValue("some UTF-8 string", TagParser::TagTextEncoding::Utf8, tag->proposedTextEncoding()));

// create progress
TagParser::AbortableProgressFeedback progress([callback for status update], [callback for percentage-only updates]);

// apply changes to the file on disk
// (might throw exception derived from TagParser::Failure for fatal processing error or ios_base::failure for IO errors)
fileInfo.applyChanges(diag, progress);

Summary

  • The most important class is TagParser::MediaFileInfo providing access to everything else.
  • IO errors are propagated via standard std::ios_base::failure.
  • Fatal processing errors are propagated by throwing a class derived from TagParser::Failure.
  • All operations which might generate warnings, non-fatal errors, ... take a TagParser::Diagnostics object to store those messages.
  • All operations which can be aborted or provide progress feedback take a TagParser::AbortableProgressFeedback object for callbacks and aborting.
  • Field values are stored using TagParser::TagValue objects. Those objects erase the actual type similar to QVariant from the Qt framework. The documentation of TagParser::TagValue covers how different types and encodings are handled.

Further documentation

For more examples check out the command line interface of Tag Editor. API documentation can be generated using Doxygen with make tagparser_apidoc.

Bugs, stability

Bugs can be reported on GitHub.

It is recommend to create backups before editing because I can not test whether the library works with all kinds of files. (When forcing rewrite a backup is always created.)

Build instructions

The tagparser library depends on c++utilities and is built in the same way. It also depends on zlib. For checking integrity of testfiles, the OpenSSL crypto library is required.

TODOs

  • Support more formats (EXIF, PDF metadata, Theora, ...)
  • Support adding cue-sheet to FLAC files

More TODOs are tracked in the issue section at GitHub.