I'm trying to find a way to move to required position in the track without loading all file into memory. And without using vorbisfile
, because the file is stored in the remote server. I read the paragraph in documentation about seeking but couldn't understand it.
How to seek in ogg vorbis file without loading all file into memory?
2.8k Views Asked by AudioBubble AtThere are 2 best solutions below

If the remote server lets you use HTTP GET's with Range headers, you can "fake" the file access by sending a bunch of requests for the different parts just like you would for a local file...
ASSUMING: The file is Ogg-encapsulated and ONLY has the Vorbis stream in it...
- Do an HTTP HEAD request to get the total length of the file
- GET the first 4KB of the file and "sync" the Vorbis headers. You might need to get more data to complete this.
- GET the last 4KB of the file and "sync" the last Ogg page header to get the total sample count
- Do the spec-described bi-section search, substituting HTTP GET w/ Range in place of fseek / fread
If you do it right, seeking should transfer less than 100KB in most cases.
UPDATE:
The bi-section search is a bit non-intuitive... The idea is to jump around in the file looking for the correct page, but every jump is "informed" by the previous jumps and the current page... An example is probably best:
To seek to sample 300,000 in a file having 1,000,000 samples (I'm assuming we're on step 4 above):
- Seek physical file to {fileStream.Length * .3}
- Read forward until you find an Ogg Page
- Check that the page is part of the Vorbis stream in question
- If not, go to next Ogg Page & go to step 3
- Check the granule position
- If not the right page, seek physical file to {current position + ((300000 - granule position) / 1000000) * fileStream.Length} & go to step 2
- You've found the right page, but may need to move back a page to get the "pre-roll"... Vorbis requires 1 packet to be decoded before the desired packet.
There are probably better algorithms for this, but that's the basic idea.
Remember, granule position is the sample count at the END of the page, so when you find the correct page its granule position will be slightly larger than your target.
Seeking ogg files is hard.
List of things to understand
You will need this function
In my code below, I will add another layer which is essentially the file buffer in addition to the ogg page and ogg packet. Essentially, my code only bisects the first synced end page of each file buffer.
When I cannot find a ogg_page_sync, my code creates a second block cursor to load the next 4k file buffer until I either find the page sync or surpasses the boundaries.
When you are done, you essentially backtrack the ogg_pages until you find the desired ogg_packet.
Here is a trick to calculate the timestamp with serially incremented packets
https://xiph.org/ogg/doc/libogg/reference.html
https://github.com/xiph/theora/blob/master/examples/player_example.c
https://xiph.org/vorbis/doc/libvorbis/reference.html
https://xkcd.com/979/
https://xiph.org/oggz/doc/group__basics.html