2015-08-16 23:39:42 +02:00
|
|
|
# Tag Parser
|
2016-05-16 20:56:53 +02:00
|
|
|
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags.
|
2015-05-19 22:53:17 +02:00
|
|
|
|
2015-06-08 22:04:24 +02:00
|
|
|
## Supported formats
|
|
|
|
The tag library can read and write the following tag formats:
|
2018-03-06 22:41:21 +01:00
|
|
|
|
|
|
|
* 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
|
2015-06-08 22:04:24 +02:00
|
|
|
|
2015-12-22 23:54:35 +01:00
|
|
|
## 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:
|
2018-03-06 22:41:21 +01:00
|
|
|
* 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.
|
2015-12-22 23:54:35 +01:00
|
|
|
|
2016-11-18 17:09:26 +01:00
|
|
|
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.
|
2015-12-22 23:54:35 +01:00
|
|
|
|
2016-09-10 17:17:32 +02:00
|
|
|
Taking advantage of padding is currently not supported when dealing with Ogg streams (it is supported when dealing with raw FLAC streams).
|
2016-01-17 21:38:27 +01:00
|
|
|
|
2015-12-22 23:54:35 +01:00
|
|
|
## Additional features
|
2015-08-16 23:36:49 +02:00
|
|
|
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.
|
|
|
|
|
2015-06-08 22:04:24 +02:00
|
|
|
It also allows to inspect and validate the element structure of MP4 and Matroska files.
|
|
|
|
|
2015-12-27 18:06:01 +01:00
|
|
|
## Text encoding, Unicode support
|
2016-08-04 00:16:19 +02:00
|
|
|
The library is aware of different text encodings and can convert between different encodings using iconv.
|
2015-12-27 18:06:01 +01:00
|
|
|
|
2017-08-21 01:29:32 +02:00
|
|
|
### 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`.
|
|
|
|
|
2015-12-22 23:54:35 +01:00
|
|
|
## Usage
|
2018-03-06 23:50:40 +01:00
|
|
|
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
|
2019-06-01 23:20:01 +02:00
|
|
|
TagParser::MediaFileInfo fileInfo;
|
2018-03-06 23:50:40 +01:00
|
|
|
// 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
|
2019-06-01 23:20:01 +02:00
|
|
|
// (might throw exception derived from TagParser::Failure for fatal parsing error or ios_base::failure for IO errors)
|
2018-03-06 23:50:40 +01:00
|
|
|
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)
|
2019-06-01 23:20:01 +02:00
|
|
|
auto title = tag->value(TagParser::KnownField::Title).toString(TagParser::TagTextEncoding::Utf8);
|
2018-03-06 23:50:40 +01:00
|
|
|
|
|
|
|
// change album using an encoding suitable for the tag format
|
2019-06-01 23:20:01 +02:00
|
|
|
tag->setValue(TagParser::KnownField::Album, TagParser::TagValue("some UTF-8 string", TagParser::TagTextEncoding::Utf8, tag->proposedTextEncoding()));
|
2018-03-06 23:50:40 +01:00
|
|
|
|
|
|
|
// create progress
|
2019-06-01 23:20:01 +02:00
|
|
|
TagParser::AbortableProgressFeedback progress([callback for status update], [callback for percentage-only updates]);
|
2018-03-06 23:50:40 +01:00
|
|
|
|
|
|
|
// apply changes to the file on disk
|
2019-06-01 23:20:01 +02:00
|
|
|
// (might throw exception derived from TagParser::Failure for fatal processing error or ios_base::failure for IO errors)
|
2018-03-06 23:50:40 +01:00
|
|
|
fileInfo.applyChanges(diag, progress);
|
|
|
|
```
|
|
|
|
|
|
|
|
### Summary
|
2019-06-01 23:20:01 +02:00
|
|
|
* The most important class is `TagParser::MediaFileInfo` providing access to everything else.
|
2018-03-06 23:50:40 +01:00
|
|
|
* IO errors are propagated via standard `std::ios_base::failure`.
|
2019-06-01 23:20:01 +02:00
|
|
|
* 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
|
2018-03-06 23:50:40 +01:00
|
|
|
those messages.
|
2019-06-01 23:20:01 +02:00
|
|
|
* All operations which can be aborted or provide progress feedback take a `TagParser::AbortableProgressFeedback` object
|
2018-03-06 23:50:40 +01:00
|
|
|
for callbacks and aborting.
|
2019-06-01 23:20:01 +02:00
|
|
|
* 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.
|
2018-03-06 23:50:40 +01:00
|
|
|
|
|
|
|
### Further documentation
|
|
|
|
For more examples check out the command line interface of [Tag Editor](https://github.com/Martchus/tageditor).
|
2016-09-14 20:02:08 +02:00
|
|
|
API documentation can be generated using Doxygen with `make tagparser_apidoc`.
|
2015-06-08 22:04:24 +02:00
|
|
|
|
2015-12-27 18:06:01 +01:00
|
|
|
## Bugs, stability
|
2019-06-01 23:20:01 +02:00
|
|
|
Bugs can be reported on GitHub.
|
|
|
|
|
2017-05-24 20:00:44 +02:00
|
|
|
It is recommend to create backups before editing because I can not test whether the library
|
2019-06-01 23:20:01 +02:00
|
|
|
works with all kinds of files. (When forcing rewrite a backup is always created.)
|
2015-12-27 18:06:01 +01:00
|
|
|
|
2015-05-19 22:53:17 +02:00
|
|
|
## Build instructions
|
2017-05-06 08:59:57 +02:00
|
|
|
The tagparser library depends on [c++utilities](https://github.com/Martchus/cpp-utilities) and is built
|
|
|
|
in the same way.
|
2020-12-04 18:06:42 +01:00
|
|
|
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.
|
2015-08-16 23:39:42 +02:00
|
|
|
|
2018-03-06 22:41:21 +01:00
|
|
|
## 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](https://github.com/Martchus/tagparser/issues).
|