MediaFile: elegant audio file tagging ===================================== MediaFile is a simple interface to the metadata tags for many audio file formats. It wraps Mutagen_, a high-quality library for low-level tag manipulation, with a high-level, format-independent interface for a common set of tags. It currently supports MP3 files (ID3 tags), AAC files (as tagged by iTunes) as well as FLAC, Ogg, Monkey's Audio, WavPack, and Musepack. If a tag does not exist, MediaFile will return ``None`` instead of throwing an exception. .. _mutagen: https://github.com/quodlibet/mutagen .. toctree:: :maxdepth: 2 :hidden: changelog Supported Metadata Fields ------------------------- The metadata schema is generally based on MusicBrainz' schema with similar naming. MediaFile supports: - basic fields like ``title``, ``album``, ``artist`` and ``albumartist``, - sorting variants like ``albumartist_sort`` and ``composer_sort``, - plural/list variants like ``artists``, ``albumartists``, ``lyricists``, ``composers``, ``arrangers`` and ``remixers``, - identifiers like ``asin``, ``isrc`` or ``mb_releasegroupid``, - dates like the release ``year``, ``month`` and ``day`` with convenience wrapper ``date``, - detailed metadata like ``language`` or ``media``, - ``lyrics``, ``copyright``, ``url`` - calculated metadata like ``bpm`` (beats per minute) and ``r128_track_gain`` (ReplayGain), - embedded images (e.g. album art), - file metadata like ``samplerate``, ``bitdepth``, ``channels``, ``bitrate``, ``bitrate_mode``, ``encoder_info``, ``encoder_settings`` and ``length``. Compatibility ------------- The ID3 and MPEG-4 test cases were created with iTunes and the FLAC and Ogg test cases were created (mostly) with MediaRage_. The Monkey's Audio tags were mainly fabricated using the open-source Tag_. Thus, MediaFile's tag support most closely aligns with those three applications. Some open questions remain about how to most compatibly tag files. In particular, some fields MediaFile supports don't seem standardized among FLAC/Ogg taggers: - ``grouping`` and ``lyrics``: couldn't find anyone who supports these in a cursory search; MediaFile uses the keys ``grouping`` and ``lyrics`` - ``tracktotal`` and ``disctotal``: we use the keys ``tracktotal``, ``totaltracks``, and ``trackc`` all to mean the same thing - ``year``: this field appears both as a part of the ``date`` field and on its own using some taggers; both are supported For fields that have multiple possible storage keys, MediaFile optimizes for interoperability: it accepts _any_ of the possible storage keys and writes _all_ of them. This may result in duplicated information in the tags, but it ensures that other players with slightly divergent opinions on tag names will all be able to interact with beets_. Images (album art) are stored in the standard ways for ID3 and MPEG-4. For all other formats, images are stored with the `METADATA_BLOCK_PICTURE standard`_ from Vorbis Comments. .. _beets: https://beets.io .. _mediarage: https://www.chaoticsoftware.com/ProductPages/MediaRage.html .. _metadata_block_picture standard: https://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE .. _tag: https://www.feisty-dog.com/tag .. currentmodule:: mediafile MediaFile Class --------------- .. autoclass:: MediaFile .. automethod:: __init__ .. automethod:: fields .. automethod:: readable_fields .. automethod:: save .. automethod:: update Exceptions ---------- .. autoclass:: UnreadableFileError .. autoclass:: FileTypeError .. autoclass:: MutagenError Internals --------- .. autoclass:: MediaField .. automethod:: __init__ .. autoclass:: StorageStyle :members: Examples -------- To add cover art to a MediaFile: .. code-block:: python from mediafile import MediaFile, Image, ImageType image_file = "cover.jpg" with open(image_file, "rb") as f: cover = f.read() cover = Image(data=cover, desc="album cover", type=ImageType.front) f = MediaFile("file.mp3") f.images = [cover] f.save() To copy tags from one MediaFile to another: .. code-block:: python from mediafile import MediaFile f = MediaFile("file1.mp3") g = MediaFile("file2.mp3") for field in f.fields(): try: setattr(g, field, getattr(f, field)) except: pass g.save()