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

Martchus d812e0d3ae Detect VobSub within MP4 1 week ago
aac edad4e19ab Fix misc warnings 7 months ago
adts 9361e0bc13 Use constexpr where possible 8 months ago
av1 534cb2a6f7 Prepare parsing AV1 config 6 months ago
avc 3332314eb6 Prepare logging errors when parsing AVC config 6 months ago
avi 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
doc 602f4f7c8f Improve refs in "Adding new fields" doc 2 months ago
flac e81c6bb169 Implement small TODOs for v8 8 months ago
id3 dbce74444a Deprecate unused methods in Id3v2Frame 1 month ago
ivf c4adad4297 Detect AV1 in IVF stream 7 months ago
matroska 3332314eb6 Prepare logging errors when parsing AVC config 6 months ago
mp4 d812e0d3ae Detect VobSub within MP4 1 week ago
mpegaudio f1a3f5cbce Fix warnings in MpegAudioFrame 7 months ago
ogg 59d2156165 Add tagType and tagName to OggVorbisComment 2 months ago
opus 9361e0bc13 Use constexpr where possible 8 months ago
scripts e9526225ea Add testfile for AV1 in MP4 4 months ago
testfiles 3924b5f56b Test more methods of MediaFileInfo 1 year ago
tests 296e5d11b6 Fix TagValue::toStandardGenreIndex() for empty genre index 1 month ago
vorbis 6afcd0f8d3 Support album artist and fix/improve grouping 2 months ago
wav 3c06590085 Detect float PCM in WAVE container 2 months ago
.gitignore bc306af88e Apply clang-format later 1 year ago
CMakeLists.txt 0452b42bfc Add MediaFileInfo::overallAverageBitrate() 1 week ago
LICENSE 2eb5e3172f Initial commit 3 years ago
README.md 88edd43f8c Document usage, especially error handling 1 year ago
abstractattachment.cpp dff3c0ec70 Fix compile error due to incomplete MediaFileInfo 5 months ago
abstractattachment.h dff3c0ec70 Fix compile error due to incomplete MediaFileInfo 5 months ago
abstractchapter.cpp 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
abstractchapter.h c0336ed4bb Apply clang-format 1 year ago
abstractcontainer.cpp 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
abstractcontainer.h b47705ff81 Refactor MediaFileInfo::createAppropriateTags() 1 year ago
abstracttrack.cpp 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
abstracttrack.h c4adad4297 Detect AV1 in IVF stream 7 months ago
aspectratio.cpp 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
aspectratio.h 54174f014a Add AspectRatio::toString() 7 months ago
backuphelper.cpp a2ff0f418f Fix typo occured -> occurred 7 months ago
backuphelper.h a87ad5f5ec Don't use global variable for backup directory 8 months ago
basicfileinfo.cpp 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
basicfileinfo.h c0336ed4bb Apply clang-format 1 year ago
caseinsensitivecomparer.h c0336ed4bb Apply clang-format 1 year ago
diagnostics.cpp d64084ec78 Refactor formatting list of values 8 months ago
diagnostics.h 1a9f71a3ea Remove DiagPtr 8 months ago
exceptions.cpp bd7d5b00d7 Use noexcept directly 4 weeks ago
exceptions.h bd7d5b00d7 Use noexcept directly 4 weeks ago
fieldbasedtag.h e75a8d25c5 Adjust values()/setValues() to handle multiple values per text frame 8 months ago
genericcontainer.h af4b43ff79 Replace typedef with using 8 months ago
genericfileelement.h af4b43ff79 Replace typedef with using 8 months ago
generictagfield.h af4b43ff79 Replace typedef with using 8 months ago
global.h bc306af88e Apply clang-format later 1 year ago
localeawarestring.cpp c0336ed4bb Apply clang-format 1 year ago
localeawarestring.h c0336ed4bb Apply clang-format 1 year ago
margin.h c0336ed4bb Apply clang-format 1 year ago
mediafileinfo.cpp 0452b42bfc Add MediaFileInfo::overallAverageBitrate() 1 week ago
mediafileinfo.h 0452b42bfc Add MediaFileInfo::overallAverageBitrate() 1 week ago
mediaformat.cpp 1dc8fb4839 Detect AV1 in MKV 7 months ago
mediaformat.h edad4e19ab Fix misc warnings 7 months ago
positioninset.h 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
progressfeedback.cpp 27d3acad9a Document progress feedback 9 months ago
progressfeedback.h 27d3acad9a Document progress feedback 9 months ago
settings.h 3e85eba00f Apply clang-format 1 year ago
signature.cpp f99f22f270 Detect MIDI files 6 months ago
signature.h f99f22f270 Detect MIDI files 6 months ago
size.cpp c0336ed4bb Apply clang-format 1 year ago
size.h c0336ed4bb Apply clang-format 1 year ago
tag.cpp 7d709ce9af Add Tag::supportsMultipleValues() 8 months ago
tag.h 3a35ce4b16 Don't treat synchronized lyrics as regular text field 1 month ago
tagtarget.cpp 3265e0bea4 Fix documentation which was still using the old namespace 9 months ago
tagtarget.h af4b43ff79 Replace typedef with using 8 months ago
tagvalue.cpp 296e5d11b6 Fix TagValue::toStandardGenreIndex() for empty genre index 1 month ago
tagvalue.h e81c6bb169 Implement small TODOs for v8 8 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>

using namespace TagParser;

// create a MediaFileInfo for high-level access to overall functionality of the library
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 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(KnownField::Title).toString(TagTextEncoding::Utf8);

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

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

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

Summary

  • So the most important class is 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 Failure.
  • All operations which might generate warnings, non-fatal errors, ... take a Diagnostics object to store those messages.
  • All operations which can be aborted or provide progress feedback take a AbortableProgressFeedback object for callbacks and aborting.
  • Field values are stored using TagValue objects. Those objects erase the actual type similar to QVariant from the Qt framework.

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

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.