Ogg leaves the meaning of a page’s 64-bit granule position to the codec. It marks a point in time at the end of the last packet finished on the page, and a page where no packet ends has the value −1 (all bits set), so a reader can seek without decoding.
By kind of stream
| Stream | Meaning |
|---|---|
| Vorbis | the number of PCM samples (per channel) decoded by the end of the page |
| Opus | the number of samples at 48 kHz decoded by the end of the page, whatever the input rate was. The header’s pre-skip must be subtracted to get the time |
| Speex | the number of samples, at the sample rate of the header |
| FLAC | the number of the sample at the end of the last frame finished on the page |
| Theora | a key frame number and an inter-frame count: (keyframe << KFGSHIFT) + frames since it, where KFGSHIFT comes from the Theora identification header |
Working out time
A file’s playing time is the last granule position of the stream (less any pre-skip for Opus) divided by the sample rate. For Vorbis and Opus the last page may give a granule position that is smaller than what the last packet decodes to: the spare samples at the end are dropped. A stream need not start at 0: a stream made by cutting another can start at any position.
Pages without a position
A granule position of −1 can only be on a page where no packet ends, such as the middle of a very long packet. Readers use the nearest page either side of it when seeking.