OGG / Vorbis: Complete Audio Format Guide
OGG is a free, open container format developed by the Xiph.Org Foundation. Vorbis is the open-source lossy audio codec most commonly paired with it. Together, OGG/Vorbis represents the fully royalty-free alternative to MP3 — delivering comparable or better audio quality at similar bitrates, with no patent encumbrances.
The OGG Container
OGG is a logical bitstream multiplexing format. A physical OGG stream is divided into pages, which carry data from one or more logical bitstreams (audio, video, metadata, etc.). The page structure is:
| Field | Size | Description |
|---|---|---|
| Capture pattern | 4 bytes | OggS magic bytes |
| Stream structure version | 1 byte | Always 0x00 |
| Header type | 1 byte | 0x02 = BOS (Beginning of Stream), 0x04 = EOS (End of Stream), 0x01 = continuation |
| Granule position | 8 bytes | PCM sample count decoded so far (used for seeking) |
| Bitstream serial number | 4 bytes | Identifies the logical bitstream |
| Page sequence number | 4 bytes | Monotonically increasing per bitstream |
| Checksum | 4 bytes | CRC-32 of the entire page |
| Number of segments | 1 byte | How many lace values follow (max 255) |
| Segment table | 1–255 bytes | Lace values describing packet boundaries |
| Page data | variable | Packed audio/metadata packets |
Packets spanning multiple pages use the continuation bit. A segment table value of 255 means "more data follows in the next segment"; a value < 255 terminates the packet. This lacing scheme allows packets larger than a single page (up to 64 KB × 255 segments).
Vorbis Encoding Pipeline
Vorbis is a transform codec using the MDCT (Modified Discrete Cosine Transform) with overlapping analysis windows:
- Windowing: Input PCM is divided into overlapping blocks of 256 or 4096 samples. Small blocks handle transients; large blocks handle sustained tones — Vorbis switches dynamically.
- MDCT: Transforms each windowed block into 128 or 2048 frequency coefficients.
- Psychoacoustic masking: Noise shaping computes a masking curve; frequency components masked by louder nearby tones are assigned coarser quantisation.
- Floor coding: A piecewise linear approximation of the spectral envelope (floor0 uses LSP polynomials; floor1 uses direct point specification).
- Residue coding: Residuals after floor removal are vector-quantised using a trained codebook (VQ).
- Huffman entropy coding: VQ outputs are entropy-coded using Huffman trees stored in the setup header.
Vorbis Header Packets
A Vorbis stream begins with three mandatory header packets, all on separate OGG pages:
| Header | Content |
|---|---|
| Identification | Magic \x01vorbis, version, channel count, sample rate, bitrate min/nominal/max |
| Comment | \x03vorbis + UTF-8 Vorbis Comment tags (artist, title, etc.) |
| Setup | \x05vorbis + codebooks, floor configurations, residue configurations, mapping, modes |
The setup header contains everything the decoder needs to reconstruct the psychoacoustic model. It can be kilobytes large for high-quality encoders with detailed codebooks.
Vorbis Quality Scale
Unlike MP3 which uses a nominal bitrate (-b:a 128k), Vorbis uses a quality index (-q:a in FFmpeg, -q in oggenc) ranging from -1 to 10:
| Quality | Approx. VBR bitrate | Perceptual quality | Use case |
|---|---|---|---|
| -1 | ~45 kbps | Acceptable speech | Minimal voice streams |
| 0 | ~64 kbps | Good speech | Podcast, voice |
| 1 | ~80 kbps | Acceptable music | Low-bandwidth streaming |
| 2 | ~96 kbps | Good music | Standard mobile |
| 3 | ~112 kbps | Very good | Standard web streaming |
| 4 | ~128 kbps | Excellent | High-quality streaming |
| 5 | ~160 kbps | Transparent | Music distribution |
| 6 | ~192 kbps | Very transparent | High-quality music |
| 8 | ~256 kbps | Near-archival | Audiophile streaming |
| 10 | ~500 kbps | Near-lossless | Reference quality |
FFmpeg OGG/Vorbis Encoding
# Convert WAV to OGG Vorbis at quality 5 (~160 kbps VBR)
ffmpeg -i input.wav -c:a libvorbis -q:a 5 output.ogg
# Specific average bitrate (ABR mode)
ffmpeg -i input.wav -c:a libvorbis -b:a 128k output.ogg
# Extract audio from video as OGG
ffmpeg -i video.mp4 -vn -c:a libvorbis -q:a 4 audio.ogg
# Convert MP3 → OGG without quality loss beyond source
ffmpeg -i source.mp3 -c:a libvorbis -q:a 6 output.ogg
# Batch: convert all WAV files in a directory
for f in *.wav; do
ffmpeg -i "$f" -c:a libvorbis -q:a 5 "${f%.wav}.ogg"
done
# Verify OGG stream info
ffprobe -v quiet -print_format json -show_streams audio.ogg | python -m json.tool
Python OGG/Vorbis Manipulation
from mutagen.oggvorbis import OggVorbis
audio = OggVorbis('track.ogg')
# Stream info (read-only)
print(f"Duration : {audio.info.length:.2f} s")
print(f"Bitrate : {audio.info.bitrate} bps")
print(f"Channels : {audio.info.channels}")
print(f"Sample rate : {audio.info.sample_rate} Hz")
# Read Vorbis Comment tags
print("Title :", audio.get('title', ['(none)'])[0])
print("Artist :", audio.get('artist', ['(none)'])[0])
print("Album :", audio.get('album', ['(none)'])[0])
print("Date :", audio.get('date', ['(none)'])[0])
# Write tags (all values are lists of strings in Vorbis Comment spec)
audio['title'] = ['New Track Title']
audio['artist'] = ['Artist Name']
audio['album'] = ['Album Name']
audio['tracknumber'] = ['04']
audio['date'] = ['2025']
audio['genre'] = ['Electronic']
audio.save()
Parsing OGG Page Headers in Python
import struct
def parse_ogg_pages(path: str, max_pages: int = 10) -> list:
"""Read and describe OGG page headers from a file."""
pages = []
with open(path, 'rb') as f:
for _ in range(max_pages):
magic = f.read(4)
if not magic or magic != b'OggS':
break
ver = struct.unpack('B', f.read(1))[0]
htype = struct.unpack('B', f.read(1))[0]
granule = struct.unpack('<q', f.read(8))[0]
serial = struct.unpack('<I', f.read(4))[0]
seq = struct.unpack('<I', f.read(4))[0]
checksum = struct.unpack('<I', f.read(4))[0]
n_segs = struct.unpack('B', f.read(1))[0]
seg_table = f.read(n_segs)
data_len = sum(seg_table)
f.read(data_len) # skip data
flags = []
if htype & 0x01: flags.append('CONTINUATION')
if htype & 0x02: flags.append('BOS')
if htype & 0x04: flags.append('EOS')
pages.append({
'seq': seq, 'serial': hex(serial),
'granule': granule, 'data_bytes': data_len,
'flags': flags or ['NORMAL']
})
return pages
for pg in parse_ogg_pages('track.ogg'):
print(pg)
OGG/Vorbis vs Other Audio Codecs
| Codec | Container | Royalty-free | ~128 kbps quality | ~64 kbps quality | Browser support |
|---|---|---|---|---|---|
| Vorbis | OGG | Yes | Excellent | Good | Chrome, Firefox, Edge (no Safari) |
| Opus | OGG/WebM | Yes | Excellent | Excellent | All modern browsers |
| MP3 | MP3/MPEG | Free (2017+) | Good | Poor | Universal |
| AAC | M4A/MP4 | Licensed | Excellent | Good | All (native iOS/macOS) |
| FLAC | FLAC/OGG | Yes | Lossless | Lossless | Growing |
Should you use Vorbis or Opus? For new projects, prefer Opus. Vorbis was state-of-the-art when released (~2000) but Opus superseded it in 2012. At any given bitrate, Opus delivers equal or better quality, with dramatically better performance at very low bitrates (below 64 kbps) and ultra-low latency modes for WebRTC. The only reason to choose Vorbis today is legacy compatibility with players that support OGG/Vorbis but not Opus.
Common Pitfalls
- Safari does not support OGG Vorbis. Apple's Safari browser and iOS/macOS system audio do not include a Vorbis decoder. For web audio that must work on Apple devices, use AAC/MP4 or Opus/WebM.
- Avoid ABR Vorbis unless bitrate budgets are fixed. VBR quality mode produces significantly better quality than ABR at equivalent average bitrate because it allocates more bits to complex musical passages.
- Vorbis Comment tags are case-insensitive but conventionally lowercase.
ARTIST,Artist, andartistare the same field; use the lowercase form to maximise compatibility. - Do not copy-encode lossy to lossy. Converting MP3 → OGG at the same quality level will not improve — and likely will degrade — audio quality. Keep originals lossless or encode from the highest-quality source available.
Related conversions
Audio format pairs that come up most often: