New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 4 users
Status: Fixed
Closed: Dec 2015
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 1
Type: Bug

Sign in to add a comment
Incorrectly seeks to wrong part of mp3 encoded audio
Reported by, Oct 21 2015 Back to list
UserAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36

Example URL:,js,console,output

Steps to reproduce the problem:
1. Load the above JSBin and Click run with JS
2. Try the links on Chrome (observe the audio)
3. Try the links on Safari, Firefox, Opera etc (observe the audio)

What is the expected behavior?
The audio should commence playback from the correct point in time.

What went wrong?
The audio commences playback from significantly before the correct point in time. The gap seems to increase the further forward you seek.

Did this work before? N/A 

Is it a problem with Flash or HTML5? HTML5

Does this work in other browsers? Yes 

Chrome version: 46.0.2490.71  Channel: stable
OS Version: 10.11
Flash Version: 

I'm using a CBR mp3 encoded at 128mbs. This problem seems to be more apparent on longer pieces of audio.
Comment 1 by, Oct 21 2015
I missed the 'Did this work before?' field. Yes this did work 1 - 2 months ago.
(I work with timed interactive transcripts and so am sensitive to this issue)
Comment 2 by, Oct 21 2015
Here's the same jsbin with the file recoded and on a different domain. (May work better on Firefox for comparison purposes),,js,console,output
Status: Untriaged
Confirmed the bug.
Status: Assigned
this is caused by your CL: Use "fast seek" and usetoc flags for FFmpeg mp3 decoding.
can you take a look?
TLDR: Got this figured out, will start a discussion with ffmpeg folks to get it fixed.

The bug appears/disappears when fast seek flag is set/unset. Under the hood, setting this flag causes us to use the TOC for seeking in this CBR file. The TOC seek algorithm chooses the first timestamp in TOC that is <= requested timestamp. This is why the audio plays out slightly behind where you'd expect. 

The thing is, for CBR files, we don't really need the TOC. IIUC, the constant frame size means we can just interpolate to perfectly compute the byte offset for any time in the file. (We already do this when we have no TOC to work with). 

For VBR, I think it makes sense to prioritize TOC over interpolation since its more accurate. But for CBR I would just always interpolate. I've prototyped this - it fixes the issue we're seeing here. 
Slight correction to what I said before! We can/will fix the issue, but also I want to mention that the file appears to be a little corrupt (which we'll work around with the fix).

"The TOC seek algorithm chooses the first timestamp in TOC that is <= requested timestamp. This is why the audio plays out slightly behind where you'd expect. "

That's not quite right! The TOC seek algorithm *does* choose the first timestamp <= requested, *but* that is *not* why we're hearing audio get behind. 

What typically happens is the chrome rendering pipeline knows you requested time X and observes that the first few frames are a little before X and doesn't actually play those frames. In the case of this bug the renderer is failing to drop the frames because the timestamps on those frames are actually wrong (about 10 seconds behind where they should be). The timestamps are coming from the TOC in the file, so this is where I think the file is a little corrupt. The workaround I mention in 6 works because in bypasses the TOC. 

The corruption is easy to spot. The the first 10 entries are .026 seconds apart each, then the next 90 or so are ~90 seconds apart each. IIUC, because the file is CBR, we should expect that 90 seconds of time equates to a fixed number of bytes. But in the TOC positions I see the offsets skip around between 1681818 and 1123719 bytes (seemingly at random). This is a pretty huge difference in size for 90 seconds, so it seems likely to be a bug. It also explains why the problem is more obvious when seeking later in the file.

 Issue 550914  has been merged into this issue.
Comment 10 by, Nov 18 2015
Chcunnin: I use ffmpeg to create the mp3 file. It's a logger so it creates new files every hour. They all have this issue. How can all mp3 files be corrupt?
Comment 11 by, Nov 18 2015
By the way. I just tested some things. I tried converting like you did in 550914 but omitting the -t 2000 so it converted the entire file. The file size did change (it got larger). But the Chrome audio-element still does the same strange thing with it (request is off, audio keeps playing after 1:00:00).

Also tested this on every other player I could find: WMP, VLC, MPC, iTunes, Firefox, IE/Edge, Safari and they all work just fine no matter which version of the file I use.

To make sure I've used some MP3-error checker tools like MP3Diags and MPEGAudioInfo and they both don't show me any error message.
Hrm... It may be that ffmpeg's toc parsing has a bug. For your file (and the previous file in this bug) I see the difference in byte positions varies widely while the difference in time positions is mostly the same in the later part of the TOC. 

I'll take a closer look at the TOC parsing code and report back. 
Labels: -Pri-2 Pri-1

It turns out that your mp3 TOC is not corrupt (neither was the earlier mp3 in this bug). It looks like the mp3 TOC is designed in such a way that they are really quite imprecise for large files. This means anyone seeking in CBR mp3s is experiencing the same trouble, so I'm bumping to p1.

We really should *never* use the TOC for CBR files since we can just use linear interpolation since all frames are the same size. I will put out a change to make this happen.

For VBR, depending on how variable the bit rate is, TOC may still be more accurate than interpolating. Still not sure it makes sense for the average VBR file though.

I cant find a spec for this anywhere, but I've read the code for ffmpeg, mpg123, and lame. Here's how it works:

- All mp3 TOCs are 100 bytes
- Each byte is read as a uint8, value between 0 - 255.
- The index into this array is the numerator in the ratio: index / 100. The resulting division represents a playback time as a percentage of the total duration (e.g. index 49 represents the 30 second mark in a 1 minute file).
- The value at the given index is the numerator in the ratio: value / 256. The resulting division represents a byte offset as a percentage of the total size of the file.

Lets try to make a TOC. Imagine a file w/ size: 43,200,597 bytes (size of test file from  Issue 550914 )
- lets assume there is a frame that starts exactly 1% of the way through the timeline (not likely)
- assume we know the position of this frame is is 432,006
- offset / filesize = 432,006 / 43,200,597 = 0.010000000694434848. This is 2.560000177775321 / 256.
- we truncate 2.560000177775321 -> 2 since our TOC is just uint8 bytes and store 2 as the value at index 1.

:( that truncation just cost us a ton of precision. If we try to reverse the operations above to get a byte offset again:
- 2 / 256 = 0.0078125
- percent * filesize = 0.0078125 * 43,200,597 = 337504.6640625, which we can truncate / round to 337,504

337,504 is 94,502 bytes less than the original offset we tried to encode. Way off! 

I don't know the history of the xing toc, but I assume it was designed for much much smaller files. If the file were only 1K then the loss in precision would be more in the neighborhood of 1 - 2 bytes. 
Patch in review upstream here:

Will cherry pick when its ready.
Cherry pick:

DEPS roll coming shortly.
Labels: Merge-Request-48
Looks good in Canary. Requesting merge back to 48
Comment 18 by, Dec 7 2015
Labels: -Merge-Request-48 Merge-Review-48 Hotlist-Merge-Review
[Automated comment] DEPS changes referenced in bugdroid comments, needs manual review.
Comment 19 by, Dec 7 2015
Labels: -Merge-Review-48 Merge-Approved-48
Merge approved for M48 (branch 2564), pls merge in!
Labels: -Merge-Approved-48 Merge-Merged
Merged as r81590. Builders are red, but seems to be not related. 
Status: Fixed
Note: the link for r81590 in #20 is bad. My revision number refers to SVN deps for the 2564 src-internal branch.
Comment 22 Deleted
Sign in to add a comment