Variable speed playback with ExoPlayer

Andrew Lewis
AndroidX Media3
Published in
2 min readApr 26, 2017

ExoPlayer 2.4 is the first release to support playback speed adjustment back to Android Jelly Bean (API level 16). This post explains how to use the new functionality and gives some background on its implementation.

Playback speed adjustment can be useful feature for apps that play spoken content, like podcast players. ExoPlayer previously exposed platform support for setting the audio playback speed, but this was limited to devices running Android Marshmallow (API level 23) onward. The new functionality works on all API levels supported by ExoPlayer.

To change the playback speed, call ExoPlayer.setPlaybackParameters passing in a PlaybackParameters instance with the required speed. As noted in the method’s Javadoc, setting the playback parameters is not always possible. For example, the speed can’t be changed when the player is outputting encoded surround sound via HDMI passthrough.

Setting the playback speed is an asynchronous operation, because any audio already written to the AudioTrack’s internal buffer needs to be played before the speed change takes effect. There’s a new event listener method, onPlaybackParametersChanged, which will be called at the point when audio starts playing with new parameters. There is also a getPlaybackParameters method in case you need to find out what parameters are currently in use.

Internally, variable speed playback is implemented using an AudioProcessor. ExoPlayer’s AudioTrack applies a chain of processors to PCM audio before it’s output. The audio processor uses the Java version of the Sonic library by Bill Cox to process the audio signal.

If you’re testing the feature using a debuggable APK on a device running Android Marshmallow or earlier, you may find that speed-adjusted audio playback is not smooth. The reason is that the Java version of Sonic heavily relies on bounds-checking elimination for efficiency, but this optimization is only applied on release APKs. If you’re seeing this problem, please test on a release APK (and see this thread for more information). From Android Nougat the optimization applies even on debuggable builds.

We have switched to using ExoPlayer’s bundled variable playback speed functionality for all API levels to keep the implementation simple and ensure consistent behavior. The platform’s speed adjustment feature uses the native version of Sonic, but the Java and native versions have similar performance.

In the future we plan to make ExoPlayer’s LoadControl and adaptive track selection logic take into account the current playback speed, and improve handling of speed adjustment when playing live streams.

Please file an issue if you have any problems with speed adjustment, and feel free to reply with any other comments below. Thanks!

--

--