ACIDCAT . FILE FORMAT REFERENCE

OGG

Xiph.Org Containerpage / segment model
RFC 3533
magic "OggS"
endian little *
container pages + segments
codecs Vorbis / Opus / FLAC

An OGG bitstream is a sequence of pages, each carrying lacing-delimited packet segments; the format is little-endian throughout -- the reverse of MP4 and AIFF. A logical packet may span many pages; the segment table encodes boundaries without explicit lengths. Hover a field to light its bytes, click a + for its table. Color marks kind (see the key). * the one trap: OGG is little-endian everywhere, including all multi-byte fields in the page header.

page structure

Every page in a physical OGG stream has this layout, repeated end-to-end.

page header (fixed)0x00 . 27 bytes . drawn below

capture_pattern through page_segments. The 27-byte fixed portion before the segment table. See the byte map below.

segment tablepage_segments bytes . lacing
countpage_segments lacing bytes, one per segment (each 0-255)
rule255 = this segment is 255 bytes and the packet continues; < 255 = packet ends here
total datasum of all lacing bytes on this page
page datasum(segment_table) bytes . codec payload

Raw codec payload packed continuously. The segment table above tells the decoder where each logical packet ends.

page header

27 bytes. Example: first BOS page, header_type 0x02, granule -1 (no packet completes), serial 1, page 0, one segment.

header type flags

1 byte, bit register. Example: 0x02 -- BOS set, EOS and continued-packet clear. Bits indexed MSB-first.

lacing & packets

The segment table encodes packet boundaries without a separate length field.

packet segmentationlacing model . RFC 3533 s.6
lacing byte0-255; the byte length of that segment's data contribution
packet sizesum of consecutive lacing values belonging to one logical packet
255 rulea value of 255 means the packet spans into the next segment (more data follows)
terminationa value strictly less than 255 ends the packet at that segment boundary
exact multiple of 255a packet whose total size is an exact multiple of 255 bytes appends a trailing 0 lacing byte to signal termination
max page payloadpage_segments is one byte (≤ 255) and each lacing byte is ≤ 255, so a page carries at most 255 × 255 = 65,025 data bytes; a larger packet must span pages
codec identification

The payload of the first (BOS) page carries a codec identification header. A reader identifies the codec before any other decode.

codec header magicBOS payload prefix
Vorbis0x01 followed by "vorbis" (7 bytes total) -- the 0x01 is the Vorbis packet type
Opus"OpusHead" (8 literal ASCII bytes) per RFC 7845
Opus pre_skipu16 LE in OpusHead: samples to discard at the start (encoder priming). Opus always decodes at 48 kHz, so duration = (last_granule − pre_skip) / 48000
FLAC-in-Ogg0x7F followed by "FLAC" (5 bytes), then the native fLaC STREAMINFO block
notea reader identifies the codec from these first bytes of the BOS packet, before decoding anything else; a mismatch is a hard error
the identification header (30 bytes)

Packet type 1. Channels and sample rate live here, not in the page header.

the comment header (24 bytes)

Packet type 3, and the same comment structure FLAC borrowed.

stream organization

Two ways logical streams combine in one physical file. A reader must handle both.

multiplexed vs chainedgrouping . serial numbers
multiplexedseveral logical streams interleaved page by page, each a distinct serial_number (e.g. audio + video); all their BOS pages appear grouped at the very start
chainedwhole logical streams concatenated end to end: a full BOS..EOS sequence, then a fresh BOS..EOS with a new serial_number
the trapacross a chain seam the codec, channel count, and sample rate can all change; a reader that stops at the first EOS misses everything after it