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

ogg-formats.mddocs/

OGG Formats

This document covers Mutagen's support for OGG container-based audio formats including OGG Vorbis, OGG FLAC, OGG Opus, OGG Speex, and OGG Theora. All OGG formats use Vorbis Comments for metadata and share a common container structure.

Imports

# Base OGG container support
from mutagen.ogg import OggPage, OggFileType

# OGG Vorbis
from mutagen.oggvorbis import OggVorbis, OggVorbisInfo
from mutagen.oggvorbis import Open as OggVorbisOpen, delete as oggvorbis_delete

# OGG FLAC  
from mutagen.oggflac import OggFLAC, OggFLACInfo
from mutagen.oggflac import Open as OggFLACOpen, delete as oggflac_delete

# OGG Opus
from mutagen.oggopus import OggOpus, OggOpusInfo
from mutagen.oggopus import Open as OggOpusOpen, delete as oggopus_delete

# OGG Speex
from mutagen.oggspeex import OggSpeex, OggSpeexInfo  
from mutagen.oggspeex import Open as OggSpeexOpen, delete as oggspeex_delete

# OGG Theora (video)
from mutagen.oggtheora import OggTheora, OggTheoraInfo
from mutagen.oggtheora import Open as OggTheoraOpen, delete as oggtheora_delete

# Vorbis Comments (shared by all OGG formats)
from mutagen._vorbis import VCommentDict

OGG Container Basics

Base OGG Support

class OggPage:
    """Individual OGG container page.
    
    OGG files are composed of pages containing packet data.
    Each page has headers with sequence numbers, checksums, and flags.
    
    Attributes:
        version: OGG version (always 0)
        type: Page type flags
        granule_pos: Granule position for timing
        serial: Logical bitstream serial number
        sequence: Page sequence number
        crc: CRC32 checksum
        data: Page payload data
    """

class OggFileType:
    """Base class for OGG-based audio formats.
    
    All OGG formats inherit from this class and use Vorbis Comments
    for metadata storage.
    
    Attributes:
        tags: VCommentDict (Vorbis Comments) container
        info: Format-specific stream information
    """
    
    def add_tags(self) -> None:
        """Add empty Vorbis Comments if none exist."""
    
    def save(self) -> None:
        """Save Vorbis Comments back to OGG file."""
    
    def delete(self) -> None:
        """Remove all Vorbis Comments from file."""

# All OGG formats share Vorbis Comments structure
class VCommentDict:
    """Vorbis Comments dictionary container.
    
    Case-insensitive field names supporting multiple values per field.
    Standard fields include TITLE, ARTIST, ALBUM, DATE, etc.
    """
    
    # Standard field names (case-insensitive)
    STANDARD_FIELDS = [
        "TITLE", "VERSION", "ALBUM", "TRACKNUMBER", "ARTIST", "PERFORMER",
        "COPYRIGHT", "LICENSE", "ORGANIZATION", "DESCRIPTION", "GENRE", 
        "DATE", "LOCATION", "CONTACT", "ISRC", "DISCNUMBER", "ALBUMARTIST",
        "COMPOSER", "LYRICIST", "CONDUCTOR", "REMIXER", "PRODUCER", "ENGINEER"
    ]

OGG Vorbis

OggVorbis Class

class OggVorbis(OggFileType):
    """OGG Vorbis audio file.
    
    Lossy audio compression with high quality and efficient encoding.
    Uses Vorbis Comments for metadata.
    
    Attributes:
        info: OggVorbisInfo with stream details
        tags: VCommentDict (Vorbis Comments) container
        filename: Path to OGG Vorbis file
    """
    
    def __init__(self, filename: str) -> None:
        """Load OGG Vorbis file and parse metadata.
        
        Args:
            filename: Path to .ogg file
            
        Raises:
            MutagenError: If file is not valid OGG Vorbis or corrupted
        """

class OggVorbisInfo:
    """OGG Vorbis stream information.
    
    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)
        bitrate_nominal: Nominal bitrate from headers
        bitrate_minimum: Minimum bitrate (VBR)
        bitrate_maximum: Maximum bitrate (VBR)
        version: Vorbis encoder version
        vendor: Encoder identification string
    """

# Function aliases
Open = OggVorbis

def delete(filename: str) -> None:
    """Remove Vorbis Comments from OGG Vorbis file.
    
    Args:
        filename: Path to OGG Vorbis file
    """

# Usage examples
from mutagen.oggvorbis import OggVorbis

# Load OGG Vorbis file
ogg_file = OggVorbis("song.ogg")

# Access stream info
info = ogg_file.info
print(f"Sample rate: {info.sample_rate} Hz")
print(f"Channels: {info.channels}")
print(f"Bitrate: {info.bitrate} bps")
print(f"Encoder: {info.vendor}")

# Access Vorbis Comments
print(ogg_file["TITLE"])    # Title
print(ogg_file["ARTIST"])   # Artist
print(ogg_file["ALBUM"])    # Album

# Modify tags
ogg_file["TITLE"] = ["New Title"]
ogg_file["ARTIST"] = ["New Artist"]
ogg_file.save()

# Multi-value fields
ogg_file["GENRE"] = ["Rock", "Alternative"]
ogg_file["ARTIST"] = ["Primary Artist", "Featured Artist"]
ogg_file.save()

OGG FLAC

OggFLAC Class

class OggFLAC(OggFileType):
    """OGG-wrapped FLAC audio file.
    
    FLAC lossless compression in OGG container instead of native FLAC.
    Uses Vorbis Comments for metadata (not FLAC metadata blocks).
    
    Attributes:
        info: OggFLACInfo with stream details
        tags: VCommentDict (Vorbis Comments) container
        filename: Path to OGG FLAC file
    """

class OggFLACInfo:
    """OGG FLAC stream information.
    
    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
    """

# Function aliases
Open = OggFLAC

def delete(filename: str) -> None:
    """Remove Vorbis Comments from OGG FLAC file."""

# Usage examples
from mutagen.oggflac import OggFLAC

# Load OGG FLAC file
oggflac_file = OggFLAC("song.oga")

# Stream info (similar to regular FLAC)
info = oggflac_file.info
print(f"Sample rate: {info.sample_rate} Hz")
print(f"Bit depth: {info.bits_per_sample} bits")
print(f"Total samples: {info.total_samples}")

# Vorbis Comments (not FLAC metadata blocks)
oggflac_file["TITLE"] = ["Song Title"]
oggflac_file["ARTIST"] = ["Artist Name"]
oggflac_file.save()

OGG Opus

OggOpus Class

class OggOpus(OggFileType):
    """OGG Opus audio file.
    
    Modern low-latency audio codec optimized for speech and music.
    Excellent quality at low bitrates with Vorbis Comments metadata.
    
    Attributes:
        info: OggOpusInfo with stream details
        tags: VCommentDict (Vorbis Comments) container
        filename: Path to OGG Opus file
    """

class OggOpusInfo:
    """OGG Opus stream information.
    
    Attributes:
        length: Duration in seconds (float)
        bitrate: Bitrate in bits per second (int)
        sample_rate: Original sample rate before encoding (int)
        channels: Number of audio channels (int)
        version: Opus version
        gain: Output gain adjustment in dB
        pre_skip: Pre-skip samples for padding
        vendor: Encoder identification string
    """

# Function aliases
Open = OggOpus

def delete(filename: str) -> None:
    """Remove Vorbis Comments from OGG Opus file."""

# Usage examples
from mutagen.oggopus import OggOpus

# Load OGG Opus file  
opus_file = OggOpus("song.opus")

# Opus-specific info
info = opus_file.info
print(f"Original sample rate: {info.sample_rate} Hz")
print(f"Output gain: {info.gain} dB")
print(f"Pre-skip: {info.pre_skip} samples")
print(f"Encoder: {info.vendor}")

# Standard Vorbis Comments
opus_file["TITLE"] = ["Song Title"]
opus_file["ARTIST"] = ["Artist Name"]
opus_file.save()

OGG Speex

OggSpeex Class

class OggSpeex(OggFileType):
    """OGG Speex audio file.
    
    Speech-optimized lossy compression codec designed for voice.
    Uses Vorbis Comments for metadata.
    
    Attributes:
        info: OggSpeexInfo with stream details
        tags: VCommentDict (Vorbis Comments) container  
        filename: Path to OGG Speex file
    """

class OggSpeexInfo:
    """OGG Speex stream information.
    
    Attributes:
        length: Duration in seconds (float)
        bitrate: Bitrate in bits per second (int)
        sample_rate: Sample rate in Hz (int)
        channels: Number of audio channels (int)
        mode: Speex encoding mode
        vbr: Variable bitrate flag
        version: Speex version
        vendor: Encoder identification string
    """

# Function aliases
Open = OggSpeex

def delete(filename: str) -> None:
    """Remove Vorbis Comments from OGG Speex file."""

# Usage examples
from mutagen.oggspeex import OggSpeex

# Load OGG Speex file
speex_file = OggSpeex("speech.spx")

# Speex-specific info
info = speex_file.info
print(f"Encoding mode: {info.mode}")
print(f"Variable bitrate: {info.vbr}")
print(f"Speex version: {info.version}")

# Vorbis Comments
speex_file["TITLE"] = ["Speech Recording"]
speex_file["ARTIST"] = ["Speaker Name"]
speex_file.save()

OGG Theora (Video)

OggTheora Class

class OggTheora(OggFileType):
    """OGG Theora video file.
    
    Open video codec in OGG container. Supports Vorbis Comments
    for metadata even though it's primarily a video format.
    
    Attributes:
        info: OggTheoraInfo with stream details
        tags: VCommentDict (Vorbis Comments) container
        filename: Path to OGG Theora file
    """

class OggTheoraInfo:
    """OGG Theora stream information.
    
    Attributes:
        length: Duration in seconds (float)
        bitrate: Video bitrate in bits per second (int)
        fps: Frames per second (float)
        width: Video width in pixels (int)
        height: Video height in pixels (int)
        version: Theora version tuple
        vendor: Encoder identification string
    """

# Function aliases
Open = OggTheora

def delete(filename: str) -> None:
    """Remove Vorbis Comments from OGG Theora file."""

# Usage examples
from mutagen.oggtheora import OggTheora

# Load OGG Theora file
theora_file = OggTheora("video.ogv")

# Video-specific info
info = theora_file.info
print(f"Resolution: {info.width}x{info.height}")
print(f"Frame rate: {info.fps} fps")
print(f"Encoder: {info.vendor}")

# Metadata for video
theora_file["TITLE"] = ["Video Title"]
theora_file["DESCRIPTION"] = ["Video description"]
theora_file.save()

Vorbis Comments (Shared Metadata)

All OGG formats use Vorbis Comments for metadata:

# Standard Vorbis Comment fields (case-insensitive)
VORBIS_FIELDS = {
    # Basic metadata
    "TITLE": "Track title",
    "VERSION": "Version of track (e.g. remix info)", 
    "ALBUM": "Album name",
    "TRACKNUMBER": "Track number",
    "ARTIST": "Artist name",
    "PERFORMER": "Performer name",
    "ALBUMARTIST": "Album artist",
    
    # Additional credits
    "COMPOSER": "Composer name",
    "LYRICIST": "Lyricist name", 
    "CONDUCTOR": "Conductor name",
    "REMIXER": "Remixer name",
    "PRODUCER": "Producer name",
    "ENGINEER": "Engineer name",
    
    # Classification
    "GENRE": "Genre classification",
    "DATE": "Date of recording/release",
    "DISCNUMBER": "Disc number in set",
    
    # Technical/legal
    "ORGANIZATION": "Organization/label",
    "COPYRIGHT": "Copyright information",
    "LICENSE": "License information", 
    "ISRC": "International Standard Recording Code",
    "LOCATION": "Recording location",
    "CONTACT": "Contact information",
    
    # Content
    "DESCRIPTION": "Description/comment",
    "LYRICS": "Song lyrics",
}

# Usage examples for any OGG format
ogg_file = OggVorbis("song.ogg")  # or OggFLAC, OggOpus, etc.

# Basic tags
ogg_file["TITLE"] = ["Song Title"]
ogg_file["ARTIST"] = ["Artist Name"]
ogg_file["ALBUM"] = ["Album Name"]
ogg_file["DATE"] = ["2023"]
ogg_file["TRACKNUMBER"] = ["1"]
ogg_file["DISCNUMBER"] = ["1"]

# Multiple values
ogg_file["GENRE"] = ["Rock", "Alternative"] 
ogg_file["ARTIST"] = ["Primary Artist", "Featured Artist"]

# Extended metadata
ogg_file["ALBUMARTIST"] = ["Album Artist"]
ogg_file["COMPOSER"] = ["Composer Name"]
ogg_file["PRODUCER"] = ["Producer Name"]
ogg_file["ORGANIZATION"] = ["Record Label"]
ogg_file["COPYRIGHT"] = ["2023 Copyright Holder"]

# Custom fields (any name allowed)
ogg_file["CUSTOM_FIELD"] = ["Custom Value"]
ogg_file["MOOD"] = ["Happy"]
ogg_file["TEMPO"] = ["Fast"]

# Case insensitive access
ogg_file["title"] = ["Same as TITLE"]
ogg_file["Title"] = ["Same as TITLE"]

ogg_file.save()

# Reading tags
for key, values in ogg_file.items():
    print(f"{key}: {', '.join(values)}")

Practical Examples

Cross-OGG Format Tagging

def tag_ogg_file(filename, metadata):
    """Tag any OGG format file with standard metadata."""
    import mutagen
    
    ogg_file = mutagen.File(filename)
    if not ogg_file or not hasattr(ogg_file, 'tags'):
        return False
    
    # All OGG formats use Vorbis Comments
    if ogg_file.tags is None:
        ogg_file.add_tags()
    
    # Standard fields
    field_mapping = {
        'title': 'TITLE',
        'artist': 'ARTIST',
        'album': 'ALBUM', 
        'date': 'DATE',
        'track': 'TRACKNUMBER',
        'disc': 'DISCNUMBER',
        'genre': 'GENRE',
        'albumartist': 'ALBUMARTIST',
        'composer': 'COMPOSER'
    }
    
    for source_key, vorbis_key in field_mapping.items():
        if source_key in metadata:
            value = metadata[source_key]
            if isinstance(value, list):
                ogg_file[vorbis_key] = value
            else:
                ogg_file[vorbis_key] = [str(value)]
    
    ogg_file.save()
    return True

# Usage with different OGG formats
metadata = {
    'title': 'Song Title',
    'artist': 'Artist Name',
    'album': 'Album Name',
    'date': '2023',
    'track': 1,
    'genre': ['Rock', 'Alternative']
}

tag_ogg_file("song.ogg", metadata)      # OGG Vorbis
tag_ogg_file("song.oga", metadata)      # OGG FLAC  
tag_ogg_file("song.opus", metadata)     # OGG Opus
tag_ogg_file("speech.spx", metadata)    # OGG Speex

OGG Format Detection

def identify_ogg_format(filename):
    """Identify specific OGG format and codec."""
    import mutagen
    
    ogg_file = mutagen.File(filename)
    if not ogg_file:
        return "Unknown"
    
    format_name = ogg_file.__class__.__name__
    format_info = {
        'OggVorbis': 'OGG Vorbis (Lossy)',
        'OggFLAC': 'OGG FLAC (Lossless)', 
        'OggOpus': 'OGG Opus (Low-latency)',
        'OggSpeex': 'OGG Speex (Speech)',
        'OggTheora': 'OGG Theora (Video)'
    }
    
    format_desc = format_info.get(format_name, format_name)
    
    # Additional details
    info = ogg_file.info
    details = {
        'format': format_desc,
        'sample_rate': getattr(info, 'sample_rate', 'N/A'),
        'channels': getattr(info, 'channels', 'N/A'),
        'bitrate': getattr(info, 'bitrate', 'N/A'),
        'duration': getattr(info, 'length', 0)
    }
    
    if hasattr(info, 'vendor'):
        details['encoder'] = info.vendor
    
    return details

# Usage
details = identify_ogg_format("audio.ogg")
print(f"Format: {details['format']}")
print(f"Sample rate: {details['sample_rate']} Hz")
print(f"Bitrate: {details['bitrate']} bps")

Batch OGG Processing

import os
import mutagen

def process_ogg_directory(directory):
    """Process all OGG files in directory."""
    ogg_extensions = ['.ogg', '.oga', '.opus', '.spx', '.ogv']
    
    for filename in os.listdir(directory):
        if any(filename.lower().endswith(ext) for ext in ogg_extensions):
            filepath = os.path.join(directory, filename)
            
            try:
                ogg_file = mutagen.File(filepath)
                if ogg_file and hasattr(ogg_file, 'tags'):
                    
                    # Print current metadata
                    print(f"\n{filename}:")
                    print(f"  Format: {ogg_file.__class__.__name__}")
                    print(f"  Duration: {ogg_file.info.length:.2f}s")
                    
                    if ogg_file.tags:
                        for key, values in ogg_file.tags.items():
                            print(f"  {key}: {', '.join(values)}")
                    else:
                        print("  No metadata found")
                        
            except Exception as e:
                print(f"Error processing {filename}: {e}")

# Usage
process_ogg_directory("/path/to/ogg/files")

Format Comparison

FormatCodecQualityUse CaseContainer
OGG VorbisVorbisHigh quality lossyGeneral musicOGG
OGG FLACFLACLosslessArchival qualityOGG
OGG OpusOpusExcellent at low bitratesStreaming, VoIPOGG
OGG SpeexSpeexSpeech optimizedVoice recordingsOGG
OGG TheoraTheoraVideo codecVideo filesOGG

All formats share:

  • Vorbis Comments for metadata
  • Open source codecs
  • Cross-platform support
  • Streaming capabilities

See Also

  • Mutagen - Main documentation and overview
  • Lossless Audio Formats - Native FLAC and other lossless formats
  • Core Functionality - Base classes and common patterns
  • Easy Interfaces - Simplified cross-format tag access

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