CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-mutagen

Python library for handling audio metadata across multiple formats including MP3, FLAC, MP4, OGG and many others

Pending
Overview
Eval results
Files

lossless-formats.mddocs/

Lossless Audio Formats

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.

Imports

# 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, DSDIFFInfo

FLAC (Free Lossless Audio Codec)

FLAC Class

class 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()

FLAC Metadata Blocks

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__}")

Vorbis Comments in FLAC

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()

WavPack

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()

TrueAudio

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()

APE (Monkey's Audio)

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()

APEv2 Tags

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()

Other Lossless Formats

TAK (Tom's lossless Audio Kompressor)

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()

OptimFROG

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()

Uncompressed Formats

WAVE Files

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()

AIFF Files

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()

High-Resolution Formats

DSF (DSD Stream File)

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()

DSDIFF (DSD Interchange File Format)

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}")

Practical Examples

Cross-Format Lossless Tagging

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)

FLAC with Complete 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")

See Also

  • Mutagen - Main documentation and overview
  • MP3 and ID3 Tags - MP3 format and ID3 tagging
  • Container Formats - MP4, ASF/WMA containers
  • OGG Formats - OGG-based audio formats

Install with Tessl CLI

npx tessl i tessl/pypi-mutagen

docs

container-formats.md

core-functionality.md

easy-interfaces.md

index.md

lossless-formats.md

mp3-id3.md

ogg-formats.md

tile.json