AVPlayer
has a property called rate
that is meant to control the playback rate. 1.0
is normal speed while values like 2.0
or 5.0
should playback at 2x and 5x respectively.
Whenever I set a playback rate value higher than 1.0
(say 10.0
), the playback is very choppy and it looks like a large number of frames are getting dropped as the player can't keep up.
However, the same values in QuickTime Player (with the same movie), produce smooth playback for rates of 2x, 5x, 10x, 30x and 60x
(as reported by the QuickTime Player).
I created a test OS X application that contains nothing more than an AVPlayerView
and two buttons for setting the playback rate. A rate of 1.0
works as expected, but a rate of 10.0
produces very choppy playback.
However, the AVPlayerView
has an odd quirk in that if you mouse-click on the playback timeline to seek to another location (while it's playing at 10x and choppy), then the AVPlayerView
will "fix" the playback and the movie will be played smoothly at 10x. All it took was clicking on the playback timeline.
Does anyone know how to get smooth playback for rates other than 1x? It's obviously not a hardware problem or a file size problem because both QuickTime Player and AVPlayerView can do it.
Attempts
This question suggests that it might be an audio issue (and indeed both QuickTime Player and AVPlayerView mute the audio when forwarding) but all attempts on my part to either disable all audio tracks, mute all tracks or change the audio pitch algorithm did not seem to make a difference. Playback was still choppy even when there was no audio present.
I've also tried stopping playback and then calling prerollAtRate:completionHandler
with the new rate but that doesn't make a difference either.
What is it that QuickTime Player and AVPlayerView are doing that allows for smooth movie playback at rates of 10x, 30x or even 60x?
This is only a workaround.
When the playback rate is changed from 0.0 to a large value, if this is the first zero-to-nonzero transition in playback rate since the last call to AVPlayer.replaceCurrentItem
, playback is smooth (and audio is automatically muted). It is necessary that this is the first such transition: merely setting the rate to 0.0 first and then to the desired rate does not work.
So, for example, this will produce smooth playback at high speeds:
func setPlayerRate(player: AVPlayer, rate: Float) {
// AVFoundation wants us to do most things on the main queue.
DispatchQueue.main.async {
if (rate == player.rate) {
return
}
if (rate > 2.0 || rate < -2.0) {
let playerItem = player.currentItem
player.replaceCurrentItem(with: nil)
player.replaceCurrentItem(with: playerItem)
player.rate = rate
} else {
// No problems "out of the box" with rates in the range [-2.0,2.0].
player.rate = rate
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With