Skip to content

Audio leak on ExoPlayer.pause() #3336

Description

@lubumbax

I have implemented a player app with Kotlin (2.3.21), Jetpack Compose (1.11.2) and Media3 ExoPlayer (1.10.1).

The app has a component that displays the waveform of the track being played, given a "zoom" time-window (e.g. 5 seconds). A visual play-head is locked in the middle of the component, always matching the sample corresponding to ExoPlayer.currentPosition - the waveform scrolls left as the track plays.
Quickly said, I decode tracks with 'miniaudio' and 'FFmpeg' (whichever succeeds first) via C++/JNI and, downmix/summarize samples to a cache and then deliver them to the waveform component when it requests frames as currentPosition progresses.

I am finding it challenging to match the position of the play-head to what the user is hearing.
If I pause the player at a silent region of the track, right before a loud region, I can already hear what's on the loud region.

To explain and isolate this a bit better, I tested with a pure PCM/WAV track that I created with Garage Band.
Clicks 6 sec WAV.wav
Image
The track has a duration of 6000 ms (264600 samples @41000 Hz), 1411 kpbs CBR. It contains 2 "tick" 1/4 notes: at 2000 ms and at 4000 ms.

I load the track in my app and play it.
Then I pause it right before the play-head reaches the first note.
ExoPlayer reports a currentPosition of 1909 ms which is right before the "tick" (almost 100 ms ahead of it!), but I can clearly hear the "tick":

Image

Note that the waveform component is rendering the part of the wafeform precisely matching currentPosition.

Next, in order to resume playing, I first exoPlayer.seekTo(1909) then exoPlayer.play(). This time I can hear the "tick" but not entirely. It sounds more like "_ick", like if it had started from 2010 ms loosing the "attack" (but logging is telling us that currentPosition is progressing from 1909).
The reason I call seekTo() is because if I don't, sometimes I observe play() resuming from like 1980 ms (so like 70 ms from where it paused), but I hear what's way past 2000 ms (I hear like "___k").

Thus, It looks like there are at least 100 ms of frames "leaked to the speaker" on exoPlayer.pause(). I am testing with a Sasung Galaxy S23 Ultra. I have observed audio "leakage" of up to 150 ms, but usually it is of about 50~80 ms.
Is there anything that can be done in order to mitigate that?
Ideally, it would be great if ExoPlayer stopped playing audio at the point where it is asked to .pause() and resumed right from where it was paused.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions