|
7 days ago | |
---|---|---|
aac | 4 weeks ago | |
adts | 4 weeks ago | |
av1 | 2 years ago | |
avc | 5 months ago | |
avi | 2 years ago | |
cmake/scripts | 3 months ago | |
doc | 2 years ago | |
flac | 4 weeks ago | |
id3 | 4 weeks ago | |
ivf | 2 months ago | |
matroska | 1 week ago | |
mp4 | 7 days ago | |
mpegaudio | 4 weeks ago | |
ogg | 4 weeks ago | |
opus | 2 years ago | |
scripts | 12 months ago | |
testfiles | 2 years ago | |
tests | 4 weeks ago | |
vorbis | 4 weeks ago | |
wav | 4 weeks ago | |
.gitignore | 4 years ago | |
CMakeLists.txt | 3 months ago | |
LICENSE | 6 years ago | |
README.md | 2 months ago | |
abstractattachment.cpp | 4 weeks ago | |
abstractattachment.h | 4 weeks ago | |
abstractchapter.cpp | 2 months ago | |
abstractchapter.h | 2 months ago | |
abstractcontainer.cpp | 2 months ago | |
abstractcontainer.h | 2 months ago | |
abstracttrack.cpp | 1 week ago | |
abstracttrack.h | 2 months ago | |
aspectratio.cpp | 2 years ago | |
aspectratio.h | 4 months ago | |
backuphelper.cpp | 3 months ago | |
backuphelper.h | 2 years ago | |
basicfileinfo.cpp | 3 months ago | |
basicfileinfo.h | 3 months ago | |
caseinsensitivecomparer.h | 3 months ago | |
diagnostics.cpp | 3 months ago | |
diagnostics.h | 3 months ago | |
exceptions.cpp | 5 months ago | |
exceptions.h | 2 years ago | |
fieldbasedtag.h | 4 weeks ago | |
genericcontainer.h | 4 weeks ago | |
genericfileelement.h | 4 weeks ago | |
generictagfield.h | 3 months ago | |
global.h | 2 years ago | |
localeawarestring.cpp | 3 years ago | |
localeawarestring.h | 4 months ago | |
localehelper.cpp | 3 months ago | |
localehelper.h | 3 months ago | |
margin.h | 4 months ago | |
mediafileinfo.cpp | 4 weeks ago | |
mediafileinfo.h | 2 months ago | |
mediaformat.cpp | 3 months ago | |
mediaformat.h | 3 months ago | |
positioninset.h | 4 months ago | |
progressfeedback.cpp | 3 years ago | |
progressfeedback.h | 2 months ago | |
settings.h | 2 years ago | |
signature.cpp | 3 months ago | |
signature.h | 3 months ago | |
size.cpp | 2 months ago | |
size.h | 3 months ago | |
tag.cpp | 4 weeks ago | |
tag.h | 4 weeks ago | |
tagtarget.cpp | 3 months ago | |
tagtarget.h | 3 months ago | |
tagvalue.cpp | 4 weeks ago | |
tagvalue.h | 3 months ago |
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags.
The tag library can read and write the following tag formats:
The library allows you to choose whether tags should be placed at the beginning or at the end of an MP4/Matroska file.
Padding allows adding additional tag information without rewriting the entire file or appending the tag. Usage of padding can be configured:
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).
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.
The library is aware of different text encodings and can convert between different encodings using iconv.
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
.
This example shows how to read and write tag fields in a format-independent way:
#include <tagparser/mediafileinfo.h>
#include <tagparser/diagnostics.h>
#include <tagparser/progressfeedback.h>
// create a MediaFileInfo for high-level access to overall functionality of the library
auto fileInfo = MediaFileInfo();
// create container for errors, warnings, etc.
auto diag = Diagnostics();
// create handle to abort gracefully and get feedback during during long operations
auto progress = AbortableProgressFeedback([callback for status update], [callback for percentage-only updates]);
// open file (might throw ios_base::failure)
fileInfo.setPath("/path/to/some/file");
fileInfo.open();
// parse container format, tags, attachments and/or chapters as needed
// notes:
// - These functions might throw exceptions derived from ios_base::failure for IO errors and
// populate diag with possibly critical parsing messages you definitely want to check in production
// code.
// - Parsing a file can be expensive if the file is big or the disk IO is slow. You might want to
// run it in a separate thread.
// - At this point the parser does not make much use of the progress object.
fileInfo.parseContainerFormat(diag, progress);
fileInfo.parseTags(diag, progress);
fileInfo.parseAttachments(diag, progress);
fileInfo.parseChapters(diag, progress);
fileInfo.parseEverything(diag, progress); // just use that one if you want all over the above
// get tag as an object derived from the Tag class
// notes:
// - In real code you might want to check how many tags are assigned or use
// fileInfo.createAppropriateTags(…) to create tags as needed.
auto tag = fileInfo.tags().at(0);
// extract a field value and convert it to UTF-8 std::string (toString() might throw ConversionException)
#include <tagparser/tag.h>
#include <tagparser/tagvalue.h>
auto title = tag->value(TagParser::KnownField::Title).toString(TagParser::TagTextEncoding::Utf8);
// change a field value using an encoding suitable for the tag format
tag->setValue(KnownField::Album, TagValue("some UTF-8 string", TagTextEncoding::Utf8, tag->proposedTextEncoding()));
// get/remove/create attachments
#include <tagparser/abstractattachment.h>
if (auto *const container = fileInfo.container()) {
for (auto i = 0, count = container->attachmentCount(); i != count; ++i) {
auto attachment = container->attachment(i);
if (attachment->mimeType() == "image/jpeg") {
attachment->setIgnored(true); // remove existing attachment
}
}
// create new attachment
auto attachment = container->createAttachment();
attachment->setName("cover.jpg");
attachment->setFile(cover, diag);
}
// apply changes to the file on disk
// notes:
// - Might throw exception derived from TagParser::Failure for fatal processing error or ios_base::failure
// for IO errors.
// - Applying changes can be expensive if the file is big or the disk IO is slow. You might want to
// run it in a separate thread.
// - Use progress.tryToAbort() from another thread or an interrupt handler to abort gracefully without leaving
// the file in an inconsistent state.
// - Be sure everyting has been parsed before as the library needs to be aware of the whole file structure.
fileInfo.parseEverything(diag, progress);
fileInfo.applyChanges(diag, progress);
TagParser::MediaFileInfo
providing access to everything else.std::ios_base::failure
.TagParser::Failure
.TagParser::Diagnostics
object to store
those messages.TagParser::AbortableProgressFeedback
object for callbacks and aborting.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.For more examples check out the command line interface of Tag Editor.
API documentation can be generated using Doxygen with make tagparser_apidoc
.
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.)
The tagparser library depends on c++utilities and is built in the same way. It also depends on zlib, iso-codes and requires at least CMake 3.19. For checking integrity of testfiles, the OpenSSL crypto library is required.
More TODOs are tracked in the issue section at GitHub.