Python library for handling audio metadata across multiple formats including MP3, FLAC, MP4, OGG and many others
—
This document covers Mutagen's support for lossless audio compression formats including FLAC, WavPack, TrueAudio, APE (Monkey's Audio), and other lossless codecs. These formats preserve perfect audio quality while providing compression and comprehensive metadata support.
# FLAC format
from mutagen.flac import FLAC, StreamInfo, VCFLACDict, MetadataBlock
from mutagen.flac import SeekTable, SeekPoint, CueSheet, CueSheetTrack, Picture, Padding
from mutagen.flac import Open, delete
# WavPack format
from mutagen.wavpack import WavPack, WavPackInfo
from mutagen.wavpack import Open as WavPackOpen, delete as wavpack_delete
# TrueAudio format
from mutagen.trueaudio import TrueAudio, TrueAudioInfo, EasyTrueAudio
from mutagen.trueaudio import Open as TrueAudioOpen, delete as trueaudio_delete
# APE format (Monkey's Audio)
from mutagen.monkeysaudio import MonkeysAudio, MonkeysAudioInfo
# APEv2 tags (standalone and attached)
from mutagen.apev2 import APEv2, APEv2File, APEItem, APEValue, APETextValue, APEBinaryValue
# Other lossless formats
from mutagen.tak import TAK, TAKInfo
from mutagen.optimfrog import OptimFROG, OptimFROGInfo
# Uncompressed formats
from mutagen.wave import WAVE, WaveInfo
from mutagen.aiff import AIFF, AIFFInfo
# High-resolution formats
from mutagen.dsf import DSF, DSFInfo
from mutagen.dsdiff import DSDIFF, DSDIFFInfoclass FLAC:
"""Free Lossless Audio Codec file with Vorbis Comments.
FLAC provides lossless compression with excellent metadata support through
Vorbis Comments and metadata blocks for pictures, cue sheets, and more.
Attributes:
info: FLAC StreamInfo with technical details
tags: VCFLACDict (Vorbis Comments) container
metadata_blocks: List of all FLAC metadata blocks
filename: Path to the FLAC file
"""
def __init__(self, filename: str) -> None:
"""Load FLAC file and parse metadata blocks.
Args:
filename: Path to FLAC file
Raises:
MutagenError: If file is not valid FLAC or corrupted
"""
def add_tags(self) -> None:
"""Add empty Vorbis Comments block if none exists."""
def clear_pictures(self) -> None:
"""Remove all embedded picture blocks."""
def add_picture(self, picture: Picture) -> None:
"""Add embedded picture metadata block.
Args:
picture: Picture metadata block instance
"""
def save(self, deleteid3=False, padding=None) -> None:
"""Save FLAC metadata and tags.
Args:
deleteid3: Remove ID3 tags if present
padding: Custom padding function or None for default
"""
class StreamInfo:
"""FLAC stream information metadata block.
Contains technical details about the FLAC audio stream.
Attributes:
length: Duration in seconds (float)
bitrate: Average bitrate in bits per second (int)
sample_rate: Sample rate in Hz (int)
channels: Number of audio channels (int)
bits_per_sample: Bit depth (typically 16 or 24)
total_samples: Total number of audio samples
min_blocksize: Minimum block size used
max_blocksize: Maximum block size used
min_framesize: Minimum frame size used
max_framesize: Maximum frame size used
md5_signature: MD5 hash of audio data (bytes)
"""
# Function aliases
Open = FLAC
def delete(filename: str) -> None:
"""Remove FLAC metadata while preserving audio.
Args:
filename: Path to FLAC file
"""
# Usage examples
from mutagen.flac import FLAC
# Load FLAC file
flac_file = FLAC("song.flac")
# Access stream info
info = flac_file.info
print(f"Sample rate: {info.sample_rate} Hz")
print(f"Bit depth: {info.bits_per_sample} bits")
print(f"Channels: {info.channels}")
print(f"Duration: {info.length} seconds")
# Access Vorbis Comments
print(flac_file["TITLE"]) # Title
print(flac_file["ARTIST"]) # Artist
print(flac_file["ALBUM"]) # Album
# Modify tags
flac_file["TITLE"] = ["New Title"]
flac_file["ARTIST"] = ["New Artist"]
flac_file.save()class MetadataBlock:
"""Generic FLAC metadata block.
Base class for all FLAC metadata block types including
StreamInfo, Vorbis Comments, Pictures, CueSheet, etc.
"""
class Picture:
"""FLAC picture metadata block for embedded artwork.
Attributes:
type: Picture type (same as ID3 APIC types)
mime: MIME type string (e.g., 'image/jpeg')
desc: Picture description string
width: Image width in pixels
height: Image height in pixels
depth: Color depth in bits
colors: Number of colors for indexed images
data: Image data bytes
"""
class CueSheet:
"""FLAC cue sheet metadata block.
Contains CD track layout information for audio CDs.
Attributes:
media_catalog_number: CD media catalog number
lead_in: Number of lead-in samples
compact_disc: True if from compact disc
tracks: List of CueSheetTrack instances
"""
class CueSheetTrack:
"""Individual track in FLAC cue sheet.
Attributes:
track_number: Track number (1-99, or 170 for lead-out)
start_offset: Track start offset in samples
isrc: International Standard Recording Code
type: Track type flags
pre_emphasis: Pre-emphasis flag
indexes: List of index points
"""
class SeekTable:
"""FLAC seek table metadata block for fast seeking.
Contains seek points for efficient random access.
Attributes:
seekpoints: List of SeekPoint instances
"""
class SeekPoint:
"""Individual seek point in FLAC seek table.
Attributes:
sample_number: Sample number for this seek point
stream_offset: Byte offset in stream
frame_samples: Number of samples in frame
"""
# Usage examples
from mutagen.flac import FLAC, Picture
# Add embedded artwork
flac_file = FLAC("song.flac")
with open("cover.jpg", "rb") as f:
image_data = f.read()
picture = Picture()
picture.type = 3 # Front cover
picture.mime = "image/jpeg"
picture.desc = "Album Cover"
picture.data = image_data
flac_file.add_picture(picture)
flac_file.save()
# Access all metadata blocks
for block in flac_file.metadata_blocks:
print(f"Block type: {block.__class__.__name__}")class VCFLACDict:
"""Vorbis Comments container for FLAC files.
Dictionary-like interface for FLAC Vorbis Comment tags.
Field names are case-insensitive and support multiple values.
"""
# Common field names (case-insensitive)
# TITLE, ARTIST, ALBUM, DATE, TRACKNUMBER, DISCNUMBER
# GENRE, ALBUMARTIST, COMPOSER, PERFORMER, etc.
# Usage examples
flac_file = FLAC("song.flac")
tags = flac_file.tags
# Standard fields
tags["TITLE"] = ["Song Title"]
tags["ARTIST"] = ["Artist Name"]
tags["ALBUM"] = ["Album Name"]
tags["DATE"] = ["2023"]
tags["TRACKNUMBER"] = ["1"]
tags["DISCNUMBER"] = ["1"]
# Multi-value fields
tags["GENRE"] = ["Rock", "Alternative"]
tags["ARTIST"] = ["Primary Artist", "Featured Artist"]
# Custom fields
tags["CUSTOM_FIELD"] = ["Custom Value"]
# Case insensitive access
tags["title"] = ["Same as TITLE"]
tags["Title"] = ["Same as TITLE"]
flac_file.save()class WavPack:
"""WavPack lossless/hybrid audio file.
Supports both lossless and hybrid (lossy + correction) modes.
Uses APEv2 tags for metadata.
Attributes:
info: WavPackInfo with stream details
tags: APEv2 tag container
filename: Path to WavPack file
"""
class WavPackInfo:
"""WavPack stream information.
Attributes:
length: Duration in seconds
bitrate: Bitrate in bits per second
sample_rate: Sample rate in Hz
channels: Number of channels
bits_per_sample: Bit depth
version: WavPack version
mode: Compression mode info
"""
# Usage examples
from mutagen.wavpack import WavPack
wv_file = WavPack("song.wv")
print(f"Sample rate: {wv_file.info.sample_rate}")
print(f"Mode: {wv_file.info.mode}")
# APEv2 tags
wv_file["Title"] = "Song Title"
wv_file["Artist"] = "Artist Name"
wv_file.save()class TrueAudio:
"""TrueAudio lossless audio file.
Uses ID3v2 tags (like MP3) for metadata.
Attributes:
info: TrueAudioInfo with stream details
tags: ID3 tag container
filename: Path to TrueAudio file
"""
class EasyTrueAudio(TrueAudio):
"""TrueAudio with EasyID3 interface."""
class TrueAudioInfo:
"""TrueAudio stream information.
Attributes:
length: Duration in seconds
bitrate: Bitrate in bits per second
sample_rate: Sample rate in Hz
channels: Number of channels
bits_per_sample: Bit depth
version: TrueAudio version
"""
# Usage examples
from mutagen.trueaudio import TrueAudio, EasyTrueAudio
# Standard interface (uses ID3 frames)
tta_file = TrueAudio("song.tta")
tta_file["TIT2"] = "Song Title" # ID3 frame
tta_file.save()
# Easy interface
easy_tta = EasyTrueAudio("song.tta")
easy_tta["title"] = ["Song Title"] # Normalized name
easy_tta.save()class MonkeysAudio:
"""Monkey's Audio lossless file.
Uses APEv2 tags for metadata.
Attributes:
info: MonkeysAudioInfo with stream details
tags: APEv2 tag container
filename: Path to APE file
"""
class MonkeysAudioInfo:
"""Monkey's Audio stream information.
Attributes:
length: Duration in seconds
bitrate: Bitrate in bits per second
sample_rate: Sample rate in Hz
channels: Number of channels
bits_per_sample: Bit depth
compression_level: Compression level used
version: APE format version
"""
# Usage examples
from mutagen.monkeysaudio import MonkeysAudio
ape_file = MonkeysAudio("song.ape")
print(f"Compression: {ape_file.info.compression_level}")
# APEv2 tags
ape_file["Title"] = "Song Title"
ape_file["Artist"] = "Artist Name"
ape_file.save()class APEv2:
"""APEv2 tag container.
Can be used standalone or attached to audio files.
Dictionary-like interface with case-insensitive keys.
Attributes:
version: APEv2 version (usually 2000)
is_header: True if header is present
is_footer: True if footer is present
read_only: True if tags are read-only
"""
class APEv2File:
"""File with APEv2 tags attached.
Base class for formats that use APEv2 tags.
"""
class APEItem:
"""Individual APEv2 tag item.
Can contain text, binary data, or external references.
Attributes:
key: Tag key name
value: APEValue instance containing data
read_only: True if item is read-only
"""
# Usage examples
from mutagen.apev2 import APEv2
# Standalone APEv2 tags
tags = APEv2("file_with_ape_tags.mp3")
# Text items
tags["Title"] = "Song Title"
tags["Artist"] = "Artist Name"
tags["Album"] = "Album Name"
# Multi-value text
tags["Genre"] = "Rock\0Alternative" # Null-separated
# Custom binary data
tags["CustomData"] = b"Binary content here"
tags.save()class TAK:
"""TAK lossless audio file.
Uses APEv2 tags for metadata.
"""
class TAKInfo:
"""TAK stream information."""
# Usage
from mutagen.tak import TAK
tak_file = TAK("song.tak")
tak_file["Title"] = "Song Title"
tak_file.save()class OptimFROG:
"""OptimFROG lossless audio file.
Uses APEv2 tags for metadata.
"""
class OptimFROGInfo:
"""OptimFROG stream information."""
# Usage
from mutagen.optimfrog import OptimFROG
ofr_file = OptimFROG("song.ofr")
ofr_file["Title"] = "Song Title"
ofr_file.save()class WAVE:
"""WAVE audio file.
Supports ID3v2 tags and RIFF INFO chunks.
"""
class WaveInfo:
"""WAVE stream information.
Attributes:
length: Duration in seconds
bitrate: Bitrate in bits per second
sample_rate: Sample rate in Hz
channels: Number of channels
bits_per_sample: Bit depth
"""
# Usage
from mutagen.wave import WAVE
wave_file = WAVE("song.wav")
print(f"Sample rate: {wave_file.info.sample_rate}")
# Uses ID3v2 tags like MP3
wave_file["TIT2"] = "Song Title"
wave_file.save()class AIFF:
"""Audio Interchange File Format file.
Supports ID3v2 tags.
"""
class AIFFInfo:
"""AIFF stream information."""
# Usage
from mutagen.aiff import AIFF
aiff_file = AIFF("song.aiff")
aiff_file["TIT2"] = "Song Title" # ID3v2 tags
aiff_file.save()class DSF:
"""DSD Stream File (Super Audio CD format).
High-resolution 1-bit audio format.
Uses ID3v2 tags for metadata.
"""
class DSFInfo:
"""DSF stream information.
Attributes:
length: Duration in seconds
bitrate: Bitrate in bits per second
sample_rate: DSD sample rate (typically 2.8MHz or 5.6MHz)
channels: Number of channels
"""
# Usage
from mutagen.dsf import DSF
dsf_file = DSF("song.dsf")
print(f"DSD sample rate: {dsf_file.info.sample_rate}")
# ID3v2 tags
dsf_file["TIT2"] = "Song Title"
dsf_file.save()class DSDIFF:
"""DSD Interchange File Format file.
Another DSD format with different metadata handling.
"""
class DSDIFFInfo:
"""DSDIFF stream information."""
# Usage
from mutagen.dsdiff import DSDIFF
dff_file = DSDIFF("song.dff")
print(f"DSD sample rate: {dff_file.info.sample_rate}")def tag_lossless_file(filename, metadata):
"""Tag lossless audio file with common metadata."""
import mutagen
audio_file = mutagen.File(filename)
if not audio_file:
return False
format_name = audio_file.__class__.__name__
if format_name == "FLAC":
# Vorbis Comments
audio_file["TITLE"] = [metadata.get("title", "")]
audio_file["ARTIST"] = [metadata.get("artist", "")]
audio_file["ALBUM"] = [metadata.get("album", "")]
elif format_name in ["WavPack", "MonkeysAudio", "TAK", "OptimFROG"]:
# APEv2 tags
audio_file["Title"] = metadata.get("title", "")
audio_file["Artist"] = metadata.get("artist", "")
audio_file["Album"] = metadata.get("album", "")
elif format_name in ["TrueAudio", "WAVE", "AIFF", "DSF"]:
# ID3v2 tags
from mutagen.id3 import TIT2, TPE1, TALB
audio_file["TIT2"] = TIT2(encoding=3, text=[metadata.get("title", "")])
audio_file["TPE1"] = TPE1(encoding=3, text=[metadata.get("artist", "")])
audio_file["TALB"] = TALB(encoding=3, text=[metadata.get("album", "")])
audio_file.save()
return True
# Usage
metadata = {
"title": "Song Title",
"artist": "Artist Name",
"album": "Album Name"
}
tag_lossless_file("song.flac", metadata)
tag_lossless_file("song.wv", metadata)
tag_lossless_file("song.tta", metadata)from mutagen.flac import FLAC, Picture
def setup_flac_complete(filename, metadata, cover_path=None):
"""Set up FLAC file with complete metadata and artwork."""
flac_file = FLAC(filename)
# Basic tags
flac_file["TITLE"] = [metadata["title"]]
flac_file["ARTIST"] = [metadata["artist"]]
flac_file["ALBUM"] = [metadata["album"]]
flac_file["DATE"] = [metadata["date"]]
flac_file["TRACKNUMBER"] = [str(metadata["track"])]
flac_file["DISCNUMBER"] = [str(metadata.get("disc", 1))]
# Optional tags
if "albumartist" in metadata:
flac_file["ALBUMARTIST"] = [metadata["albumartist"]]
if "genre" in metadata:
flac_file["GENRE"] = metadata["genre"] if isinstance(metadata["genre"], list) else [metadata["genre"]]
# Add artwork
if cover_path:
with open(cover_path, "rb") as f:
image_data = f.read()
picture = Picture()
picture.type = 3 # Front cover
picture.mime = "image/jpeg"
picture.desc = "Front Cover"
picture.data = image_data
flac_file.clear_pictures() # Remove existing
flac_file.add_picture(picture)
flac_file.save()
print(f"FLAC file tagged: {filename}")
# Usage
metadata = {
"title": "Song Title",
"artist": "Artist Name",
"album": "Album Name",
"date": "2023",
"track": 1,
"disc": 1,
"albumartist": "Album Artist",
"genre": ["Rock", "Alternative"]
}
setup_flac_complete("song.flac", metadata, "cover.jpg")Install with Tessl CLI
npx tessl i tessl/pypi-mutagen